From 8428b25939d39711e732eeb3928e8a8e64aad8a9 Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Mon, 26 Oct 2009 00:10:23 +0100 Subject: Add llRotLookat pt1. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 39 ++++++++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 12 ++++ .../BasicPhysicsPlugin/BasicPhysicsActor.cs | 20 ++++++ .../BulletDotNETPlugin/BulletDotNETCharacter.cs | 6 ++ .../Physics/BulletDotNETPlugin/BulletDotNETPrim.cs | 5 ++ .../Region/Physics/BulletXPlugin/BulletXPlugin.cs | 20 ++++++ OpenSim/Region/Physics/Manager/PhysicsActor.cs | 13 +++- OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 22 ++++++ OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs | 4 +- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 83 ++++++++++++++++------ OpenSim/Region/Physics/POSPlugin/POSCharacter.cs | 21 ++++++ OpenSim/Region/Physics/POSPlugin/POSPrim.cs | 20 ++++++ OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs | 44 ++++++++++++ .../Shared/Api/Implementation/LSL_Api.cs | 18 +++-- 14 files changed, 296 insertions(+), 31 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 69b3ded..fff807a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1727,6 +1727,45 @@ namespace OpenSim.Region.Framework.Scenes } } + public void rotLookAt(Quaternion target, float strength, float damping) + { + SceneObjectPart rootpart = m_rootPart; + if (rootpart != null) + { + if (IsAttachment) + { + /* + ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); + if (avatar != null) + { + Rotate the Av? + } */ + } + else + { + if (rootpart.PhysActor != null) + { + rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); + rootpart.PhysActor.APIDStrength = strength; + rootpart.PhysActor.APIDDamping = damping; + rootpart.PhysActor.APIDActive = true; + } + } + } + } + public void stopLookAt() + { + SceneObjectPart rootpart = m_rootPart; + if (rootpart != null) + { + if (rootpart.PhysActor != null) + { + rootpart.PhysActor.APIDActive = false; + } + } + + } + /// /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 32171a0..5f46f6f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2187,6 +2187,11 @@ if (m_shape != null) { ParentGroup.HasGroupChanged = true; ScheduleFullUpdate(); } + + public void RotLookAt(Quaternion target, float strength, float damping) + { + m_parentGroup.rotLookAt(target, strength, damping); + } /// /// Schedules this prim for a full update @@ -2662,6 +2667,13 @@ if (m_shape != null) { SetText(text); } + public void StopLookAt() + { + m_parentGroup.stopLookAt(); + + m_parentGroup.ScheduleGroupForTerseUpdate(); + } + public void StopMoveToTarget() { m_parentGroup.stopMoveToTarget(); diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs index 8d8b3fe..2b905b6 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs @@ -307,6 +307,26 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin set { return; } } + public override Quaternion APIDTarget + { + set { return; } + } + + public override bool APIDActive + { + set { return; } + } + + public override float APIDStrength + { + set { return; } + } + + public override float APIDDamping + { + set { return; } + } + public override void SubscribeEvents(int ms) { } diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs index 8da9687..d7aed3c 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs @@ -627,6 +627,12 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { set { return; } } + + public override Quaternion APIDTarget { set { return; } } + public override bool APIDActive { set { return; } } + public override float APIDStrength { set { return; } } + public override float APIDDamping { set { return; } } + /// /// Adds the force supplied to the Target Velocity diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs index f22ea71..977b463 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs @@ -566,6 +566,11 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } public override float PIDHoverTau { set { m_PIDHoverTau = value; } } + public override Quaternion APIDTarget { set { return; } } + public override bool APIDActive { set { return; } } + public override float APIDStrength { set { return; } } + public override float APIDDamping { set { return; } } + public override void AddForce(PhysicsVector force, bool pushforce) { diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs index abed8df..14b8f39 100644 --- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs +++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs @@ -1236,6 +1236,26 @@ namespace OpenSim.Region.Physics.BulletXPlugin public override PIDHoverType PIDHoverType { set { return; } } public override float PIDHoverTau { set { return; } } + public override OpenMetaverse.Quaternion APIDTarget + { + set { return; } + } + + public override bool APIDActive + { + set { return; } + } + + public override float APIDStrength + { + set { return; } + } + + public override float APIDDamping + { + set { return; } + } + public override void SubscribeEvents(int ms) { diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 7603131..566746a 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -230,7 +230,12 @@ namespace OpenSim.Region.Physics.Manager public abstract PIDHoverType PIDHoverType { set;} public abstract float PIDHoverTau { set;} - + // For RotLookAt + public abstract Quaternion APIDTarget { set;} + public abstract bool APIDActive { set;} + public abstract float APIDStrength { set;} + public abstract float APIDDamping { set;} + public abstract void AddForce(PhysicsVector force, bool pushforce); public abstract void AddAngularForce(PhysicsVector force, bool pushforce); public abstract void SetMomentum(PhysicsVector momentum); @@ -463,6 +468,12 @@ namespace OpenSim.Region.Physics.Manager public override bool PIDHoverActive { set { return; } } public override PIDHoverType PIDHoverType { set { return; } } public override float PIDHoverTau { set { return; } } + + public override Quaternion APIDTarget { set { return; } } + public override bool APIDActive { set { return; } } + public override float APIDStrength { set { return; } } + public override float APIDDamping { set { return; } } + public override void SetMomentum(PhysicsVector momentum) { diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index 71ace16..8272083 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -1205,6 +1205,28 @@ namespace OpenSim.Region.Physics.OdePlugin public override bool PIDHoverActive { set { return; } } public override PIDHoverType PIDHoverType { set { return; } } public override float PIDHoverTau { set { return; } } + + public override Quaternion APIDTarget + { + set { return; } + } + + public override bool APIDActive + { + set { return; } + } + + public override float APIDStrength + { + set { return; } + } + + public override float APIDDamping + { + set { return; } + } + + public override void SubscribeEvents(int ms) { diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs index 467eba0..8b57f06 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs @@ -119,7 +119,7 @@ namespace OpenSim.Region.Physics.OdePlugin private float m_VhoverEfficiency = 0f; private float m_VhoverTimescale = 0f; private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height - private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. + private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle. // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. @@ -478,7 +478,7 @@ namespace OpenSim.Region.Physics.OdePlugin Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object m_dir *= rotq; // apply obj rotation to velocity vector - // add Gravity andBuoyancy + // add Gravity and Buoyancy // KF: So far I have found no good method to combine a script-requested // .Z velocity and gravity. Therefore only 0g will used script-requested // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index f59f0ae..e1bf996 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -1,15 +1,4 @@ /* - * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -34,6 +23,18 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces + * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: + * ODEPrim.cs contains methods dealing with Prim editing, Prim + * characteristics and Kinetic motion. + * ODEDynamics.cs contains methods dealing with Prim Physical motion + * (dynamics) and the associated settings. Old Linear and angular + * motors for dynamic motion have been replace with MoveLinear() + * and MoveAngular(); 'Physical' is used only to switch ODE dynamic + * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to + * switch between 'VEHICLE' parameter use and general dynamics + * settings use. */ using System; using System.Collections.Generic; @@ -82,6 +83,14 @@ namespace OpenSim.Region.Physics.OdePlugin private float PID_D = 35f; private float PID_G = 25f; private bool m_usePID = false; + + private Quaternion m_APIDTarget = new Quaternion(); + private float m_APIDStrength = 0.5f; + private float m_APIDDamping = 0.5f; + + private float APID_D = 35f; + private float APID_G = 25f; + private bool m_useAPID = false; // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), // and are for non-VEHICLES only. @@ -93,7 +102,7 @@ namespace OpenSim.Region.Physics.OdePlugin private float m_targetHoverHeight = 0f; private float m_groundHeight = 0f; private float m_waterHeight = 0f; - private float m_buoyancy = 0f; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. + private float m_buoyancy = 0f; //Set by llSetBuoyancy(), for non-vehicles. // private float m_tensor = 5f; private int body_autodisable_frames = 20; @@ -1586,21 +1595,18 @@ Console.WriteLine(" JointCreateFixed"); //m_log.Info(m_collisionFlags.ToString()); - //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. - // would come from SceneObjectPart.cs, public void SetBuoyancy(float fvalue) , PhysActor.Buoyancy = fvalue; ?? + //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle. // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up - // gravityz multiplier = 1 - m_buoyancy - fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; + // NB Prims in ODE are no subject to global gravity + fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass if (m_usePID) { //Console.WriteLine("PID " + m_primName); - // KF - this is for object move? eg. llSetPos() ? + // KF - this is for object MoveToTarget. + //if (!d.BodyIsEnabled(Body)) //d.BodySetForce(Body, 0f, 0f, 0f); - // If we're using the PID controller, then we have no gravity - //fz = (-1 * _parent_scene.gravityz) * m_mass; //KF: ?? Prims have no global gravity,so simply... - fz = 0f; // no lock; for now it's only called from within Simulate() @@ -1744,8 +1750,37 @@ Console.WriteLine(" JointCreateFixed"); // We're flying and colliding with something fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); } - } + } // end m_useHoverPID && !m_usePID + + if (m_useAPID) + { + // RotLookAt, apparently overrides all other rotation sources. Inputs: + // Quaternion m_APIDTarget + // float m_APIDStrength // perhaps ratio other forces to lookat force? + // float m_APIDDamping //'seconds to critically damps in'[sic] + // Factors: + // float APID_D + // float APID_G + + // get present body rotation + d.Quaternion rot = d.BodyGetQuaternion(Body); + Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); + Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget; + float diff_angle; + Vector3 diff_axis; + rot_diff.GetAxisAngle(out diff_axis, out diff_angle); + diff_axis.Normalize(); + PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z); + float RLAservo = timestep / m_APIDDamping; + rotforce = rotforce * RLAservo * m_mass; + d.BodyAddTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); + + // d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); + + + } // end m_useAPID + fx *= m_mass; fy *= m_mass; //fz *= m_mass; @@ -2778,6 +2813,12 @@ Console.WriteLine(" JointCreateFixed"); } public override bool PIDActive { set { m_usePID = value; } } public override float PIDTau { set { m_PIDTau = value; } } + + // For RotLookAt + public override Quaternion APIDTarget { set { m_APIDTarget = value; } } + public override bool APIDActive { set { m_useAPID = value; } } + public override float APIDStrength { set { m_APIDStrength = value; } } + public override float APIDDamping { set { m_APIDDamping = value; } } public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } public override bool PIDHoverActive { set { m_useHoverPID = value; } } diff --git a/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs b/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs index 35fc616..135f49e 100644 --- a/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs +++ b/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs @@ -307,6 +307,27 @@ namespace OpenSim.Region.Physics.POSPlugin { set { return; } } + + public override Quaternion APIDTarget + { + set { return; } + } + + public override bool APIDActive + { + set { return; } + } + + public override float APIDStrength + { + set { return; } + } + + public override float APIDDamping + { + set { return; } + } + public override void SubscribeEvents(int ms) { diff --git a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs index b50364b..4521dce 100644 --- a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs +++ b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs @@ -302,6 +302,26 @@ namespace OpenSim.Region.Physics.POSPlugin { set { return; } } + public override Quaternion APIDTarget + { + set { return; } + } + + public override bool APIDActive + { + set { return; } + } + + public override float APIDStrength + { + set { return; } + } + + public override float APIDDamping + { + set { return; } + } + public override void SubscribeEvents(int ms) { diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs index e7d989c..b3bf70b 100644 --- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs +++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs @@ -500,6 +500,28 @@ namespace OpenSim.Region.Physics.PhysXPlugin public override bool PIDHoverActive { set { return; } } public override PIDHoverType PIDHoverType { set { return; } } public override float PIDHoverTau { set { return; } } + + public override Quaternion APIDTarget + { + set { return; } + } + + public override bool APIDActive + { + set { return; } + } + + public override float APIDStrength + { + set { return; } + } + + public override float APIDDamping + { + set { return; } + } + + public override void SubscribeEvents(int ms) { @@ -782,6 +804,28 @@ namespace OpenSim.Region.Physics.PhysXPlugin public override bool PIDHoverActive { set { return; } } public override PIDHoverType PIDHoverType { set { return; } } public override float PIDHoverTau { set { return; } } + + public override Quaternion APIDTarget + { + set { return; } + } + + public override bool APIDActive + { + set { return; } + } + + public override float APIDStrength + { + set { return; } + } + + public override float APIDDamping + { + set { return; } + } + + public override void SubscribeEvents(int ms) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 11f255f..1dc20ff 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2694,11 +2694,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Orient the object to the angle calculated llSetRot(rot); } + + public void llRotLookAt(LSL_Rotation target, double strength, double damping) + { + m_host.AddScriptLPS(1); +// NotImplemented("llRotLookAt"); + m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); + + } + public void llStopLookAt() { m_host.AddScriptLPS(1); - NotImplemented("llStopLookAt"); +// NotImplemented("llStopLookAt"); + m_host.StopLookAt(); } public void llSetTimerEvent(double sec) @@ -3042,12 +3052,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); } - public void llRotLookAt(LSL_Rotation target, double strength, double damping) - { - m_host.AddScriptLPS(1); - NotImplemented("llRotLookAt"); - } - public LSL_Integer llStringLength(string str) { m_host.AddScriptLPS(1); -- cgit v1.1 From a81a16f22f7af6d102f365f69a50c5d201ae8362 Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Tue, 27 Oct 2009 19:56:39 +0100 Subject: llRotLookAt Pt 2 --- OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs | 34 ++++++++------- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 55 +++++++++++++++---------- 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs index 8b57f06..0c168c6 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs @@ -1,16 +1,4 @@ /* - * Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. - * * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -35,6 +23,19 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces + * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: + * ODEPrim.cs contains methods dealing with Prim editing, Prim + * characteristics and Kinetic motion. + * ODEDynamics.cs contains methods dealing with Prim Physical motion + * (dynamics) and the associated settings. Old Linear and angular + * motors for dynamic motion have been replace with MoveLinear() + * and MoveAngular(); 'Physical' is used only to switch ODE dynamic + * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to + * switch between 'VEHICLE' parameter use and general dynamics + * settings use. + * */ using System; @@ -66,8 +67,8 @@ namespace OpenSim.Region.Physics.OdePlugin // private OdeScene m_parentScene = null; private IntPtr m_body = IntPtr.Zero; - private IntPtr m_jointGroup = IntPtr.Zero; - private IntPtr m_aMotor = IntPtr.Zero; +// private IntPtr m_jointGroup = IntPtr.Zero; +// private IntPtr m_aMotor = IntPtr.Zero; // Vehicle properties @@ -560,6 +561,7 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body */ +//if(frcount == 0) Console.WriteLine("MoveAngular "); // Get what the body is doing, this includes 'external' influences d.Vector3 angularVelocity = d.BodyGetAngularVel(Body); @@ -614,7 +616,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Error is 0 (no error) to +/- 2 (max error) // scale it by VAservo verterr = verterr * VAservo; -//if(frcount == 0) Console.WriteLine("VAerr=" + verterr); +if(frcount == 0) Console.WriteLine("VAerr=" + verterr); // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. @@ -635,7 +637,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Deflection section tba // Sum velocities - m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection + m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // tba: + bank + deflection if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) { diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index e1bf996..93c9a44 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -87,9 +87,6 @@ namespace OpenSim.Region.Physics.OdePlugin private Quaternion m_APIDTarget = new Quaternion(); private float m_APIDStrength = 0.5f; private float m_APIDDamping = 0.5f; - - private float APID_D = 35f; - private float APID_G = 25f; private bool m_useAPID = false; // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), @@ -192,6 +189,9 @@ namespace OpenSim.Region.Physics.OdePlugin private ODEDynamics m_vehicle; internal int m_material = (int)Material.Wood; + + private int frcount = 0; // Used to limit dynamics debug output to + public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size, Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) @@ -1563,9 +1563,14 @@ Console.WriteLine(" JointCreateFixed"); float fy = 0; float fz = 0; + frcount++; // used to limit debug comment output + if (frcount > 100) + frcount = 0; if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. { +if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_vehicle.Type + + " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); if (m_vehicle.Type != Vehicle.TYPE_NONE) { // 'VEHICLES' are dealt with in ODEDynamics.cs @@ -1573,7 +1578,6 @@ Console.WriteLine(" JointCreateFixed"); } else { -//Console.WriteLine("Move " + m_primName); if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 // NON-'VEHICLES' are dealt with here if (d.BodyIsEnabled(Body) && !m_angularlock.IsIdentical(PhysicsVector.Zero, 0.003f)) @@ -1602,7 +1606,7 @@ Console.WriteLine(" JointCreateFixed"); if (m_usePID) { -//Console.WriteLine("PID " + m_primName); +//if(frcount == 0) Console.WriteLine("PID " + m_primName); // KF - this is for object MoveToTarget. //if (!d.BodyIsEnabled(Body)) @@ -1741,7 +1745,7 @@ Console.WriteLine(" JointCreateFixed"); d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); d.BodySetLinearVel(Body, vel.X, vel.Y, 0); d.BodyAddForce(Body, 0, 0, fz); - return; + //KF this prevents furthur motions return; } else { @@ -1756,13 +1760,16 @@ Console.WriteLine(" JointCreateFixed"); { // RotLookAt, apparently overrides all other rotation sources. Inputs: // Quaternion m_APIDTarget - // float m_APIDStrength // perhaps ratio other forces to lookat force? - // float m_APIDDamping //'seconds to critically damps in'[sic] + // float m_APIDStrength // From SL experiments, this is the time to get there + // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly + // Also in SL the mass of the object has no effect on time to get there. // Factors: - // float APID_D - // float APID_G - +//if(frcount == 0) Console.WriteLine("APID "); // get present body rotation + float limit = 1.0f; + float scaler = 50f; // adjusts damping time + float RLAservo = 0f; + d.Quaternion rot = d.BodyGetQuaternion(Body); Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget; @@ -1770,15 +1777,21 @@ Console.WriteLine(" JointCreateFixed"); Vector3 diff_axis; rot_diff.GetAxisAngle(out diff_axis, out diff_angle); diff_axis.Normalize(); - PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z); - float RLAservo = timestep / m_APIDDamping; - rotforce = rotforce * RLAservo * m_mass; - d.BodyAddTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); - - // d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); - - - + if(diff_angle > 0.01f) // diff_angle is always +ve + { +// PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z); + Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z); + rotforce = rotforce * rotq; + if(diff_angle > limit) diff_angle = limit; // cap the rotate rate +// RLAservo = timestep / m_APIDStrength * m_mass * scaler; + // rotforce = rotforce * RLAservo * diff_angle ; + // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); + RLAservo = timestep / m_APIDStrength * scaler; + rotforce = rotforce * RLAservo * diff_angle ; + d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); +//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); + } +if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); } // end m_useAPID fx *= m_mass; @@ -2674,7 +2687,7 @@ Console.WriteLine(" JointCreateFixed"); //outofBounds = true; } - float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)); +// float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)); //Console.WriteLine("Adiff " + m_primName + " = " + Adiff); if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) -- cgit v1.1 From 28aa8010b2b47b73c6b867ff8f6284f98f12f37a Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 15 Nov 2009 21:38:38 +0100 Subject: - Lower TIME_MS_TOLERANCE to 200ms - Allow m_updateFlag to be reset to 0 in the event of a terse update being rejected - Re-add a synchronous SendTo for certain types of packets --- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 24 ++++++++++++++++++++-- .../Region/ClientStack/LindenUDP/OpenSimUDPBase.cs | 18 ++++++++++++++++ .../Region/ClientStack/LindenUDP/OutgoingPacket.cs | 4 +++- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 18 ++++++---------- 4 files changed, 49 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index c773c05..0b05ed9 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -399,6 +399,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Queue or Send OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); + outgoingPacket.Type = type; if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) SendPacketFinal(outgoingPacket); @@ -510,6 +511,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte flags = buffer.Data[0]; bool isResend = (flags & Helpers.MSG_RESENT) != 0; bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; + bool sendSynchronous = false; LLUDPClient udpClient = outgoingPacket.Client; if (!udpClient.IsConnected) @@ -565,9 +567,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (isReliable) Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength); - // Put the UDP payload on the wire - AsyncBeginSend(buffer); + //Some packet types need to be sent synchonously. + //Sorry, i know it's not optimal, but until the LL client + //manages packets correctly and re-orders them as required, this is necessary. + + if (outgoingPacket.Type == PacketType.ImprovedTerseObjectUpdate + || outgoingPacket.Type == PacketType.ChatFromSimulator + || outgoingPacket.Type == PacketType.ObjectUpdate + || outgoingPacket.Type == PacketType.LayerData) + { + sendSynchronous = true; + } + // Put the UDP payload on the wire + if (sendSynchronous == true) + { + SyncBeginSend(buffer); + } + else + { + AsyncBeginSend(buffer); + } // Keep track of when this packet was sent out (right now) outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; } diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs index d2779ba..63579ac 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs @@ -246,6 +246,24 @@ namespace OpenMetaverse } } + public void SyncBeginSend(UDPPacketBuffer buf) + { + if (!m_shutdownFlag) + { + try + { + m_udpSocket.SendTo( + buf.Data, + 0, + buf.DataLength, + SocketFlags.None, + buf.RemoteEndPoint); + } + catch (SocketException) { } + catch (ObjectDisposedException) { } + } + } + public void AsyncBeginSend(UDPPacketBuffer buf) { if (!m_shutdownFlag) diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs index 1a1a1cb..7dc42d3 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs @@ -28,6 +28,7 @@ using System; using OpenSim.Framework; using OpenMetaverse; +using OpenMetaverse.Packets; namespace OpenSim.Region.ClientStack.LindenUDP { @@ -52,7 +53,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public int TickCount; /// Category this packet belongs to public ThrottleOutPacketType Category; - + /// The type of packet so its delivery method can be determined + public PacketType Type; /// /// Default constructor /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 73d0984..c0fd437 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1064,14 +1064,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Clear all pending updates of parts to clients - /// - private void ClearUpdateSchedule() - { - m_updateFlag = 0; - } - private void SendObjectPropertiesToClient(UUID AgentID) { ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); @@ -2387,8 +2379,8 @@ namespace OpenSim.Region.Framework.Scenes { const float ROTATION_TOLERANCE = 0.01f; const float VELOCITY_TOLERANCE = 0.001f; - const float POSITION_TOLERANCE = 0.05f; - const int TIME_MS_TOLERANCE = 3000; + const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary + const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds. if (m_updateFlag == 1) { @@ -2401,7 +2393,7 @@ namespace OpenSim.Region.Framework.Scenes Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) { AddTerseUpdateToAllAvatars(); - ClearUpdateSchedule(); + // This causes the Scene to 'poll' physical objects every couple of frames // bad, so it's been replaced by an event driven method. @@ -2419,13 +2411,15 @@ namespace OpenSim.Region.Framework.Scenes m_lastAngularVelocity = AngularVelocity; m_lastTerseSent = Environment.TickCount; } + //Moved this outside of the if clause so updates don't get blocked.. *sigh* + m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams* } else { if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes { AddFullUpdateToAllAvatars(); - ClearUpdateSchedule(); + m_updateFlag = 0; //Same here } } } -- cgit v1.1 From b7f1fc116eb37a651a80bc09df11fa47540a1df9 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 15 Nov 2009 20:21:46 +0000 Subject: Prevent a nullref if a recipient of a group message gas left the scene --- .../Avatar/InstantMessage/OfflineMessageModule.cs | 27 ++++++++++++---------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index 1614b70..7f9e5af 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -164,19 +164,22 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage Listmsglist = SynchronousRestObjectPoster.BeginPostObject>( "POST", m_RestURL+"/RetrieveMessages/", client.AgentId); - foreach (GridInstantMessage im in msglist) + if (msglist != null) { - // client.SendInstantMessage(im); - - // Send through scene event manager so all modules get a chance - // to look at this message before it gets delivered. - // - // Needed for proper state management for stored group - // invitations - // - Scene s = FindScene(client.AgentId); - if (s != null) - s.EventManager.TriggerIncomingInstantMessage(im); + foreach (GridInstantMessage im in msglist) + { + // client.SendInstantMessage(im); + + // Send through scene event manager so all modules get a chance + // to look at this message before it gets delivered. + // + // Needed for proper state management for stored group + // invitations + // + Scene s = FindScene(client.AgentId); + if (s != null) + s.EventManager.TriggerIncomingInstantMessage(im); + } } } -- cgit v1.1 From a49c524c9e93db1409f1f05d7b881922e178927c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 15 Nov 2009 20:22:15 +0000 Subject: Add the ability to send messages to users ir regions via remote admin --- .../RemoteController/RemoteAdminPlugin.cs | 48 ++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 3149eaa..3bc557d 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -123,6 +123,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController availableMethods["admin_region_query"] = XmlRpcRegionQueryMethod; availableMethods["admin_shutdown"] = XmlRpcShutdownMethod; availableMethods["admin_broadcast"] = XmlRpcAlertMethod; + availableMethods["admin_dialog"] = XmlRpcDialogMethod; availableMethods["admin_restart"] = XmlRpcRestartMethod; availableMethods["admin_load_heightmap"] = XmlRpcLoadHeightmapMethod; // User management @@ -277,6 +278,53 @@ namespace OpenSim.ApplicationPlugins.RemoteController m_log.Info("[RADMIN]: Alert request complete"); return response; } + public XmlRpcResponse XmlRpcDialogMethod(XmlRpcRequest request, IPEndPoint remoteClient) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + + m_log.Info("[RADMIN]: Dialog request started"); + + try + { + Hashtable requestData = (Hashtable)request.Params[0]; + + checkStringParameters(request, new string[] { "password", "from", "message" }); + + if (m_requiredPassword != String.Empty && + (!requestData.Contains("password") || (string)requestData["password"] != m_requiredPassword)) + throw new Exception("wrong password"); + + string message = (string)requestData["message"]; + string fromuuid = (string)requestData["from"]; + m_log.InfoFormat("[RADMIN]: Broadcasting: {0}", message); + + responseData["accepted"] = true; + responseData["success"] = true; + response.Value = responseData; + + m_app.SceneManager.ForEachScene( + delegate(Scene scene) + { + IDialogModule dialogModule = scene.RequestModuleInterface(); + if (dialogModule != null) + dialogModule.SendNotificationToUsersInRegion(UUID.Zero, fromuuid, message); + }); + } + catch (Exception e) + { + m_log.ErrorFormat("[RADMIN]: Broadcasting: failed: {0}", e.Message); + m_log.DebugFormat("[RADMIN]: Broadcasting: failed: {0}", e.ToString()); + + responseData["accepted"] = false; + responseData["success"] = false; + responseData["error"] = e.Message; + response.Value = responseData; + } + + m_log.Info("[RADMIN]: Alert request complete"); + return response; + } public XmlRpcResponse XmlRpcLoadHeightmapMethod(XmlRpcRequest request, IPEndPoint remoteClient) { -- cgit v1.1 From b9546d12f230f4153b2c6e7e71520aa2d35c762b Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 15 Nov 2009 21:20:42 +0000 Subject: Change land packet sending back to what the careminster release used to use, remove the silly spiral stuff. Revert to double packets for improved user experience --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 83 +++++++++------------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 7eb829e..49b9378 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -785,6 +785,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void SendLayerData(float[] map) { Util.FireAndForget(DoSendLayerData, map); + + // Send it sync, and async. It's not that much data + // and it improves user experience just so much! + DoSendLayerData(map); } /// @@ -797,16 +801,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { - //for (int y = 0; y < 16; y++) - //{ - // for (int x = 0; x < 16; x++) - // { - // SendLayerData(x, y, map); - // } - //} - - // Send LayerData in a spiral pattern. Fun! - SendLayerTopRight(map, 0, 0, 15, 15); + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x+=4) + { + SendLayerPacket(x, y, map); + } + } } catch (Exception e) { @@ -814,51 +815,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2) - { - // Row - for (int i = x1; i <= x2; i++) - SendLayerData(i, y1, map); - - // Column - for (int j = y1 + 1; j <= y2; j++) - SendLayerData(x2, j, map); - - if (x2 - x1 > 0) - SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2); - } - - void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2) - { - // Row in reverse - for (int i = x2; i >= x1; i--) - SendLayerData(i, y2, map); - - // Column in reverse - for (int j = y2 - 1; j >= y1; j--) - SendLayerData(x1, j, map); - - if (x2 - x1 > 0) - SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1); - } - /// /// Sends a set of four patches (x, x+1, ..., x+3) to the client /// /// heightmap /// X coordinate for patches 0..12 /// Y coordinate for patches 0..15 - // private void SendLayerPacket(float[] map, int y, int x) - // { - // int[] patches = new int[4]; - // patches[0] = x + 0 + y * 16; - // patches[1] = x + 1 + y * 16; - // patches[2] = x + 2 + y * 16; - // patches[3] = x + 3 + y * 16; - - // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); - // OutPacket(layerpack, ThrottleOutPacketType.Land); - // } + private void SendLayerPacket(int x, int y, float[] map) + { + int[] patches = new int[4]; + patches[0] = x + 0 + y * 16; + patches[1] = x + 1 + y * 16; + patches[2] = x + 2 + y * 16; + patches[3] = x + 3 + y * 16; + + float[] heightmap = (map.Length == 65536) ? + map : + LLHeightFieldMoronize(map); + + try + { + Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); + OutPacket(layerpack, ThrottleOutPacketType.Land); + } + catch + { + for (int px = x ; px < x + 4 ; px++) + SendLayerData(px, y, map); + } + } /// /// Sends a specified patch to a client -- cgit v1.1 From 4c10826caa4b2b19200ab3f0272bb1c20c26c53e Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Mon, 16 Nov 2009 02:12:56 +0100 Subject: Fix merge conflicts --- OpenSim/Region/Physics/Manager/PhysicsActor.cs | 6 +++--- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 7 ------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 8241e8f..b82586f 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -249,9 +249,9 @@ namespace OpenSim.Region.Physics.Manager public abstract float APIDStrength { set;} public abstract float APIDDamping { set;} - public abstract void AddForce(PhysicsVector force, bool pushforce); - public abstract void AddAngularForce(PhysicsVector force, bool pushforce); - public abstract void SetMomentum(PhysicsVector momentum); + public abstract void AddForce(Vector3 force, bool pushforce); + public abstract void AddAngularForce(Vector3 force, bool pushforce); + public abstract void SetMomentum(Vector3 momentum); public abstract void SubscribeEvents(int ms); public abstract void UnSubscribeEvents(); public abstract bool SubscribedEvents(); diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index b963d65..8f2c801 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -107,17 +107,10 @@ namespace OpenSim.Region.Physics.OdePlugin private float m_PIDHoverTau; private bool m_useHoverPID; private PIDHoverType m_PIDHoverType = PIDHoverType.Ground; -<<<<<<< HEAD:OpenSim/Region/Physics/OdePlugin/ODEPrim.cs - private float m_targetHoverHeight = 0f; - private float m_groundHeight = 0f; - private float m_waterHeight = 0f; - private float m_buoyancy = 0f; //Set by llSetBuoyancy(), for non-vehicles. -======= private float m_targetHoverHeight; private float m_groundHeight; private float m_waterHeight; private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. ->>>>>>> vehicles:OpenSim/Region/Physics/OdePlugin/ODEPrim.cs // private float m_tensor = 5f; private int body_autodisable_frames = 20; -- cgit v1.1 From 7f0f5060ec418533ee7d952bdc0815f3925bda9f Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Thu, 19 Nov 2009 20:13:26 +0100 Subject: Clean up messages in ODE --- OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs | 2 +- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs index 1842eb4..78b15be 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs @@ -629,7 +629,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Error is 0 (no error) to +/- 2 (max error) // scale it by VAservo verterr = verterr * VAservo; -if(frcount == 0) Console.WriteLine("VAerr=" + verterr); +//if(frcount == 0) Console.WriteLine("VAerr=" + verterr); // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 8f2c801..2bf96e4 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -1584,8 +1584,8 @@ Console.WriteLine(" JointCreateFixed"); if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. { -if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_vehicle.Type + - " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); +//if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_vehicle.Type + + // " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); if (m_vehicle.Type != Vehicle.TYPE_NONE) { // 'VEHICLES' are dealt with in ODEDynamics.cs @@ -1806,7 +1806,7 @@ if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_vehicle d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); //Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); } -if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); +//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); } // end m_useAPID fx *= m_mass; -- cgit v1.1 From 0149265ee83581cf2fb150dcd5d8734c02926261 Mon Sep 17 00:00:00 2001 From: CasperW Date: Sat, 21 Nov 2009 15:36:38 +0100 Subject: Improved avatar responsiveness. --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 4 +- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 24 +++--- .../Region/ClientStack/LindenUDP/OpenSimUDPBase.cs | 89 +++++++++++++++++++--- .../Scenes/Animation/ScenePresenceAnimator.cs | 4 +- OpenSim/Region/Framework/Scenes/Scene.cs | 10 +-- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 80 +++++++++++++++---- 6 files changed, 163 insertions(+), 48 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 49b9378..39eb968 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3121,7 +3121,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data); - OutPacket(objupdate, ThrottleOutPacketType.Task); } @@ -3172,8 +3171,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue(); } - // HACK: Using the task category until the tiered reprioritization code is in - OutPacket(terse, ThrottleOutPacketType.Task); + OutPacket(terse, ThrottleOutPacketType.State); } public void SendCoarseLocationUpdate(List users, List CoarseLocations) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 0b05ed9..4a7bdfe 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -571,23 +571,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP //Sorry, i know it's not optimal, but until the LL client //manages packets correctly and re-orders them as required, this is necessary. - if (outgoingPacket.Type == PacketType.ImprovedTerseObjectUpdate - || outgoingPacket.Type == PacketType.ChatFromSimulator - || outgoingPacket.Type == PacketType.ObjectUpdate - || outgoingPacket.Type == PacketType.LayerData) + + // Put the UDP payload on the wire + if (outgoingPacket.Type == PacketType.ImprovedTerseObjectUpdate) { - sendSynchronous = true; + SyncBeginPrioritySend(buffer, 2); // highest priority } - - // Put the UDP payload on the wire - if (sendSynchronous == true) + else if (outgoingPacket.Type == PacketType.ObjectUpdate + || outgoingPacket.Type == PacketType.ChatFromSimulator + || outgoingPacket.Type == PacketType.LayerData) { - SyncBeginSend(buffer); + SyncBeginPrioritySend(buffer, 1); // medium priority } else { - AsyncBeginSend(buffer); + SyncBeginPrioritySend(buffer, 0); // normal priority } + + //AsyncBeginSend(buffer); + // Keep track of when this packet was sent out (right now) outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; } @@ -862,7 +864,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); - AsyncBeginSend(buffer); + SyncBeginPrioritySend(buffer, 1); //Setting this to a medium priority should help minimise resends } private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs index 63579ac..45d9170 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs @@ -29,6 +29,7 @@ using System; using System.Net; using System.Net.Sockets; using System.Threading; +using System.Collections.Generic; using log4net; namespace OpenMetaverse @@ -52,12 +53,25 @@ namespace OpenMetaverse /// Local IP address to bind to in server mode protected IPAddress m_localBindAddress; + /// + /// Standard queue for our outgoing SyncBeginPrioritySend + /// + private List m_standardQueue = new List(); + + /// + /// Prioritised queue for our outgoing SyncBeginPrioritySend + /// + private List m_priorityQueue = new List(); + /// UDP socket, used in either client or server mode private Socket m_udpSocket; /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; + /// Are we currently sending data asynchronously? + private volatile bool m_sendingData = false; + /// The all important shutdown flag private volatile bool m_shutdownFlag = true; @@ -246,25 +260,48 @@ namespace OpenMetaverse } } - public void SyncBeginSend(UDPPacketBuffer buf) + public void SyncBeginPrioritySend(UDPPacketBuffer buf, int Priority) { if (!m_shutdownFlag) { - try + if (!m_sendingData) { - m_udpSocket.SendTo( - buf.Data, - 0, - buf.DataLength, - SocketFlags.None, - buf.RemoteEndPoint); + m_sendingData = true; + try + { + AsyncBeginSend(buf); + } + catch (SocketException) { } + catch (ObjectDisposedException) { } + } + else + { + if (Priority == 2) + { + lock (m_priorityQueue) + { + m_priorityQueue.Add(buf); + } + } + else + { + lock (m_standardQueue) + { + if (Priority != 0) + { + m_standardQueue.Insert(0, buf); + } + else + { + m_standardQueue.Add(buf); + } + } + } } - catch (SocketException) { } - catch (ObjectDisposedException) { } } } - public void AsyncBeginSend(UDPPacketBuffer buf) + private void AsyncBeginSend(UDPPacketBuffer buf) { if (!m_shutdownFlag) { @@ -288,8 +325,36 @@ namespace OpenMetaverse { try { -// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; m_udpSocket.EndSendTo(result); + + if (m_sendingData) + { + lock (m_priorityQueue) + { + if (m_priorityQueue.Count > 0) + { + UDPPacketBuffer buf = m_priorityQueue[0]; + m_priorityQueue.RemoveAt(0); + AsyncBeginSend(buf); + } + else + { + lock (m_standardQueue) + { + if (m_standardQueue.Count > 0) + { + UDPPacketBuffer buf = m_standardQueue[0]; + m_standardQueue.RemoveAt(0); + AsyncBeginSend(buf); + } + else + { + m_sendingData = false; + } + } + } + } + } } catch (SocketException) { } catch (ObjectDisposedException) { } diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index cbe4118..2230fba 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -156,8 +156,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); // Check control flags - bool heldForward = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; - bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; + bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS); + bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG; //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a430b1e..5058457 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1164,16 +1164,16 @@ namespace OpenSim.Region.Framework.Scenes // Check if any objects have reached their targets CheckAtTargets(); - // Update SceneObjectGroups that have scheduled themselves for updates - // Objects queue their updates onto all scene presences - if (m_frame % m_update_objects == 0) - m_sceneGraph.UpdateObjectGroups(); - // Run through all ScenePresences looking for updates // Presence updates and queued object updates for each presence are sent to clients if (m_frame % m_update_presences == 0) m_sceneGraph.UpdatePresences(); + // Update SceneObjectGroups that have scheduled themselves for updates + // Objects queue their updates onto all scene presences + if (m_frame % m_update_objects == 0) + m_sceneGraph.UpdateObjectGroups(); + int TempPhysicsMS2 = Environment.TickCount; if ((m_frame % m_update_physics == 0) && m_physics_enabled) m_sceneGraph.UpdatePreparePhysics(); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 424c25b..99f3141 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes // { // m_log.Debug("[ScenePresence] Destructor called"); // } - + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; @@ -144,7 +144,6 @@ namespace OpenSim.Region.Framework.Scenes private int m_perfMonMS; private bool m_setAlwaysRun; - private bool m_forceFly; private bool m_flyDisabled; @@ -166,7 +165,8 @@ namespace OpenSim.Region.Framework.Scenes protected RegionInfo m_regionInfo; protected ulong crossingFromRegion; - private readonly Vector3[] Dir_Vectors = new Vector3[6]; + private readonly Vector3[] Dir_Vectors = new Vector3[9]; + private bool m_isNudging = false; // Position of agent's camera in world (region cordinates) protected Vector3 m_CameraCenter; @@ -230,6 +230,8 @@ namespace OpenSim.Region.Framework.Scenes DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, + DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, + DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG } @@ -714,21 +716,41 @@ namespace OpenSim.Region.Framework.Scenes Dir_Vectors[3] = -Vector3.UnitY; //RIGHT Dir_Vectors[4] = Vector3.UnitZ; //UP Dir_Vectors[5] = -Vector3.UnitZ; //DOWN - Dir_Vectors[5] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge + Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE + Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE + Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge } private Vector3[] GetWalkDirectionVectors() { - Vector3[] vector = new Vector3[6]; + Vector3[] vector = new Vector3[9]; vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK vector[2] = Vector3.UnitY; //LEFT vector[3] = -Vector3.UnitY; //RIGHT vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN - vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge + vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE + vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE + vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge return vector; } + + private bool[] GetDirectionIsNudge() + { + bool[] isNudge = new bool[9]; + isNudge[0] = false; //FORWARD + isNudge[1] = false; //BACK + isNudge[2] = false; //LEFT + isNudge[3] = false; //RIGHT + isNudge[4] = false; //UP + isNudge[5] = false; //DOWN + isNudge[6] = true; //FORWARD_NUDGE + isNudge[7] = true; //BACK_NUDGE + isNudge[8] = true; //DOWN_Nudge + return isNudge; + } + #endregion @@ -1147,7 +1169,6 @@ namespace OpenSim.Region.Framework.Scenes // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); // return; //} - m_perfMonMS = Environment.TickCount; ++m_movementUpdateCount; @@ -1229,7 +1250,6 @@ namespace OpenSim.Region.Framework.Scenes m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); } } - lock (scriptedcontrols) { if (scriptedcontrols.Count > 0) @@ -1261,7 +1281,6 @@ namespace OpenSim.Region.Framework.Scenes { return; } - if (m_allowMovement) { int i = 0; @@ -1289,6 +1308,11 @@ namespace OpenSim.Region.Framework.Scenes update_rotation = true; } + //guilty until proven innocent.. + bool Nudging = true; + //Basically, if there is at least one non-nudge control then we don't need + //to worry about stopping the avatar + if (m_parentID == 0) { bool bAllowUpdateMoveToPosition = false; @@ -1303,6 +1327,12 @@ namespace OpenSim.Region.Framework.Scenes else dirVectors = Dir_Vectors; + bool[] isNudge = GetDirectionIsNudge(); + + + + + foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) { if (((uint)flags & (uint)DCF) != 0) @@ -1312,6 +1342,10 @@ namespace OpenSim.Region.Framework.Scenes try { agent_control_v3 += dirVectors[i]; + if (isNudge[i] == false) + { + Nudging = false; + } } catch (IndexOutOfRangeException) { @@ -1373,6 +1407,9 @@ namespace OpenSim.Region.Framework.Scenes // Ignore z component of vector Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); LocalVectorToTarget2D.Normalize(); + + //We're not nudging + Nudging = false; agent_control_v3 += LocalVectorToTarget2D; // update avatar movement flags. the avatar coordinate system is as follows: @@ -1450,7 +1487,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); - AddNewMovement(agent_control_v3, q); + AddNewMovement(agent_control_v3, q, Nudging); if (update_movementflag) Animator.UpdateMovementAnimations(); @@ -1886,7 +1923,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// The vector in which to move. This is relative to the rotation argument /// The direction in which this avatar should now face. - public void AddNewMovement(Vector3 vec, Quaternion rotation) + public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging) { if (m_isChildAgent) { @@ -1960,7 +1997,7 @@ namespace OpenSim.Region.Framework.Scenes // TODO: Add the force instead of only setting it to support multiple forces per frame? m_forceToApply = direc; - + m_isNudging = Nudging; m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS); } @@ -1975,7 +2012,7 @@ namespace OpenSim.Region.Framework.Scenes const float POSITION_TOLERANCE = 0.05f; //const int TIME_MS_TOLERANCE = 3000; - SendPrimUpdates(); + if (m_newCoarseLocations) { @@ -2011,6 +2048,9 @@ namespace OpenSim.Region.Framework.Scenes CheckForBorderCrossing(); CheckForSignificantMovement(); // sends update to the modules. } + + //Sending prim updates AFTER the avatar terse updates are sent + SendPrimUpdates(); } #endregion @@ -2864,14 +2904,24 @@ namespace OpenSim.Region.Framework.Scenes { if (m_forceToApply.HasValue) { - Vector3 force = m_forceToApply.Value; + Vector3 force = m_forceToApply.Value; m_updateflag = true; -// movementvector = force; Velocity = force; m_forceToApply = null; } + else + { + if (m_isNudging) + { + Vector3 force = Vector3.Zero; + + m_updateflag = true; + Velocity = force; + m_isNudging = false; + } + } } public override void SetText(string text, Vector3 color, double alpha) -- cgit v1.1 From 4a29a7f92cc5264dfcb4a4376a61506d29dd9d8d Mon Sep 17 00:00:00 2001 From: CasperW Date: Sat, 21 Nov 2009 18:50:52 +0100 Subject: Minor packet ordering fix --- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 1 - .../Region/ClientStack/LindenUDP/OpenSimUDPBase.cs | 40 ++++++++++++++++------ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 4a7bdfe..98bb4f7 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -578,7 +578,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP SyncBeginPrioritySend(buffer, 2); // highest priority } else if (outgoingPacket.Type == PacketType.ObjectUpdate - || outgoingPacket.Type == PacketType.ChatFromSimulator || outgoingPacket.Type == PacketType.LayerData) { SyncBeginPrioritySend(buffer, 1); // medium priority diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs index 45d9170..de2cd24 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs @@ -57,7 +57,12 @@ namespace OpenMetaverse /// Standard queue for our outgoing SyncBeginPrioritySend /// private List m_standardQueue = new List(); - + + /// + /// Medium priority queue for our outgoing SyncBeginPrioritySend + /// + private List m_mediumPriorityQueue = new List(); + /// /// Prioritised queue for our outgoing SyncBeginPrioritySend /// @@ -285,13 +290,16 @@ namespace OpenMetaverse } else { - lock (m_standardQueue) + if (Priority != 0) { - if (Priority != 0) + lock (m_mediumPriorityQueue) { - m_standardQueue.Insert(0, buf); + m_mediumPriorityQueue.Add(buf); } - else + } + else + { + lock (m_standardQueue) { m_standardQueue.Add(buf); } @@ -339,17 +347,29 @@ namespace OpenMetaverse } else { - lock (m_standardQueue) + lock (m_mediumPriorityQueue) { - if (m_standardQueue.Count > 0) + if (m_mediumPriorityQueue.Count > 0) { - UDPPacketBuffer buf = m_standardQueue[0]; - m_standardQueue.RemoveAt(0); + UDPPacketBuffer buf = m_mediumPriorityQueue[0]; + m_mediumPriorityQueue.RemoveAt(0); AsyncBeginSend(buf); } else { - m_sendingData = false; + lock (m_standardQueue) + { + if (m_standardQueue.Count > 0) + { + UDPPacketBuffer buf = m_standardQueue[0]; + m_standardQueue.RemoveAt(0); + AsyncBeginSend(buf); + } + else + { + m_sendingData = false; + } + } } } } -- cgit v1.1 From f1522e62042d11604ad70a39b26dc94953e9db7d Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Sun, 22 Nov 2009 08:31:35 +0100 Subject: Add non-scripted sit, fix scripted sit. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 99 +++++++++++++++++------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 1dedcf1..aa538dc 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -89,7 +89,8 @@ namespace OpenSim.Region.Framework.Scenes /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis /// issue #1716 /// - private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); +// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); + private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); public UUID currentParcelUUID = UUID.Zero; @@ -113,7 +114,8 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 lastKnownAllowedPosition; public bool sentMessageAboutRestrictedParcelFlyingDown; public Vector4 CollisionPlane = Vector4.UnitW; - + + private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation private Vector3 m_lastPosition; private Quaternion m_lastRotation; private Vector3 m_lastVelocity; @@ -1531,7 +1533,7 @@ namespace OpenSim.Region.Framework.Scenes Velocity = Vector3.Zero; SendFullUpdateToAllClients(); - //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); + HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ?? } //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); m_requestedSitTargetUUID = UUID.Zero; @@ -1644,7 +1646,7 @@ namespace OpenSim.Region.Framework.Scenes bool SitTargetisSet = (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f && avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f)); - + // this test is probably failing if (SitTargetisSet && SitTargetUnOccupied) { //switch the target to this prim @@ -1671,26 +1673,37 @@ namespace OpenSim.Region.Framework.Scenes { // TODO: determine position to sit at based on scene geometry; don't trust offset from client // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it - + + // part is the prim to sit on + // offset is the vector distance from that prim center to the click-spot + // UUID is the UUID of the Avatar doing the clicking + + m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation + // Is a sit target available? Vector3 avSitOffSet = part.SitTargetPosition; Quaternion avSitOrientation = part.SitTargetOrientation; UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); - bool SitTargetisSet = - (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f && - avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f)); +// bool SitTargetisSet = +// (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f && +// avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f)); + bool SitTargetisSet = ((Vector3.Zero != avSitOffSet) || (Quaternion.Identity != avSitOrientation)); + +//Console.WriteLine("SendSitResponse offset=" + offset + " UnOccup=" + SitTargetUnOccupied + +// " TargSet=" + SitTargetisSet); + if (SitTargetisSet && SitTargetUnOccupied) { part.SetAvatarOnSitTarget(UUID); offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); sitOrientation = avSitOrientation; - autopilot = false; + autopilot = false; // Jump direct to scripted llSitPos() } - pos = part.AbsolutePosition + offset; + pos = part.AbsolutePosition + offset; // Region position where clicked //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) //{ // offset = pos; @@ -1703,17 +1716,17 @@ namespace OpenSim.Region.Framework.Scenes m_sitAvatarHeight = m_physicsActor.Size.Z; if (autopilot) - { + { // its not a scripted sit if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) { - autopilot = false; + autopilot = false; // close enough RemoveFromPhysicalScene(); - AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); - } + AbsolutePosition = pos + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to Prim + } // else the autopilot will get us close } else - { + { // its a scripted sit RemoveFromPhysicalScene(); } } @@ -1816,26 +1829,41 @@ namespace OpenSim.Region.Framework.Scenes { if (part.GetAvatarOnSitTarget() == UUID) { + // Scripted sit Vector3 sitTargetPos = part.SitTargetPosition; Quaternion sitTargetOrient = part.SitTargetOrientation; - - //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0); - //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w); - - //Quaternion result = (sitTargetOrient * vq) * nq; - m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); m_pos += SIT_TARGET_ADJUSTMENT; m_bodyRot = sitTargetOrient; - //Rotation = sitTargetOrient; m_parentPosition = part.AbsolutePosition; - - //SendTerseUpdateToAllClients(); } else { - m_pos -= part.AbsolutePosition; + // Non-scripted sit by Kitto Flora 21Nov09 + // Calculate angle of line from prim to Av + float y_diff = (m_avInitialPos.Y - part.AbsolutePosition.Y); + float x_diff = ( m_avInitialPos.X - part.AbsolutePosition.X); + if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0 + if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0 + float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff); + Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); + // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'. + // Av sits at world euler <0,0, z>, translated by part rotation + m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click + m_pos = new Vector3(0f, 0f, 0.05f) + + (new Vector3(0.0f, 0f, 0.625f) * partIRot) + + (new Vector3(0.25f, 0f, 0.0f) * m_bodyRot); // sit at center of prim m_parentPosition = part.AbsolutePosition; + //Set up raytrace to find top surface of prim + Vector3 size = part.Scale; + float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); + Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); + Vector3 down = new Vector3(0f, 0f, -1f); + m_scene.PhysicsScene.RaycastWorld( + start, // Vector3 position, + down, // Vector3 direction, + mag, // float length, + SitAltitudeCallback); // retMethod } } else @@ -1850,11 +1878,22 @@ namespace OpenSim.Region.Framework.Scenes Animator.TrySetMovementAnimation(sitAnimation); SendFullUpdateToAllClients(); - // This may seem stupid, but Our Full updates don't send avatar rotation :P - // So we're also sending a terse update (which has avatar rotation) - // [Update] We do now. - //SendTerseUpdateToAllClients(); } + + public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance) + { +// Console.WriteLine("[RAYCASTRESULT]: Hit={0}, Point={1}, ID={2}, Dist={3}", hitYN, collisionPoint, localid, distance); + if(hitYN) + { + // m_pos = Av offset from prim center to make look like on center + // m_parentPosition = Actual center pos of prim + // collisionPoint = spot on prim where we want to sit + SceneObjectPart part = m_scene.GetSceneObjectPart(localid); + Vector3 offset = (collisionPoint - m_parentPosition) * Quaternion.Inverse(part.RotationOffset); + m_pos += offset; +// Console.WriteLine("m_pos={0}, offset={1} newsit={2}", m_pos, offset, newsit); + } + } /// /// Event handler for the 'Always run' setting on the client @@ -3578,4 +3617,4 @@ namespace OpenSim.Region.Framework.Scenes } } } -} \ No newline at end of file +} -- cgit v1.1 From 234b29cf66ae79ab686fcce8a84499dbf031b161 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 23 Nov 2009 14:59:39 +0100 Subject: testing checkout --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index a004cad..6d7f602 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -11,7 +11,7 @@ modification, are permitted provided that the following conditions are met: * Neither the name of the OpenSimulator Project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -- cgit v1.1 From c3d4b66953b4375cc93b709968c7765d2395566a Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 23 Nov 2009 12:52:52 +0000 Subject: Revert "testing checkout" This reverts commit 234b29cf66ae79ab686fcce8a84499dbf031b161. --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index 6d7f602..a004cad 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -11,7 +11,7 @@ modification, are permitted provided that the following conditions are met: * Neither the name of the OpenSimulator Project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -- cgit v1.1 From 889ce36afa67c521f3e50e4833a894ffd39af490 Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 23 Nov 2009 16:02:05 +0100 Subject: Added some [DebuggerNonUserCode] modifiers to functions that throw EventAbortException() to ease debugging on Visual Studio --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++++ OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs | 2 ++ OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs | 2 ++ OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 5 ++++- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 3 +++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 50b2fb5..b549b5c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; //for [DebuggerNonUserCode] using System.Runtime.Remoting.Lifetime; using System.Text; using System.Threading; @@ -151,6 +152,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api get { return m_ScriptEngine.World; } } + [DebuggerNonUserCode] public void state(string newState) { m_ScriptEngine.SetState(m_itemID, newState); @@ -160,6 +162,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Reset the named script. The script must be present /// in the same prim. /// + [DebuggerNonUserCode] public void llResetScript() { m_host.AddScriptLPS(1); @@ -3755,6 +3758,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(3000); } + [DebuggerNonUserCode] public void llRemoveInventory(string name) { m_host.AddScriptLPS(1); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs index 7f67599..15e0408 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/Executor.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; //for [DebuggerNonUserCode] using System.Reflection; using System.Runtime.Remoting.Lifetime; using OpenSim.Region.ScriptEngine.Shared; @@ -131,6 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return (eventFlags); } + [DebuggerNonUserCode] public void ExecuteEvent(string state, string FunctionName, object[] args) { // IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory. diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs index 121159c..a44abb0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs @@ -33,6 +33,7 @@ using System.Threading; using System.Reflection; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; //for [DebuggerNonUserCode] using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api.Runtime; @@ -90,6 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return (int)m_Executor.GetStateEventFlags(state); } + [DebuggerNonUserCode] public void ExecuteEvent(string state, string FunctionName, object[] args) { m_Executor.ExecuteEvent(state, FunctionName, args); diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 41b5d49..ed3fdbe 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -27,6 +27,7 @@ using System; using System.IO; +using System.Diagnostics; //for [DebuggerNonUserCode] using System.Runtime.Remoting; using System.Runtime.Remoting.Lifetime; using System.Threading; @@ -544,6 +545,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance return true; } + [DebuggerNonUserCode] //Prevents the debugger from farting in this function public void SetState(string state) { if (state == State) @@ -555,7 +557,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance new DetectParams[0])); PostEvent(new EventParams("state_entry", new Object[0], new DetectParams[0])); - + throw new EventAbortException(); } @@ -824,6 +826,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance new Object[0], new DetectParams[0])); } + [DebuggerNonUserCode] //Stops the VS debugger from farting in this function public void ApiResetScript() { // bool running = Running; diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index a60c0ba..8b94f28 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -30,6 +30,7 @@ using System.IO; using System.Threading; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; //for [DebuggerNonUserCode] using System.Security; using System.Security.Policy; using System.Reflection; @@ -1119,6 +1120,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine return false; } + [DebuggerNonUserCode] public void ApiResetScript(UUID itemID) { IScriptInstance instance = GetInstance(itemID); @@ -1170,6 +1172,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine return UUID.Zero; } + [DebuggerNonUserCode] public void SetState(UUID itemID, string newState) { IScriptInstance instance = GetInstance(itemID); -- cgit v1.1 From 73c2162ff60850d96761aa07a1950dbbb2ec3e80 Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 23 Nov 2009 19:51:40 +0100 Subject: Fixed nullrefs --- .../Region/CoreModules/Avatar/Chat/ChatModule.cs | 42 ++++++++++++---------- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 8 +++-- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index cd59bdb..5c24f03 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -266,25 +266,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat } // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); - - ((Scene)c.Scene).ForEachScenePresence( - delegate(ScenePresence presence) - { - // ignore chat from child agents - if (presence.IsChildAgent) return; - - IClientAPI client = presence.ControllingClient; - - // don't forward SayOwner chat from objects to - // non-owner agents - if ((c.Type == ChatTypeEnum.Owner) && - (null != c.SenderObject) && - (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) - return; - - client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, - (byte)sourceType, (byte)ChatAudibleLevel.Fully); - }); + if (c.Scene != null) + { + ((Scene)c.Scene).ForEachScenePresence + ( + delegate(ScenePresence presence) + { + // ignore chat from child agents + if (presence.IsChildAgent) return; + + IClientAPI client = presence.ControllingClient; + + // don't forward SayOwner chat from objects to + // non-owner agents + if ((c.Type == ChatTypeEnum.Owner) && + (null != c.SenderObject) && + (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) + return; + + client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, + (byte)sourceType, (byte)ChatAudibleLevel.Fully); + } + ); + } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 66fb918..83208e9 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -840,8 +840,12 @@ namespace OpenSim.Region.Framework.Scenes public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) { SceneObjectPart part = GetSceneObjectPart(localID); - SceneObjectGroup group = part.ParentGroup; - if (group != null) + SceneObjectGroup group = null; + if (part != null) + { + group = part.ParentGroup; + } + if (part != null && group != null) { TaskInventoryItem item = group.GetInventoryItem(localID, itemID); if (item == null) -- cgit v1.1 From 247c66b3fe792692468ede6a516d85c6c9852d23 Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 23 Nov 2009 20:25:53 +0100 Subject: Swap the locking of m_EventQueue and m_Script to ease locks on script inventory operations --- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 234 +++++++++++---------- 1 file changed, 119 insertions(+), 115 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index ed3fdbe..063d50f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -640,154 +640,158 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance /// public object EventProcessor() { + + EventParams data = null; + + lock (m_EventQueue) + { lock (m_Script) { - EventParams data = null; - - lock (m_EventQueue) + data = (EventParams) m_EventQueue.Dequeue(); + if (data == null) // Shouldn't happen { - data = (EventParams) m_EventQueue.Dequeue(); - if (data == null) // Shouldn't happen + if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) { - if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) - { - m_CurrentResult = m_Engine.QueueEventHandler(this); - } - else - { - m_CurrentResult = null; - } - return 0; + m_CurrentResult = m_Engine.QueueEventHandler(this); } - - if (data.EventName == "timer") - m_TimerQueued = false; - if (data.EventName == "control") + else { - if (m_ControlEventsInQueue > 0) - m_ControlEventsInQueue--; + m_CurrentResult = null; } - if (data.EventName == "collision") - m_CollisionInQueue = false; + return 0; } - - //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this); - m_DetectParams = data.DetectParams; - - if (data.EventName == "state") // Hardcoded state change + if (data.EventName == "timer") + m_TimerQueued = false; + if (data.EventName == "control") { - // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}", - // m_PrimName, m_ScriptName, data.Params[0].ToString()); - m_State=data.Params[0].ToString(); - AsyncCommandManager.RemoveScript(m_Engine, - m_LocalID, m_ItemID); + if (m_ControlEventsInQueue > 0) + m_ControlEventsInQueue--; + } + if (data.EventName == "collision") + m_CollisionInQueue = false; + } + } + lock(m_Script) + { + + //m_log.DebugFormat("[XENGINE]: Processing event {0} for {1}", data.EventName, this); - SceneObjectPart part = m_Engine.World.GetSceneObjectPart( - m_LocalID); - if (part != null) - { - part.SetScriptEvents(m_ItemID, - (int)m_Script.GetStateEventFlags(State)); - } + m_DetectParams = data.DetectParams; + + if (data.EventName == "state") // Hardcoded state change + { +// m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}", +// m_PrimName, m_ScriptName, data.Params[0].ToString()); + m_State=data.Params[0].ToString(); + AsyncCommandManager.RemoveScript(m_Engine, + m_LocalID, m_ItemID); + + SceneObjectPart part = m_Engine.World.GetSceneObjectPart( + m_LocalID); + if (part != null) + { + part.SetScriptEvents(m_ItemID, + (int)m_Script.GetStateEventFlags(State)); } - else + } + else + { + if (m_Engine.World.PipeEventsForScript(m_LocalID) || + data.EventName == "control") // Don't freeze avies! { - if (m_Engine.World.PipeEventsForScript(m_LocalID) || - data.EventName == "control") // Don't freeze avies! - { - SceneObjectPart part = m_Engine.World.GetSceneObjectPart( - m_LocalID); - // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", - // m_PrimName, m_ScriptName, data.EventName, m_State); + SceneObjectPart part = m_Engine.World.GetSceneObjectPart( + m_LocalID); + // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", + // m_PrimName, m_ScriptName, data.EventName, m_State); - try - { - m_CurrentEvent = data.EventName; - m_EventStart = DateTime.Now; - m_InEvent = true; + try + { + m_CurrentEvent = data.EventName; + m_EventStart = DateTime.Now; + m_InEvent = true; - m_Script.ExecuteEvent(State, data.EventName, data.Params); + m_Script.ExecuteEvent(State, data.EventName, data.Params); - m_InEvent = false; - m_CurrentEvent = String.Empty; + m_InEvent = false; + m_CurrentEvent = String.Empty; - if (m_SaveState) - { - // This will be the very first event we deliver - // (state_entry) in default state - // + if (m_SaveState) + { + // This will be the very first event we deliver + // (state_entry) in default state + // - SaveState(m_Assembly); + SaveState(m_Assembly); - m_SaveState = false; - } + m_SaveState = false; } - catch (Exception e) - { - // m_log.DebugFormat("[SCRIPT] Exception: {0}", e.Message); - m_InEvent = false; - m_CurrentEvent = String.Empty; + } + catch (Exception e) + { + // m_log.DebugFormat("[SCRIPT] Exception: {0}", e.Message); + m_InEvent = false; + m_CurrentEvent = String.Empty; - if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) - { - try - { - // DISPLAY ERROR INWORLD - string text = FormatException(e); - - if (text.Length > 1000) - text = text.Substring(0, 1000); - m_Engine.World.SimChat(Utils.StringToBytes(text), - ChatTypeEnum.DebugChannel, 2147483647, - part.AbsolutePosition, - part.Name, part.UUID, false); - } - catch (Exception) - { - } - // catch (Exception e2) // LEGIT: User Scripting - // { - // m_log.Error("[SCRIPT]: "+ - // "Error displaying error in-world: " + - // e2.ToString()); - // m_log.Error("[SCRIPT]: " + - // "Errormessage: Error compiling script:\r\n" + - // e.ToString()); - // } - } - else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) + if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) + { + try { - m_InSelfDelete = true; - if (part != null && part.ParentGroup != null) - m_Engine.World.DeleteSceneObject(part.ParentGroup, false); + // DISPLAY ERROR INWORLD + string text = FormatException(e); + + if (text.Length > 1000) + text = text.Substring(0, 1000); + m_Engine.World.SimChat(Utils.StringToBytes(text), + ChatTypeEnum.DebugChannel, 2147483647, + part.AbsolutePosition, + part.Name, part.UUID, false); } - else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException)) + catch (Exception) { - m_InSelfDelete = true; - if (part != null && part.ParentGroup != null) - part.Inventory.RemoveInventoryItem(m_ItemID); } + // catch (Exception e2) // LEGIT: User Scripting + // { + // m_log.Error("[SCRIPT]: "+ + // "Error displaying error in-world: " + + // e2.ToString()); + // m_log.Error("[SCRIPT]: " + + // "Errormessage: Error compiling script:\r\n" + + // e.ToString()); + // } + } + else if ((e is TargetInvocationException) && (e.InnerException is SelfDeleteException)) + { + m_InSelfDelete = true; + if (part != null && part.ParentGroup != null) + m_Engine.World.DeleteSceneObject(part.ParentGroup, false); + } + else if ((e is TargetInvocationException) && (e.InnerException is ScriptDeleteException)) + { + m_InSelfDelete = true; + if (part != null && part.ParentGroup != null) + part.Inventory.RemoveInventoryItem(m_ItemID); } } } + } - lock (m_EventQueue) + lock (m_EventQueue) + { + if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) { - if ((m_EventQueue.Count > 0) && m_RunEvents && (!m_ShuttingDown)) - { - m_CurrentResult = m_Engine.QueueEventHandler(this); - } - else - { - m_CurrentResult = null; - } + m_CurrentResult = m_Engine.QueueEventHandler(this); + } + else + { + m_CurrentResult = null; } + } - m_DetectParams = null; + m_DetectParams = null; - return 0; - } + return 0; + } } public int EventTime() -- cgit v1.1 From d1147136946daf14724183b3191119be44ff8b16 Mon Sep 17 00:00:00 2001 From: CasperW Date: Tue, 24 Nov 2009 18:02:12 +0100 Subject: Drop all locking of part.TaskInventory in favour of a ReaderWriterLockSlim lock handler. This gives us: - Faster prim inventory actions. Multiple threads can read at once. - Fixes the known prim inventory thread locks - In the event of a thread lock occurring, it will usually self heal after sixty seconds with an error message in the console --- OpenSim/Framework/TaskInventoryDictionary.cs | 111 ++++- .../World/Archiver/ArchiveReadRequest.cs | 21 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 38 +- .../Framework/Scenes/SceneObjectPartInventory.cs | 390 ++++++++------- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 16 +- .../Shared/Api/Implementation/LSL_Api.cs | 532 ++++++++++++--------- .../Shared/Api/Implementation/OSSL_Api.cs | 36 +- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 22 +- 8 files changed, 685 insertions(+), 481 deletions(-) diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 25ae6b0..efe5f0c 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs @@ -27,9 +27,12 @@ using System; using System.Collections.Generic; +using System.Threading; +using System.Reflection; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; +using log4net; using OpenMetaverse; namespace OpenSim.Framework @@ -45,6 +48,105 @@ namespace OpenSim.Framework // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static XmlSerializer tiiSerializer = new XmlSerializer(typeof (TaskInventoryItem)); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Thread LockedByThread; + /// + /// An advanced lock for inventory data + /// + private System.Threading.ReaderWriterLockSlim m_itemLock = new System.Threading.ReaderWriterLockSlim(); + + /// + /// Are we readlocked by the calling thread? + /// + public bool IsReadLockedByMe() + { + if (m_itemLock.RecursiveReadCount > 0) + { + return true; + } + else + { + return false; + } + } + + /// + /// Lock our inventory list for reading (many can read, one can write) + /// + public void LockItemsForRead(bool locked) + { + if (locked) + { + if (m_itemLock.IsWriteLockHeld && LockedByThread != null) + { + if (!LockedByThread.IsAlive) + { + //Locked by dead thread, reset. + m_itemLock = new System.Threading.ReaderWriterLockSlim(); + } + } + + if (m_itemLock.RecursiveReadCount > 0) + { + m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); + m_itemLock.ExitReadLock(); + } + if (m_itemLock.RecursiveWriteCount > 0) + { + m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); + m_itemLock.ExitWriteLock(); + } + + while (!m_itemLock.TryEnterReadLock(60000)) + { + m_log.Error("Thread lock detected while trying to aquire READ lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); + if (m_itemLock.IsWriteLockHeld) + { + m_itemLock = new System.Threading.ReaderWriterLockSlim(); + } + } + } + else + { + m_itemLock.ExitReadLock(); + } + } + + /// + /// Lock our inventory list for writing (many can read, one can write) + /// + public void LockItemsForWrite(bool locked) + { + if (locked) + { + //Enter a write lock, wait indefinately for one to open. + if (m_itemLock.RecursiveReadCount > 0) + { + m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); + m_itemLock.ExitReadLock(); + } + if (m_itemLock.RecursiveWriteCount > 0) + { + m_log.Error("[TaskInventoryDictionary] Recursive write lock requested. This should not happen and means something needs to be fixed."); + m_itemLock.ExitWriteLock(); + } + while (!m_itemLock.TryEnterWriteLock(60000)) + { + m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); + if (m_itemLock.IsWriteLockHeld) + { + m_itemLock = new System.Threading.ReaderWriterLockSlim(); + } + } + + LockedByThread = Thread.CurrentThread; + } + else + { + m_itemLock.ExitWriteLock(); + } + } #region ICloneable Members @@ -52,13 +154,12 @@ namespace OpenSim.Framework { TaskInventoryDictionary clone = new TaskInventoryDictionary(); - lock (this) + m_itemLock.EnterReadLock(); + foreach (UUID uuid in Keys) { - foreach (UUID uuid in Keys) - { - clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); - } + clone.Add(uuid, (TaskInventoryItem) this[uuid].Clone()); } + m_itemLock.ExitReadLock(); return clone; } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 70a225e..f204faf 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -246,21 +246,20 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Fix ownership/creator of inventory items // Not doing so results in inventory items // being no copy/no mod for everyone - lock (part.TaskInventory) + part.TaskInventory.LockItemsForRead(true); + TaskInventoryDictionary inv = part.TaskInventory; + foreach (KeyValuePair kvp in inv) { - TaskInventoryDictionary inv = part.TaskInventory; - foreach (KeyValuePair kvp in inv) + if (!ResolveUserUuid(kvp.Value.OwnerID)) { - if (!ResolveUserUuid(kvp.Value.OwnerID)) - { - kvp.Value.OwnerID = masterAvatarId; - } - if (!ResolveUserUuid(kvp.Value.CreatorID)) - { - kvp.Value.CreatorID = masterAvatarId; - } + kvp.Value.OwnerID = masterAvatarId; + } + if (!ResolveUserUuid(kvp.Value.CreatorID)) + { + kvp.Value.CreatorID = masterAvatarId; } } + part.TaskInventory.LockItemsForRead(false); } if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index cdec135..bbece2f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -389,12 +389,16 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes + /// Get the inventory list /// public TaskInventoryDictionary TaskInventory { - get { return m_inventory.Items; } - set { m_inventory.Items = value; } + get { + return m_inventory.Items; + } + set { + m_inventory.Items = value; + } } public uint ObjectFlags @@ -2101,17 +2105,18 @@ namespace OpenSim.Region.Framework.Scenes //Trys to fetch sound id from prim's inventory. //Prim's inventory doesn't support non script items yet - lock (TaskInventory) + TaskInventory.LockItemsForRead(true); + + foreach (KeyValuePair item in TaskInventory) { - foreach (KeyValuePair item in TaskInventory) + if (item.Value.Name == sound) { - if (item.Value.Name == sound) - { - soundID = item.Value.ItemID; - break; - } + soundID = item.Value.ItemID; + break; } } + + TaskInventory.LockItemsForRead(false); } List avatarts = m_parentGroup.Scene.GetAvatars(); @@ -2457,17 +2462,16 @@ namespace OpenSim.Region.Framework.Scenes if (!UUID.TryParse(sound, out soundID)) { // search sound file from inventory - lock (TaskInventory) + TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair item in TaskInventory) { - foreach (KeyValuePair item in TaskInventory) + if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) { - if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) - { - soundID = item.Value.ItemID; - break; - } + soundID = item.Value.ItemID; + break; } } + TaskInventory.LockItemsForRead(false); } if (soundID == UUID.Zero) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index f4ca877..4dc709e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -80,7 +80,9 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal TaskInventoryDictionary Items { - get { return m_items; } + get { + return m_items; + } set { m_items = value; @@ -116,22 +118,25 @@ namespace OpenSim.Region.Framework.Scenes /// Link number for the part public void ResetInventoryIDs() { - lock (Items) + m_items.LockItemsForWrite(true); + + if (0 == Items.Count) { - if (0 == Items.Count) - return; + m_items.LockItemsForWrite(false); + return; + } - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - IList items = new List(Items.Values); - Items.Clear(); + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + IList items = new List(Items.Values); + Items.Clear(); - foreach (TaskInventoryItem item in items) - { - item.ResetIDs(m_part.UUID); - Items.Add(item.ItemID, item); - } + foreach (TaskInventoryItem item in items) + { + item.ResetIDs(m_part.UUID); + Items.Add(item.ItemID, item); } + m_items.LockItemsForWrite(false); } /// @@ -140,25 +145,25 @@ namespace OpenSim.Region.Framework.Scenes /// public void ChangeInventoryOwner(UUID ownerId) { - lock (Items) + m_items.LockItemsForWrite(true); + if (0 == Items.Count) { - if (0 == Items.Count) - { - return; - } + m_items.LockItemsForWrite(false); + return; + } - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - IList items = new List(Items.Values); - foreach (TaskInventoryItem item in items) + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + IList items = new List(Items.Values); + foreach (TaskInventoryItem item in items) + { + if (ownerId != item.OwnerID) { - if (ownerId != item.OwnerID) - { - item.LastOwnerID = item.OwnerID; - item.OwnerID = ownerId; - } + item.LastOwnerID = item.OwnerID; + item.OwnerID = ownerId; } } + m_items.LockItemsForWrite(false); } /// @@ -167,24 +172,24 @@ namespace OpenSim.Region.Framework.Scenes /// public void ChangeInventoryGroup(UUID groupID) { - lock (Items) + m_items.LockItemsForWrite(true); + if (0 == Items.Count) { - if (0 == Items.Count) - { - return; - } + m_items.LockItemsForWrite(false); + return; + } - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - IList items = new List(Items.Values); - foreach (TaskInventoryItem item in items) + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + IList items = new List(Items.Values); + foreach (TaskInventoryItem item in items) + { + if (groupID != item.GroupID) { - if (groupID != item.GroupID) - { - item.GroupID = groupID; - } + item.GroupID = groupID; } } + m_items.LockItemsForWrite(false); } /// @@ -192,14 +197,14 @@ namespace OpenSim.Region.Framework.Scenes /// public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) { - lock (m_items) + Items.LockItemsForRead(true); + IList items = new List(Items.Values); + Items.LockItemsForRead(false); + foreach (TaskInventoryItem item in items) { - foreach (TaskInventoryItem item in Items.Values) + if ((int)InventoryType.LSL == item.InvType) { - if ((int)InventoryType.LSL == item.InvType) - { - CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); - } + CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); } } } @@ -209,17 +214,20 @@ namespace OpenSim.Region.Framework.Scenes /// public void RemoveScriptInstances() { - lock (Items) + Items.LockItemsForRead(true); + IList items = new List(Items.Values); + Items.LockItemsForRead(false); + + foreach (TaskInventoryItem item in items) { - foreach (TaskInventoryItem item in Items.Values) + if ((int)InventoryType.LSL == item.InvType) { - if ((int)InventoryType.LSL == item.InvType) - { - RemoveScriptInstance(item.ItemID); - m_part.RemoveScriptEvents(item.ItemID); - } + RemoveScriptInstance(item.ItemID); + m_part.RemoveScriptEvents(item.ItemID); } } + + } /// @@ -244,8 +252,10 @@ namespace OpenSim.Region.Framework.Scenes if (stateSource == 1 && // Prim crossing m_part.ParentGroup.Scene.m_trustBinaries) { + m_items.LockItemsForWrite(true); m_items[item.ItemID].PermsMask = 0; m_items[item.ItemID].PermsGranter = UUID.Zero; + m_items.LockItemsForWrite(false); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); m_part.ParentGroup.AddActiveScriptCount(1); @@ -266,8 +276,10 @@ namespace OpenSim.Region.Framework.Scenes { if (m_part.ParentGroup.m_savedScriptState != null) RestoreSavedScriptState(item.OldItemID, item.ItemID); + m_items.LockItemsForWrite(true); m_items[item.ItemID].PermsMask = 0; m_items[item.ItemID].PermsGranter = UUID.Zero; + m_items.LockItemsForWrite(false); string script = Utils.BytesToString(asset.Data); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); @@ -302,20 +314,22 @@ namespace OpenSim.Region.Framework.Scenes /// public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) { - lock (m_items) + m_items.LockItemsForRead(true); + if (m_items.ContainsKey(itemId)) { - if (m_items.ContainsKey(itemId)) - { - CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", - itemId, m_part.Name, m_part.UUID); - } + TaskInventoryItem item = m_items[itemId]; + m_items.LockItemsForRead(false); + CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); } + else + { + m_items.LockItemsForRead(false); + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", + itemId, m_part.Name, m_part.UUID); + } + } /// @@ -346,11 +360,16 @@ namespace OpenSim.Region.Framework.Scenes /// private bool InventoryContainsName(string name) { - foreach (TaskInventoryItem item in Items.Values) + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) { if (item.Name == name) + { + m_items.LockItemsForRead(false); return true; + } } + m_items.LockItemsForRead(false); return false; } @@ -392,7 +411,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) { + m_items.LockItemsForRead(true); List il = new List(m_items.Values); + m_items.LockItemsForRead(false); foreach (TaskInventoryItem i in il) { if (i.Name == item.Name) @@ -429,15 +450,14 @@ namespace OpenSim.Region.Framework.Scenes item.ParentPartID = m_part.UUID; item.Name = name; - lock (m_items) - { - m_items.Add(item.ItemID, item); - + m_items.LockItemsForWrite(true); + m_items.Add(item.ItemID, item); + m_items.LockItemsForWrite(false); if (allowedDrop) m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); else m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - } + m_inventorySerial++; //m_inventorySerial += 2; @@ -454,14 +474,13 @@ namespace OpenSim.Region.Framework.Scenes /// public void RestoreInventoryItems(ICollection items) { - lock (m_items) + m_items.LockItemsForWrite(true); + foreach (TaskInventoryItem item in items) { - foreach (TaskInventoryItem item in items) - { - m_items.Add(item.ItemID, item); - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - } + m_items.Add(item.ItemID, item); + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); } + m_items.LockItemsForWrite(false); m_inventorySerial++; } @@ -474,8 +493,9 @@ namespace OpenSim.Region.Framework.Scenes public TaskInventoryItem GetInventoryItem(UUID itemId) { TaskInventoryItem item; + m_items.LockItemsForRead(true); m_items.TryGetValue(itemId, out item); - + m_items.LockItemsForRead(false); return item; } @@ -487,45 +507,45 @@ namespace OpenSim.Region.Framework.Scenes /// false if the item did not exist, true if the update occurred successfully public bool UpdateInventoryItem(TaskInventoryItem item) { - lock (m_items) + m_items.LockItemsForWrite(true); + + if (m_items.ContainsKey(item.ItemID)) { - if (m_items.ContainsKey(item.ItemID)) + item.ParentID = m_part.UUID; + item.ParentPartID = m_part.UUID; + item.Flags = m_items[item.ItemID].Flags; + if (item.AssetID == UUID.Zero) { - item.ParentID = m_part.UUID; - item.ParentPartID = m_part.UUID; - item.Flags = m_items[item.ItemID].Flags; - if (item.AssetID == UUID.Zero) - { - item.AssetID = m_items[item.ItemID].AssetID; - } - else if ((InventoryType)item.Type == InventoryType.Notecard) - { - ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID); + item.AssetID = m_items[item.ItemID].AssetID; + } + else if ((InventoryType)item.Type == InventoryType.Notecard) + { + ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID); - if (presence != null) - { - presence.ControllingClient.SendAgentAlertMessage( - "Notecard saved", false); - } + if (presence != null) + { + presence.ControllingClient.SendAgentAlertMessage( + "Notecard saved", false); } + } - m_items[item.ItemID] = item; - m_inventorySerial++; - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; + m_items[item.ItemID] = item; + m_inventorySerial++; + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - return true; - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", - item.ItemID, m_part.Name, m_part.UUID); - } + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + m_items.LockItemsForWrite(false); + return true; + } + else + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + item.ItemID, m_part.Name, m_part.UUID); } + m_items.LockItemsForWrite(false); return false; } @@ -538,51 +558,54 @@ namespace OpenSim.Region.Framework.Scenes /// in this prim's inventory. public int RemoveInventoryItem(UUID itemID) { - lock (m_items) + m_items.LockItemsForRead(true); + + if (m_items.ContainsKey(itemID)) { - if (m_items.ContainsKey(itemID)) + int type = m_items[itemID].InvType; + m_items.LockItemsForRead(false); + if (type == 10) // Script { - int type = m_items[itemID].InvType; - if (type == 10) // Script - { - m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); - } - m_items.Remove(itemID); - m_inventorySerial++; - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; + m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); + } + m_items.LockItemsForWrite(true); + m_items.Remove(itemID); + m_items.LockItemsForWrite(false); + m_inventorySerial++; + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - int scriptcount = 0; - lock (m_items) - { - foreach (TaskInventoryItem item in m_items.Values) - { - if (item.Type == 10) - { - scriptcount++; - } - } - } + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; - if (scriptcount <= 0) + int scriptcount = 0; + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.Type == 10) { - m_part.RemFlag(PrimFlags.Scripted); + scriptcount++; } - - m_part.ScheduleFullUpdate(); - - return type; } - else + m_items.LockItemsForRead(false); + + + if (scriptcount <= 0) { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", - itemID, m_part.Name, m_part.UUID); + m_part.RemFlag(PrimFlags.Scripted); } + + m_part.ScheduleFullUpdate(); + + return type; + } + else + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + itemID, m_part.Name, m_part.UUID); } + m_items.LockItemsForWrite(false); return -1; } @@ -635,52 +658,53 @@ namespace OpenSim.Region.Framework.Scenes // isn't available (such as drag from prim inventory to agent inventory) InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); - lock (m_items) + m_items.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) - { - UUID ownerID = item.OwnerID; - uint everyoneMask = 0; - uint baseMask = item.BasePermissions; - uint ownerMask = item.CurrentPermissions; + UUID ownerID = item.OwnerID; + uint everyoneMask = 0; + uint baseMask = item.BasePermissions; + uint ownerMask = item.CurrentPermissions; - invString.AddItemStart(); - invString.AddNameValueLine("item_id", item.ItemID.ToString()); - invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); + invString.AddItemStart(); + invString.AddNameValueLine("item_id", item.ItemID.ToString()); + invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); - invString.AddPermissionsStart(); + invString.AddPermissionsStart(); - invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); - invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); - invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); - invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); - invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); + invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); + invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); + invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); + invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); + invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); - invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); - invString.AddNameValueLine("owner_id", ownerID.ToString()); + invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); + invString.AddNameValueLine("owner_id", ownerID.ToString()); - invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); + invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); - invString.AddNameValueLine("group_id", item.GroupID.ToString()); - invString.AddSectionEnd(); + invString.AddNameValueLine("group_id", item.GroupID.ToString()); + invString.AddSectionEnd(); - invString.AddNameValueLine("asset_id", item.AssetID.ToString()); - invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); - invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); - invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); + invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); + invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); + invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); - invString.AddSaleStart(); - invString.AddNameValueLine("sale_type", "not"); - invString.AddNameValueLine("sale_price", "0"); - invString.AddSectionEnd(); + invString.AddSaleStart(); + invString.AddNameValueLine("sale_type", "not"); + invString.AddNameValueLine("sale_price", "0"); + invString.AddSectionEnd(); - invString.AddNameValueLine("name", item.Name + "|"); - invString.AddNameValueLine("desc", item.Description + "|"); + invString.AddNameValueLine("name", item.Name + "|"); + invString.AddNameValueLine("desc", item.Description + "|"); - invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); - invString.AddSectionEnd(); - } + invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); + invString.AddSectionEnd(); } + int count = m_items.Count; + m_items.LockItemsForRead(false); fileData = Utils.StringToBytes(invString.BuildString); @@ -689,6 +713,7 @@ namespace OpenSim.Region.Framework.Scenes if (fileData.Length > 2) { + m_log.Debug("Sending task inventory list of " + count.ToString() + " items to client " + client.AgentId.ToString()); xferManager.AddNewFile(m_inventoryFileName, fileData); } } @@ -701,10 +726,9 @@ namespace OpenSim.Region.Framework.Scenes { if (HasInventoryChanged) { - lock (Items) - { - datastore.StorePrimInventory(m_part.UUID, Items.Values); - } + Items.LockItemsForRead(true); + datastore.StorePrimInventory(m_part.UUID, Items.Values); + Items.LockItemsForRead(false); HasInventoryChanged = false; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 4e5fee1..4c8c94f 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1615,21 +1615,19 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); if (part != null) { + part.TaskInventory.LockItemsForRead(true); TaskInventoryDictionary taskIDict = part.TaskInventory; if (taskIDict != null) { - lock (taskIDict) + foreach (UUID taskID in taskIDict.Keys) { - foreach (UUID taskID in taskIDict.Keys) - { - UnRegisterControlEventsToScript(LocalId, taskID); - taskIDict[taskID].PermsMask &= ~( - 2048 | //PERMISSION_CONTROL_CAMERA - 4); // PERMISSION_TAKE_CONTROLS - } + UnRegisterControlEventsToScript(LocalId, taskID); + taskIDict[taskID].PermsMask &= ~( + 2048 | //PERMISSION_CONTROL_CAMERA + 4); // PERMISSION_TAKE_CONTROLS } - } + part.TaskInventory.LockItemsForRead(false); // Reset sit target. if (part.GetAvatarOnSitTarget() == UUID) part.SetAvatarOnSitTarget(UUID.Zero); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index b549b5c..a94cd46 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -275,40 +275,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected UUID InventorySelf() { UUID invItemID = new UUID(); - - lock (m_host.TaskInventory) + bool unlock = false; + if (!m_host.TaskInventory.IsReadLockedByMe()) + { + m_host.TaskInventory.LockItemsForRead(true); + unlock = true; + } + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) { - if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) - { - invItemID = inv.Key; - break; - } + invItemID = inv.Key; + break; } } - + if (unlock) + { + m_host.TaskInventory.LockItemsForRead(false); + } return invItemID; } protected UUID InventoryKey(string name, int type) { m_host.AddScriptLPS(1); - - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) + m_host.TaskInventory.LockItemsForRead(false); + + if (inv.Value.Type != type) { - if (inv.Value.Type != type) - return UUID.Zero; - - return inv.Value.AssetID; + return UUID.Zero; } + + return inv.Value.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); return UUID.Zero; } @@ -316,17 +324,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + + m_host.TaskInventory.LockItemsForRead(true); + + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) - { - return inv.Value.AssetID; - } + m_host.TaskInventory.LockItemsForRead(false); + return inv.Value.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); + + return UUID.Zero; } @@ -2537,12 +2549,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); + m_host.TaskInventory.LockItemsForRead(true); TaskInventoryItem item = m_host.TaskInventory[invItemID]; - - lock (m_host.TaskInventory) - { - item = m_host.TaskInventory[invItemID]; - } + m_host.TaskInventory.LockItemsForRead(false); if (item.PermsGranter == UUID.Zero) return 0; @@ -2617,6 +2626,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (dist > m_ScriptDistanceFactor * 10.0f) return; + //Clone is thread-safe TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); foreach (KeyValuePair inv in partInventory) @@ -2750,13 +2760,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; + } + else + { + item = m_host.TaskInventory[InventorySelf()]; } + m_host.TaskInventory.LockItemsForRead(false); if (item.PermsGranter != UUID.Zero) { @@ -2778,13 +2792,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { TaskInventoryItem item; + m_host.TaskInventory.LockItemsForRead(true); lock (m_host.TaskInventory) { + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + { + m_host.TaskInventory.LockItemsForRead(false); return; + } else + { item = m_host.TaskInventory[InventorySelf()]; + } } + m_host.TaskInventory.LockItemsForRead(false); m_host.AddScriptLPS(1); @@ -2821,14 +2843,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; + } + else + { + item = m_host.TaskInventory[InventorySelf()]; } + m_host.TaskInventory.LockItemsForRead(false); + if (item.PermsGranter != m_host.OwnerID) return; @@ -2853,13 +2881,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; + } + else + { + item = m_host.TaskInventory[InventorySelf()]; } + m_host.TaskInventory.LockItemsForRead(false); + if (item.PermsGranter != m_host.OwnerID) return; @@ -3083,14 +3117,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; } - + else + { + item = m_host.TaskInventory[InventorySelf()]; + } + m_host.TaskInventory.LockItemsForRead(false); if (item.PermsGranter == UUID.Zero) return; @@ -3120,13 +3157,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) - return; - else - item = m_host.TaskInventory[InventorySelf()]; + m_host.TaskInventory.LockItemsForRead(false); + return; } + else + { + item = m_host.TaskInventory[InventorySelf()]; + } + m_host.TaskInventory.LockItemsForRead(false); + if (item.PermsGranter == UUID.Zero) return; @@ -3199,10 +3241,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api TaskInventoryItem item; - lock (m_host.TaskInventory) + + m_host.TaskInventory.LockItemsForRead(true); + if (!m_host.TaskInventory.ContainsKey(invItemID)) + { + m_host.TaskInventory.LockItemsForRead(false); + return; + } + else { item = m_host.TaskInventory[invItemID]; } + m_host.TaskInventory.LockItemsForRead(false); if (agentID == UUID.Zero || perm == 0) // Releasing permissions { @@ -3234,11 +3284,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms { - lock (m_host.TaskInventory) - { - m_host.TaskInventory[invItemID].PermsGranter = agentID; - m_host.TaskInventory[invItemID].PermsMask = perm; - } + m_host.TaskInventory.LockItemsForWrite(true); + m_host.TaskInventory[invItemID].PermsGranter = agentID; + m_host.TaskInventory[invItemID].PermsMask = perm; + m_host.TaskInventory.LockItemsForWrite(false); m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { @@ -3258,11 +3307,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms { - lock (m_host.TaskInventory) - { - m_host.TaskInventory[invItemID].PermsGranter = agentID; - m_host.TaskInventory[invItemID].PermsMask = perm; - } + m_host.TaskInventory.LockItemsForWrite(true); + m_host.TaskInventory[invItemID].PermsGranter = agentID; + m_host.TaskInventory[invItemID].PermsMask = perm; + m_host.TaskInventory.LockItemsForWrite(false); m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { @@ -3283,11 +3331,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_waitingForScriptAnswer) { - lock (m_host.TaskInventory) - { - m_host.TaskInventory[invItemID].PermsGranter = agentID; - m_host.TaskInventory[invItemID].PermsMask = 0; - } + m_host.TaskInventory.LockItemsForWrite(true); + m_host.TaskInventory[invItemID].PermsGranter = agentID; + m_host.TaskInventory[invItemID].PermsMask = 0; + m_host.TaskInventory.LockItemsForWrite(false); presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; m_waitingForScriptAnswer=true; @@ -3322,10 +3369,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) llReleaseControls(); - lock (m_host.TaskInventory) - { - m_host.TaskInventory[invItemID].PermsMask = answer; - } + + m_host.TaskInventory.LockItemsForWrite(true); + m_host.TaskInventory[invItemID].PermsMask = answer; + m_host.TaskInventory.LockItemsForWrite(false); + m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { @@ -3337,16 +3385,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == 10 && item.ItemID == m_itemID) { - if (item.Type == 10 && item.ItemID == m_itemID) - { - return item.PermsGranter.ToString(); - } + m_host.TaskInventory.LockItemsForRead(false); + return item.PermsGranter.ToString(); } } + m_host.TaskInventory.LockItemsForRead(false); return UUID.Zero.ToString(); } @@ -3355,19 +3404,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == 10 && item.ItemID == m_itemID) { - if (item.Type == 10 && item.ItemID == m_itemID) - { - int perms = item.PermsMask; - if (m_automaticLinkPermission) - perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; - return perms; - } + int perms = item.PermsMask; + if (m_automaticLinkPermission) + perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; + m_host.TaskInventory.LockItemsForRead(false); + return perms; } } + m_host.TaskInventory.LockItemsForRead(false); return 0; } @@ -3400,11 +3450,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID invItemID = InventorySelf(); TaskInventoryItem item; - lock (m_host.TaskInventory) - { - item = m_host.TaskInventory[invItemID]; - } - + m_host.TaskInventory.LockItemsForRead(true); + item = m_host.TaskInventory[invItemID]; + m_host.TaskInventory.LockItemsForRead(false); + if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 && !m_automaticLinkPermission) { @@ -3457,16 +3506,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); UUID invItemID = InventorySelf(); - lock (m_host.TaskInventory) - { + m_host.TaskInventory.LockItemsForRead(true); if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 && !m_automaticLinkPermission) { ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); + m_host.TaskInventory.LockItemsForRead(false); return; } - } - + m_host.TaskInventory.LockItemsForRead(false); + if (linknum < ScriptBaseClass.LINK_THIS) return; @@ -3635,17 +3684,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); int count = 0; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Type == type || type == -1) { - if (inv.Value.Type == type || type == -1) - { - count = count + 1; - } + count = count + 1; } } - + + m_host.TaskInventory.LockItemsForRead(false); return count; } @@ -3654,16 +3702,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); ArrayList keys = new ArrayList(); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Type == type || type == -1) { - if (inv.Value.Type == type || type == -1) - { - keys.Add(inv.Value.Name); - } + keys.Add(inv.Value.Name); } } + m_host.TaskInventory.LockItemsForRead(false); if (keys.Count == 0) { @@ -3700,20 +3747,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // move the first object found with this inventory name - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == inventory) { - if (inv.Value.Name == inventory) - { - found = true; - objId = inv.Key; - assetType = inv.Value.Type; - objName = inv.Value.Name; - break; - } + found = true; + objId = inv.Key; + assetType = inv.Value.Type; + objName = inv.Value.Name; + break; } } + m_host.TaskInventory.LockItemsForRead(false); if (!found) { @@ -3763,20 +3809,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Name == name) { - if (item.Name == name) - { - if (item.ItemID == m_itemID) - throw new ScriptDeleteException(); - else - m_host.Inventory.RemoveInventoryItem(item.ItemID); - return; - } + if (item.ItemID == m_itemID) + throw new ScriptDeleteException(); + else + m_host.Inventory.RemoveInventoryItem(item.ItemID); + + m_host.TaskInventory.LockItemsForRead(false); + return; } } + m_host.TaskInventory.LockItemsForRead(false); } public void llSetText(string text, LSL_Vector color, double alpha) @@ -3865,6 +3912,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); + //Clone is thread safe TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); foreach (TaskInventoryItem item in itemDictionary.Values) @@ -3955,17 +4003,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID soundId = UUID.Zero; if (!UUID.TryParse(impact_sound, out soundId)) { - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) { - if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) - { - soundId = item.AssetID; - break; - } + soundId = item.AssetID; + break; } } + m_host.TaskInventory.LockItemsForRead(false); } m_host.CollisionSound = soundId; m_host.CollisionSoundVolume = (float)impact_volume; @@ -4011,6 +4058,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID partItemID; foreach (SceneObjectPart part in parts) { + //Clone is thread safe TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); foreach (TaskInventoryItem item in itemsDictionary.Values) @@ -4218,17 +4266,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == 10 && item.ItemID == m_itemID) { - if (item.Type == 10 && item.ItemID == m_itemID) - { - result = item.Name!=null?item.Name:String.Empty; - break; - } + result = item.Name!=null?item.Name:String.Empty; + break; } } + m_host.TaskInventory.LockItemsForRead(false); return result; } @@ -4486,23 +4533,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) + if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) { - if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) - { - return inv.Value.AssetID.ToString(); - } - else - { - return UUID.Zero.ToString(); - } + m_host.TaskInventory.LockItemsForRead(false); + return inv.Value.AssetID.ToString(); + } + else + { + m_host.TaskInventory.LockItemsForRead(false); + return UUID.Zero.ToString(); } } } + m_host.TaskInventory.LockItemsForRead(false); return UUID.Zero.ToString(); } @@ -5997,14 +6045,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected UUID GetTaskInventoryItem(string name) { - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) - return inv.Key; + m_host.TaskInventory.LockItemsForRead(false); + return inv.Key; } } + m_host.TaskInventory.LockItemsForRead(false); return UUID.Zero; } @@ -6315,22 +6365,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // copy the first script found with this inventory name - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) + // make sure the object is a script + if (10 == inv.Value.Type) { - // make sure the object is a script - if (10 == inv.Value.Type) - { - found = true; - srcId = inv.Key; - break; - } + found = true; + srcId = inv.Key; + break; } } } + m_host.TaskInventory.LockItemsForRead(false); if (!found) { @@ -8133,28 +8182,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == item) { - if (inv.Value.Name == item) + m_host.TaskInventory.LockItemsForRead(false); + switch (mask) { - switch (mask) - { - case 0: - return (int)inv.Value.BasePermissions; - case 1: - return (int)inv.Value.CurrentPermissions; - case 2: - return (int)inv.Value.GroupPermissions; - case 3: - return (int)inv.Value.EveryonePermissions; - case 4: - return (int)inv.Value.NextPermissions; - } + case 0: + return (int)inv.Value.BasePermissions; + case 1: + return (int)inv.Value.CurrentPermissions; + case 2: + return (int)inv.Value.GroupPermissions; + case 3: + return (int)inv.Value.EveryonePermissions; + case 4: + return (int)inv.Value.NextPermissions; } } } + m_host.TaskInventory.LockItemsForRead(false); return -1; } @@ -8169,16 +8218,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == item) { - if (inv.Value.Name == item) - { - return inv.Value.CreatorID.ToString(); - } + m_host.TaskInventory.LockItemsForRead(false); + return inv.Value.CreatorID.ToString(); } } + m_host.TaskInventory.LockItemsForRead(false); llSay(0, "No item name '" + item + "'"); @@ -8702,16 +8751,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == name) { - if (inv.Value.Name == name) - { - return inv.Value.Type; - } + m_host.TaskInventory.LockItemsForRead(false); + return inv.Value.Type; } } + m_host.TaskInventory.LockItemsForRead(false); return -1; } @@ -8742,17 +8791,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (invItemID == UUID.Zero) return new LSL_Vector(); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) { - if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) - return new LSL_Vector(); + m_host.TaskInventory.LockItemsForRead(false); + return new LSL_Vector(); + } - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) - { - ShoutError("No permissions to track the camera"); - return new LSL_Vector(); - } + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) + { + ShoutError("No permissions to track the camera"); + m_host.TaskInventory.LockItemsForRead(false); + return new LSL_Vector(); } + m_host.TaskInventory.LockItemsForRead(false); ScenePresence presence = World.GetScenePresence(m_host.OwnerID); if (presence != null) @@ -8770,17 +8822,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (invItemID == UUID.Zero) return new LSL_Rotation(); - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) { - if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) - return new LSL_Rotation(); - - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) - { - ShoutError("No permissions to track the camera"); - return new LSL_Rotation(); - } + m_host.TaskInventory.LockItemsForRead(false); + return new LSL_Rotation(); } + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) + { + ShoutError("No permissions to track the camera"); + m_host.TaskInventory.LockItemsForRead(false); + return new LSL_Rotation(); + } + m_host.TaskInventory.LockItemsForRead(false); ScenePresence presence = World.GetScenePresence(m_host.OwnerID); if (presence != null) @@ -8930,14 +8984,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (objectID == UUID.Zero) return; UUID agentID; - lock (m_host.TaskInventory) - { - // we need the permission first, to know which avatar we want to set the camera for - agentID = m_host.TaskInventory[invItemID].PermsGranter; + m_host.TaskInventory.LockItemsForRead(true); + // we need the permission first, to know which avatar we want to set the camera for + agentID = m_host.TaskInventory[invItemID].PermsGranter; - if (agentID == UUID.Zero) return; - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; + if (agentID == UUID.Zero) + { + m_host.TaskInventory.LockItemsForRead(false); + return; + } + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) + { + m_host.TaskInventory.LockItemsForRead(false); + return; } + m_host.TaskInventory.LockItemsForRead(false); ScenePresence presence = World.GetScenePresence(agentID); @@ -8987,12 +9048,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // we need the permission first, to know which avatar we want to clear the camera for UUID agentID; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + agentID = m_host.TaskInventory[invItemID].PermsGranter; + if (agentID == UUID.Zero) { - agentID = m_host.TaskInventory[invItemID].PermsGranter; - if (agentID == UUID.Zero) return; - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; + m_host.TaskInventory.LockItemsForRead(false); + return; } + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) + { + m_host.TaskInventory.LockItemsForRead(false); + return; + } + m_host.TaskInventory.LockItemsForRead(false); ScenePresence presence = World.GetScenePresence(agentID); @@ -9449,15 +9517,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal UUID ScriptByName(string name) { - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + if (item.Type == 10 && item.Name == name) { - if (item.Type == 10 && item.Name == name) - return item.ItemID; + m_host.TaskInventory.LockItemsForRead(false); + return item.ItemID; } } + m_host.TaskInventory.LockItemsForRead(false); + return UUID.Zero; } @@ -9498,6 +9570,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); + //Clone is thread safe TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); UUID assetID = UUID.Zero; @@ -9560,6 +9633,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); + //Clone is thread safe TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); UUID assetID = UUID.Zero; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 7fdbac8..83322eb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -728,18 +728,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (target != null) { UUID animID=UUID.Zero; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == animation) { - if (inv.Value.Name == animation) - { - if (inv.Value.Type == (int)AssetType.Animation) - animID = inv.Value.AssetID; - continue; - } + if (inv.Value.Type == (int)AssetType.Animation) + animID = inv.Value.AssetID; + continue; } } + m_host.TaskInventory.LockItemsForRead(false); if (animID == UUID.Zero) target.Animator.AddAnimation(animation, m_host.UUID); else @@ -761,18 +760,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (target != null) { UUID animID=UUID.Zero; - lock (m_host.TaskInventory) + m_host.TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair inv in m_host.TaskInventory) { - foreach (KeyValuePair inv in m_host.TaskInventory) + if (inv.Value.Name == animation) { - if (inv.Value.Name == animation) - { - if (inv.Value.Type == (int)AssetType.Animation) - animID = inv.Value.AssetID; - continue; - } + if (inv.Value.Type == (int)AssetType.Animation) + animID = inv.Value.AssetID; + continue; } } + m_host.TaskInventory.LockItemsForRead(false); if (animID == UUID.Zero) target.Animator.RemoveAnimation(animation); @@ -1541,6 +1539,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(name, out assetID)) { + m_host.TaskInventory.LockItemsForRead(true); foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { if (item.Type == 7 && item.Name == name) @@ -1548,6 +1547,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api assetID = item.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); } if (assetID == UUID.Zero) @@ -1594,6 +1594,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(name, out assetID)) { + m_host.TaskInventory.LockItemsForRead(true); foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { if (item.Type == 7 && item.Name == name) @@ -1601,6 +1602,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api assetID = item.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); } if (assetID == UUID.Zero) @@ -1651,6 +1653,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(name, out assetID)) { + m_host.TaskInventory.LockItemsForRead(true); foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { if (item.Type == 7 && item.Name == name) @@ -1658,6 +1661,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api assetID = item.AssetID; } } + m_host.TaskInventory.LockItemsForRead(false); } if (assetID == UUID.Zero) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 063d50f..0f4a9ad 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -238,13 +238,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance if (part != null) { - lock (part.TaskInventory) + part.TaskInventory.LockItemsForRead(true); + if (part.TaskInventory.ContainsKey(m_ItemID)) { - if (part.TaskInventory.ContainsKey(m_ItemID)) - { - m_thisScriptTask = part.TaskInventory[m_ItemID]; - } + m_thisScriptTask = part.TaskInventory[m_ItemID]; } + part.TaskInventory.LockItemsForRead(false); } ApiManager am = new ApiManager(); @@ -429,14 +428,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { int permsMask; UUID permsGranter; - lock (part.TaskInventory) + part.TaskInventory.LockItemsForRead(true); + if (!part.TaskInventory.ContainsKey(m_ItemID)) { - if (!part.TaskInventory.ContainsKey(m_ItemID)) - return; - - permsGranter = part.TaskInventory[m_ItemID].PermsGranter; - permsMask = part.TaskInventory[m_ItemID].PermsMask; + part.TaskInventory.LockItemsForRead(false); + return; } + permsGranter = part.TaskInventory[m_ItemID].PermsGranter; + permsMask = part.TaskInventory[m_ItemID].PermsMask; + part.TaskInventory.LockItemsForRead(false); if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) { -- cgit v1.1 From 8383bde76880fc94a6644422d45baa28252b0231 Mon Sep 17 00:00:00 2001 From: CasperW Date: Tue, 24 Nov 2009 18:18:19 +0100 Subject: Removed some extra debug chatter --- .../CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index d9a021f..b60b32b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -389,7 +389,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { // Check if this is ours to handle // - m_log.Info("OnFridInstantMessage"); + //m_log.Info("OnFridInstantMessage"); if (msg.dialog != (byte) InstantMessageDialog.InventoryOffered) return; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 4dc709e..abb04cd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -713,7 +713,6 @@ namespace OpenSim.Region.Framework.Scenes if (fileData.Length > 2) { - m_log.Debug("Sending task inventory list of " + count.ToString() + " items to client " + client.AgentId.ToString()); xferManager.AddNewFile(m_inventoryFileName, fileData); } } -- cgit v1.1 From d5aceb6d95779b19d13eef9f2427c79233166a63 Mon Sep 17 00:00:00 2001 From: CasperW Date: Tue, 24 Nov 2009 23:33:12 +0100 Subject: Append a prefix to the god avatar names appearing in chat whilst in god mode (disabled by default, config entry admin_prefix) --- OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | 11 ++++++++--- bin/OpenSim.ini.example | 3 +++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 5c24f03..1e63e3e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat private int m_shoutdistance = 100; private int m_whisperdistance = 10; private List m_scenes = new List(); - + private string m_adminPrefix = ""; internal object m_syncy = new object(); internal IConfig m_config; @@ -76,6 +76,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat m_whisperdistance = config.Configs["Chat"].GetInt("whisper_distance", m_whisperdistance); m_saydistance = config.Configs["Chat"].GetInt("say_distance", m_saydistance); m_shoutdistance = config.Configs["Chat"].GetInt("shout_distance", m_shoutdistance); + m_adminPrefix = config.Configs["Chat"].GetString("admin_prefix", ""); } public virtual void AddRegion(Scene scene) @@ -185,6 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat protected virtual void DeliverChatToAvatars(ChatSourceType sourceType, OSChatMessage c) { string fromName = c.From; + string fromNamePrefix = ""; UUID fromID = UUID.Zero; string message = c.Message; IScene scene = c.Scene; @@ -207,7 +209,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat fromPos = avatar.AbsolutePosition; fromName = avatar.Name; fromID = c.Sender.AgentId; - + if (avatar.GodLevel > 200) + { + fromNamePrefix = m_adminPrefix; + } break; case ChatSourceType.Object: @@ -227,7 +232,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat s.ForEachScenePresence( delegate(ScenePresence presence) { - TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType); + TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix+fromName, c.Type, message, sourceType); } ); } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 116a8fd..f9d9ca6 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -454,6 +454,9 @@ ; Distance in meters that shouts should travel. Default is 100m shout_distance = 100 + + ; Append a prefix to the god avatar names appearing in chat whilst in god mode + ; admin_prefix = "@" [Messaging] -- cgit v1.1 From 32c464ad1f43cbee9492108c1bec7f874a20cd47 Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Wed, 25 Nov 2009 08:03:09 +0100 Subject: Fixed animation sequencing: SitHere, Falling, Stand/Walk etc. Login Init Av Animation at Stand. --- .../Scenes/Animation/ScenePresenceAnimator.cs | 15 ++++++---- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 34 +++++++++++++++------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 30a95ce..2d41342 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -53,8 +53,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation { get { return m_movementAnimation; } } - protected string m_movementAnimation = "DEFAULT"; - + // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist! + protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init. private int m_animTickFall; private int m_animTickJump; @@ -123,17 +123,22 @@ namespace OpenSim.Region.Framework.Scenes.Animation /// public void TrySetMovementAnimation(string anim) { - //m_log.DebugFormat("Updating movement animation to {0}", anim); +//Console.WriteLine("Updating movement animation to {0}", anim); if (!m_scenePresence.IsChildAgent) { if (m_animations.TrySetDefaultAnimation( anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero)) { +//Console.WriteLine("TSMA {0} success.", anim); // 16384 is CHANGED_ANIMATION m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 }); SendAnimPack(); } + else + { +//Console.WriteLine("TSMA {0} fail.", anim); + } } } @@ -313,7 +318,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation public void UpdateMovementAnimations() { m_movementAnimation = GetMovementAnimation(); - +//Console.WriteLine("UMA got {0}", m_movementAnimation); if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) { // This was the previous behavior before PREJUMP @@ -445,4 +450,4 @@ namespace OpenSim.Region.Framework.Scenes.Animation SendAnimPack(animIDs, sequenceNums, objectIDs); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 4e5fee1..a65b84b 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -90,6 +90,7 @@ namespace OpenSim.Region.Framework.Scenes /// issue #1716 /// // private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); + // Value revised by KF 091121 by comparison with SL. private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); public UUID currentParcelUUID = UUID.Zero; @@ -205,6 +206,9 @@ namespace OpenSim.Region.Framework.Scenes private bool m_followCamAuto; private int m_movementUpdateCount; + private int m_lastColCount = -1; //KF: Look for Collision chnages + private int m_updateCount = 0; //KF: Update Anims for a while + private static readonly int UPDATE_COUNT = 10; // how many frames to update for private const int NumMovementsBetweenRayCast = 5; @@ -662,9 +666,7 @@ namespace OpenSim.Region.Framework.Scenes AdjustKnownSeeds(); - // TODO: I think, this won't send anything, as we are still a child here... - Animator.TrySetMovementAnimation("STAND"); - + Animator.TrySetMovementAnimation("STAND"); // we created a new ScenePresence (a new child agent) in a fresh region. // Request info about all the (root) agents in this region // Note: This won't send data *to* other clients in that region (children don't send) @@ -1018,7 +1020,9 @@ namespace OpenSim.Region.Framework.Scenes { AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); } - + + m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim. + ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); } @@ -1266,9 +1270,7 @@ namespace OpenSim.Region.Framework.Scenes if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) { - // TODO: This doesn't prevent the user from walking yet. - // Setting parent ID would fix this, if we knew what value - // to use. Or we could add a m_isSitting variable. + m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); } @@ -1926,7 +1928,6 @@ namespace OpenSim.Region.Framework.Scenes public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance) { -// Console.WriteLine("[RAYCASTRESULT]: Hit={0}, Point={1}, ID={2}, Dist={3}", hitYN, collisionPoint, localid, distance); if(hitYN) { // m_pos = Av offset from prim center to make look like on center @@ -2964,6 +2965,7 @@ namespace OpenSim.Region.Framework.Scenes m_updateflag = true; Velocity = force; m_isNudging = false; + m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND" } } } @@ -3015,19 +3017,29 @@ namespace OpenSim.Region.Framework.Scenes // Event called by the physics plugin to tell the avatar about a collision. private void PhysicsCollisionUpdate(EventArgs e) { + if (m_updateCount > 0) //KF: Update Anims for a short period. Many Anim + { // changes are very asynchronous. + Animator.UpdateMovementAnimations(); + m_updateCount--; + } + if (e == null) return; - //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents( // as of this comment the interval is set in AddToPhysicalScene - Animator.UpdateMovementAnimations(); - + CollisionEventUpdate collisionData = (CollisionEventUpdate)e; Dictionary coldata = collisionData.m_objCollisionList; CollisionPlane = Vector4.UnitW; + if (m_lastColCount != coldata.Count) + { + m_updateCount = 10; + m_lastColCount = coldata.Count; + } + if (coldata.Count != 0) { switch (Animator.CurrentMovementAnimation) -- cgit v1.1 From c81f37cf82c3a9d2aae92d5f44734fc5098c5b75 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 25 Nov 2009 17:01:41 +0000 Subject: Change osTeleportAgent parameters from long to int. That numerical range is not even supported by the underlying type, so there is no need to ask for a type the script can not even supply. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 4 ++-- OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 2 +- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 83322eb..10165d3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -636,13 +636,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // Teleport functions - public void osTeleportAgent(string agent, uint regionX, uint regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) + public void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) { // High because there is no security check. High griefer potential // CheckThreatLevel(ThreatLevel.High, "osTeleportAgent"); - ulong regionHandle = Util.UIntsToLong((regionX * (uint)Constants.RegionSize), (regionY * (uint)Constants.RegionSize)); + ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize)); m_host.AddScriptLPS(1); UUID agentId = new UUID(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 2a403bf..470946a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -83,7 +83,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces // Teleport commands void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); - void osTeleportAgent(string agent, uint regionX, uint regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); + void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); void osTeleportAgent(string agent, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); // Animation commands diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 4928e90..6b88834 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -201,9 +201,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osTeleportAgent(agent, regionName, position, lookat); } - public void osTeleportAgent(string agent, long regionX, long regionY, vector position, vector lookat) + public void osTeleportAgent(string agent, int regionX, int regionY, vector position, vector lookat) { - m_OSSL_Functions.osTeleportAgent(agent, (uint) regionX, (uint) regionY, position, lookat); + m_OSSL_Functions.osTeleportAgent(agent, regionX, regionY, position, lookat); } public void osTeleportAgent(string agent, vector position, vector lookat) -- cgit v1.1 From de927adf2709f50d0fe85a1c59e7677d862d0d72 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 25 Nov 2009 20:01:21 +0000 Subject: Add the dummy "Size" property to the list type --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 3f38bb6..1fc31c5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -429,6 +429,11 @@ namespace OpenSim.Region.ScriptEngine.Shared } } + public int Size + { + get { return 0; } + } + public object[] Data { get { -- cgit v1.1 From b9d22aa8213b62eb0c368b345ccfc105367c1aba Mon Sep 17 00:00:00 2001 From: CasperW Date: Thu, 26 Nov 2009 01:59:08 +0100 Subject: Add nudge right and left to avatar movement (faster reaction times when stepping left or right.) --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 4c8c94f..9b04422 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -169,7 +169,7 @@ namespace OpenSim.Region.Framework.Scenes protected RegionInfo m_regionInfo; protected ulong crossingFromRegion; - private readonly Vector3[] Dir_Vectors = new Vector3[9]; + private readonly Vector3[] Dir_Vectors = new Vector3[11]; private bool m_isNudging = false; // Position of agent's camera in world (region cordinates) @@ -236,6 +236,8 @@ namespace OpenSim.Region.Framework.Scenes DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, + DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, + DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG } @@ -722,12 +724,14 @@ namespace OpenSim.Region.Framework.Scenes Dir_Vectors[5] = -Vector3.UnitZ; //DOWN Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE - Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge + Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE + Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE + Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge } private Vector3[] GetWalkDirectionVectors() { - Vector3[] vector = new Vector3[9]; + Vector3[] vector = new Vector3[11]; vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK vector[2] = Vector3.UnitY; //LEFT @@ -736,13 +740,15 @@ namespace OpenSim.Region.Framework.Scenes vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE - vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge + vector[8] = Vector3.UnitY; //LEFT_NUDGE + vector[9] = -Vector3.UnitY; //RIGHT_NUDGE + vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge return vector; } private bool[] GetDirectionIsNudge() { - bool[] isNudge = new bool[9]; + bool[] isNudge = new bool[11]; isNudge[0] = false; //FORWARD isNudge[1] = false; //BACK isNudge[2] = false; //LEFT @@ -751,7 +757,9 @@ namespace OpenSim.Region.Framework.Scenes isNudge[5] = false; //DOWN isNudge[6] = true; //FORWARD_NUDGE isNudge[7] = true; //BACK_NUDGE - isNudge[8] = true; //DOWN_Nudge + isNudge[8] = true; //LEFT_NUDGE + isNudge[9] = true; //RIGHT_NUDGE + isNudge[10] = true; //DOWN_Nudge return isNudge; } -- cgit v1.1 From 63b6b9cdce6382e2285b1a9d76e68a0ac10602ef Mon Sep 17 00:00:00 2001 From: CasperW Date: Thu, 26 Nov 2009 02:35:27 +0100 Subject: Added animation support for my last commit --- OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs | 4 ++-- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 30a95ce..2c4a4b0 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -158,8 +158,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation // Check control flags bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS); bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); - bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; - bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG; + bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); + bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG); //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 9b04422..a1bb244 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -742,7 +742,7 @@ namespace OpenSim.Region.Framework.Scenes vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE vector[8] = Vector3.UnitY; //LEFT_NUDGE vector[9] = -Vector3.UnitY; //RIGHT_NUDGE - vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge + vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE return vector; } -- cgit v1.1 From ac2fcbe224d4877dccc4d73e9c58771e40a4ae1c Mon Sep 17 00:00:00 2001 From: CasperW Date: Thu, 26 Nov 2009 15:17:44 +0100 Subject: Improvements to rAdmin admin_shutdown and admin_restart. Both methods can now accept a parameter of noticetype = dialog in order to display a blue persistant dropdown instead of a short notice. Added an optional and configurable delay to the restart method, defaulting at 30 seconds as before. Both methods can also accept a noticetype = none dialog in order to act silently. --- .../RemoteController/RemoteAdminPlugin.cs | 74 +++++++++++++++++++++- OpenSim/Region/Framework/Scenes/Scene.cs | 16 ++++- 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 3bc557d..325816d 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -213,9 +213,59 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (!m_app.SceneManager.TryGetScene(regionID, out rebootedScene)) throw new Exception("region not found"); + int timeout = 30000; + string message; + + if (requestData.ContainsKey("restart") + && ((string)requestData["restart"] == "delayed") + && requestData.ContainsKey("milliseconds")) + { + timeout = Int32.Parse(requestData["milliseconds"].ToString()); + + if (timeout < 15000) + { + //It must be at least 15 seconds or we'll cancel the reboot request + timeout = 15000; + } + + message + = "Region is restarting in " + ((int)(timeout / 1000)).ToString() + + " second(s). Please save what you are doing and log out."; + } + else + { + message = "Region is restarting in 30 second(s). Please save what you are doing and log out."; + } + + if (requestData.ContainsKey("noticetype") + && ((string)requestData["noticetype"] == "dialog")) + { + m_app.SceneManager.ForEachScene( + delegate(Scene scene) + { + IDialogModule dialogModule = scene.RequestModuleInterface(); + if (dialogModule != null) + dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message); + }); + } + else + { + if (!requestData.ContainsKey("noticetype") + || ((string)requestData["noticetype"] != "none")) + { + m_app.SceneManager.ForEachScene( + delegate(Scene scene) + { + IDialogModule dialogModule = scene.RequestModuleInterface(); + if (dialogModule != null) + dialogModule.SendGeneralAlert(message); + }); + } + } + responseData["rebooting"] = true; response.Value = responseData; - rebootedScene.Restart(30); + rebootedScene.Restart(timeout / 1000,false); } catch (Exception e) { @@ -419,13 +469,33 @@ namespace OpenSim.ApplicationPlugins.RemoteController message = "Region is going down now."; } - m_app.SceneManager.ForEachScene( + if (requestData.ContainsKey("noticetype") + && ((string) requestData["noticetype"] == "dialog")) + { + m_app.SceneManager.ForEachScene( delegate(Scene scene) { IDialogModule dialogModule = scene.RequestModuleInterface(); if (dialogModule != null) + dialogModule.SendNotificationToUsersInRegion(UUID.Zero, "System", message); + }); + } + else + { + if (!requestData.ContainsKey("noticetype") + || ((string)requestData["noticetype"] != "none")) + { + m_app.SceneManager.ForEachScene( + delegate(Scene scene) + { + IDialogModule dialogModule = scene.RequestModuleInterface(); + if (dialogModule != null) dialogModule.SendGeneralAlert(message); }); + } + } + + // Perform shutdown System.Timers.Timer shutdownTimer = new System.Timers.Timer(timeout); // Wait before firing diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 4ffa1a2..be1d4bf 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -873,6 +873,15 @@ namespace OpenSim.Region.Framework.Scenes /// float indicating duration before restart. public virtual void Restart(float seconds) { + Restart(seconds, true); + } + + /// + /// Given float seconds, this will restart the region. showDialog will optionally alert the users. + /// + /// float indicating duration before restart. + public virtual void Restart(float seconds, bool showDialog) + { // notifications are done in 15 second increments // so .. if the number of seconds is less then 15 seconds, it's not really a restart request // It's a 'Cancel restart' request. @@ -893,8 +902,11 @@ namespace OpenSim.Region.Framework.Scenes m_restartTimer.Elapsed += new ElapsedEventHandler(RestartTimer_Elapsed); m_log.Info("[REGION]: Restarting Region in " + (seconds / 60) + " minutes"); m_restartTimer.Start(); - m_dialogModule.SendNotificationToUsersInRegion( - UUID.Random(), String.Empty, RegionInfo.RegionName + ": Restarting in 2 Minutes"); + if (showDialog) + { + m_dialogModule.SendNotificationToUsersInRegion( + UUID.Random(), String.Empty, RegionInfo.RegionName + ": Restarting in " + (seconds / 60).ToString() + " Minutes"); + } } } -- cgit v1.1 From 22c325aa5ae06b897e5eb10404c0aa3727f8237b Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 26 Nov 2009 12:08:20 +0000 Subject: Remove GetAssemblyName and friends from the SE interface. It's now handled internally --- .../Framework/Interfaces/IEntityInventory.cs | 6 -- .../Region/Framework/Interfaces/IScriptModule.cs | 1 - .../Framework/Scenes/SceneObjectGroup.Inventory.cs | 93 ++------------------- .../Framework/Scenes/SceneObjectPartInventory.cs | 30 ------- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 95 ++++++++++++++++++++-- 5 files changed, 91 insertions(+), 134 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 2c906a2..2998f45 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -185,12 +185,6 @@ namespace OpenSim.Region.Framework.Interfaces List GetInventoryList(); /// - /// Get the names of the assemblies associated with scripts in this inventory. - /// - /// - string[] GetScriptAssemblies(); - - /// /// Get the xml representing the saved states of scripts in this inventory. /// /// diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index 10835b9..72bb0f0 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -34,7 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces { string ScriptEngineName { get; } - string GetAssemblyName(UUID itemID); string GetXMLState(UUID itemID); bool CanBeDeleted(UUID itemID); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 3cec77f..9a6f2b8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -309,26 +309,15 @@ namespace OpenSim.Region.Framework.Scenes public string GetStateSnapshot() { - //m_log.Debug(" >>> GetStateSnapshot <<<"); - - List assemblies = new List(); Dictionary states = new Dictionary(); foreach (SceneObjectPart part in m_parts.Values) { - foreach (string a in part.Inventory.GetScriptAssemblies()) - { - if (a != "" && !assemblies.Contains(a)) - assemblies.Add(a); - } - foreach (KeyValuePair s in part.Inventory.GetScriptStates()) - { states[s.Key] = s.Value; - } } - if (states.Count < 1 || assemblies.Count < 1) + if (states.Count < 1) return ""; XmlDocument xmldoc = new XmlDocument(); @@ -342,94 +331,21 @@ namespace OpenSim.Region.Framework.Scenes xmldoc.AppendChild(rootElement); - XmlElement wrapper = xmldoc.CreateElement("", "Assemblies", - ""); - rootElement.AppendChild(wrapper); - - foreach (string assembly in assemblies) - { - string fn = Path.GetFileName(assembly); - if (fn == String.Empty) - continue; - - String filedata = String.Empty; - - if (File.Exists(assembly+".text")) - { - FileInfo tfi = new FileInfo(assembly+".text"); - - if (tfi == null) - continue; - - Byte[] tdata = new Byte[tfi.Length]; - - try - { - FileStream tfs = File.Open(assembly+".text", FileMode.Open, FileAccess.Read); - tfs.Read(tdata, 0, tdata.Length); - tfs.Close(); - } - catch (Exception e) - { - m_log.DebugFormat("[SOG]: Unable to open script textfile {0}, reason: {1}", assembly+".text", e.Message); - } - - filedata = new System.Text.ASCIIEncoding().GetString(tdata); - } - else - { - FileInfo fi = new FileInfo(assembly); - - if (fi == null) - continue; - - Byte[] data = new Byte[fi.Length]; - - try - { - FileStream fs = File.Open(assembly, FileMode.Open, FileAccess.Read); - fs.Read(data, 0, data.Length); - fs.Close(); - } - catch (Exception e) - { - m_log.DebugFormat("[SOG]: Unable to open script assembly {0}, reason: {1}", assembly, e.Message); - } - - filedata = System.Convert.ToBase64String(data); - } - XmlElement assemblyData = xmldoc.CreateElement("", "Assembly", ""); - XmlAttribute assemblyName = xmldoc.CreateAttribute("", "Filename", ""); - assemblyName.Value = fn; - assemblyData.Attributes.Append(assemblyName); - - assemblyData.InnerText = filedata; - - wrapper.AppendChild(assemblyData); - } - - wrapper = xmldoc.CreateElement("", "ScriptStates", + XmlElement wrapper = xmldoc.CreateElement("", "ScriptStates", ""); rootElement.AppendChild(wrapper); foreach (KeyValuePair state in states) { - XmlElement stateData = xmldoc.CreateElement("", "State", ""); - - XmlAttribute stateID = xmldoc.CreateAttribute("", "UUID", ""); - stateID.Value = state.Key.ToString(); - stateData.Attributes.Append(stateID); - XmlDocument sdoc = new XmlDocument(); sdoc.LoadXml(state.Value); - XmlNodeList rootL = sdoc.GetElementsByTagName("ScriptState"); + XmlNodeList rootL = sdoc.GetElementsByTagName("State"); XmlNode rootNode = rootL[0]; XmlNode newNode = xmldoc.ImportNode(rootNode, true); - stateData.AppendChild(newNode); - wrapper.AppendChild(stateData); + wrapper.AppendChild(newNode); } return xmldoc.InnerXml; @@ -437,6 +353,7 @@ namespace OpenSim.Region.Framework.Scenes public void SetState(string objXMLData, UUID RegionID) { +m_log.Debug("SetState called with " + objXMLData); if (objXMLData == String.Empty) return; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index abb04cd..2ef8258 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -880,36 +880,6 @@ namespace OpenSim.Region.Framework.Scenes return ret; } - public string[] GetScriptAssemblies() - { - IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); - - List ret = new List(); - if (engines == null) // No engine at all - return new string[0]; - - foreach (TaskInventoryItem item in m_items.Values) - { - if (item.InvType == (int)InventoryType.LSL) - { - foreach (IScriptModule e in engines) - { - if (e != null) - { - string n = e.GetAssemblyName(item.ItemID); - if (n != String.Empty) - { - if (!ret.Contains(n)) - ret.Add(n); - break; - } - } - } - } - } - return ret.ToArray(); - } - public Dictionary GetScriptStates() { IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 8b94f28..4dc6cb8 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1248,20 +1248,97 @@ namespace OpenSim.Region.ScriptEngine.XEngine } } - public string GetAssemblyName(UUID itemID) - { - IScriptInstance instance = GetInstance(itemID); - if (instance == null) - return ""; - return instance.GetAssemblyName(); - } - public string GetXMLState(UUID itemID) { IScriptInstance instance = GetInstance(itemID); if (instance == null) return ""; - return instance.GetXMLState(); + string xml = instance.GetXMLState(); + + XmlDocument sdoc = new XmlDocument(); + sdoc.LoadXml(xml); + XmlNodeList rootL = sdoc.GetElementsByTagName("ScriptState"); + XmlNode rootNode = rootL[0]; + + // Create + XmlDocument doc = new XmlDocument(); + XmlElement stateData = doc.CreateElement("", "State", ""); + XmlAttribute stateID = doc.CreateAttribute("", "UUID", ""); + stateID.Value = itemID.ToString(); + stateData.Attributes.Append(stateID); + XmlAttribute assetID = doc.CreateAttribute("", "Asset", ""); + assetID.Value = instance.AssetID.ToString(); + stateData.Attributes.Append(assetID); + doc.AppendChild(stateData); + + // Add ... + XmlNode xmlstate = doc.ImportNode(rootNode, true); + stateData.AppendChild(xmlstate); + + string assemName = instance.GetAssemblyName(); + + string fn = Path.GetFileName(assemName); + + string assem = String.Empty; + + if (File.Exists(assemName + ".text")) + { + FileInfo tfi = new FileInfo(assemName + ".text"); + + if (tfi != null) + { + Byte[] tdata = new Byte[tfi.Length]; + + try + { + FileStream tfs = File.Open(assemName + ".text", + FileMode.Open, FileAccess.Read); + tfs.Read(tdata, 0, tdata.Length); + tfs.Close(); + + assem = new System.Text.ASCIIEncoding().GetString(tdata); + } + catch (Exception e) + { + m_log.DebugFormat("[XEngine]: Unable to open script textfile {0}, reason: {1}", assemName+".text", e.Message); + } + } + } + else + { + FileInfo fi = new FileInfo(assemName); + + if (fi != null) + { + Byte[] data = new Byte[fi.Length]; + + try + { + FileStream fs = File.Open(assemName, FileMode.Open, FileAccess.Read); + fs.Read(data, 0, data.Length); + fs.Close(); + + assem = System.Convert.ToBase64String(data); + } + catch (Exception e) + { + m_log.DebugFormat("[XEngine]: Unable to open script assembly {0}, reason: {1}", assemName, e.Message); + } + + } + } + + XmlElement assemblyData = doc.CreateElement("", "Assembly", ""); + XmlAttribute assemblyName = doc.CreateAttribute("", "Filename", ""); + + assemblyName.Value = fn; + assemblyData.Attributes.Append(assemblyName); + + assemblyData.InnerText = assem; + + stateData.AppendChild(assemblyData); + + return doc.InnerXml; } public bool CanBeDeleted(UUID itemID) -- cgit v1.1 From a27d33cb634c78425eaa34cb5efd113e131baa51 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 26 Nov 2009 12:16:42 +0000 Subject: Remove the old remoting-type interregion code for prim/script crossing --- OpenSim/Framework/IRegionCommsListener.cs | 2 - OpenSim/Framework/RegionCommsListener.cs | 25 ------ OpenSim/Region/Framework/Scenes/Scene.cs | 99 ---------------------- .../Framework/Scenes/SceneCommunicationService.cs | 72 ---------------- 4 files changed, 198 deletions(-) diff --git a/OpenSim/Framework/IRegionCommsListener.cs b/OpenSim/Framework/IRegionCommsListener.cs index 307c6bc..cd59c63 100644 --- a/OpenSim/Framework/IRegionCommsListener.cs +++ b/OpenSim/Framework/IRegionCommsListener.cs @@ -32,7 +32,6 @@ namespace OpenSim.Framework { public delegate void ExpectUserDelegate(AgentCircuitData agent); - public delegate bool ExpectPrimDelegate(UUID primID, string objData, int XMLMethod); public delegate void UpdateNeighbours(List neighbours); @@ -55,7 +54,6 @@ namespace OpenSim.Framework public interface IRegionCommsListener { event ExpectUserDelegate OnExpectUser; - event ExpectPrimDelegate OnExpectPrim; event GenericCall2 OnExpectChildAgent; event AgentCrossing OnAvatarCrossingIntoRegion; event PrimCrossing OnPrimCrossingIntoRegion; diff --git a/OpenSim/Framework/RegionCommsListener.cs b/OpenSim/Framework/RegionCommsListener.cs index 90200d6..718a556 100644 --- a/OpenSim/Framework/RegionCommsListener.cs +++ b/OpenSim/Framework/RegionCommsListener.cs @@ -43,7 +43,6 @@ namespace OpenSim.Framework private ChildAgentUpdate handlerChildAgentUpdate = null; // OnChildAgentUpdate; private CloseAgentConnection handlerCloseAgentConnection = null; // OnCloseAgentConnection; private GenericCall2 handlerExpectChildAgent = null; // OnExpectChildAgent; - private ExpectPrimDelegate handlerExpectPrim = null; // OnExpectPrim; private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser private UpdateNeighbours handlerNeighboursUpdate = null; // OnNeighboursUpdate; private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion; @@ -53,7 +52,6 @@ namespace OpenSim.Framework #region IRegionCommsListener Members public event ExpectUserDelegate OnExpectUser; - public event ExpectPrimDelegate OnExpectPrim; public event GenericCall2 OnExpectChildAgent; public event AgentCrossing OnAvatarCrossingIntoRegion; public event PrimCrossing OnPrimCrossingIntoRegion; @@ -95,17 +93,6 @@ namespace OpenSim.Framework } - public virtual bool TriggerExpectPrim(UUID primID, string objData, int XMLMethod) - { - handlerExpectPrim = OnExpectPrim; - if (handlerExpectPrim != null) - { - handlerExpectPrim(primID, objData, XMLMethod); - return true; - } - return false; - } - public virtual bool TriggerChildAgentUpdate(ChildAgentDataUpdate cAgentData) { handlerChildAgentUpdate = OnChildAgentUpdate; @@ -128,18 +115,6 @@ namespace OpenSim.Framework return false; } - public virtual bool TriggerExpectPrimCrossing(UUID primID, Vector3 position, - bool isPhysical) - { - handlerPrimCrossingIntoRegion = OnPrimCrossingIntoRegion; - if (handlerPrimCrossingIntoRegion != null) - { - handlerPrimCrossingIntoRegion(primID, position, isPhysical); - return true; - } - return false; - } - public virtual bool TriggerAcknowledgeAgentCrossed(UUID agentID) { handlerAcknowledgeAgentCrossed = OnAcknowledgeAgentCrossed; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index be1d4bf..f932659 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2393,103 +2393,6 @@ namespace OpenSim.Region.Framework.Scenes return successYN; } - /// - /// Handle a scene object that is crossing into this region from another. - /// NOTE: Unused as of 2009-02-09. Soon to be deleted. - /// - /// - /// - /// - /// - /// - public bool IncomingInterRegionPrimGroup(UUID primID, string objXMLData, int XMLMethod) - { - if (XMLMethod == 0) - { - m_log.DebugFormat("[INTERREGION]: A new prim {0} arrived from a neighbor", primID); - SceneObjectGroup sceneObject = m_serialiser.DeserializeGroupFromXml2(objXMLData); - if (sceneObject.IsAttachment) - sceneObject.RootPart.ObjectFlags |= (uint)PrimFlags.Phantom; - - return AddSceneObject(sceneObject); - } - else if ((XMLMethod == 100) && m_allowScriptCrossings) - { - m_log.Warn("[INTERREGION]: Prim state data arrived from a neighbor"); - - XmlDocument doc = new XmlDocument(); - doc.LoadXml(objXMLData); - - XmlNodeList rootL = doc.GetElementsByTagName("ScriptData"); - if (rootL.Count == 1) - { - XmlNode rootNode = rootL[0]; - if (rootNode != null) - { - XmlNodeList partL = rootNode.ChildNodes; - - foreach (XmlNode part in partL) - { - XmlNodeList nodeL = part.ChildNodes; - - switch (part.Name) - { - case "Assemblies": - foreach (XmlNode asm in nodeL) - { - string fn = asm.Attributes.GetNamedItem("Filename").Value; - - Byte[] filedata = Convert.FromBase64String(asm.InnerText); - string path = Path.Combine("ScriptEngines", RegionInfo.RegionID.ToString()); - path = Path.Combine(path, fn); - - if (!File.Exists(path)) - { - FileStream fs = File.Create(path); - fs.Write(filedata, 0, filedata.Length); - fs.Close(); - } - } - break; - case "ScriptStates": - foreach (XmlNode st in nodeL) - { - string id = st.Attributes.GetNamedItem("UUID").Value; - UUID uuid = new UUID(id); - XmlNode state = st.ChildNodes[0]; - - XmlDocument sdoc = new XmlDocument(); - XmlNode sxmlnode = sdoc.CreateNode( - XmlNodeType.XmlDeclaration, - "", ""); - sdoc.AppendChild(sxmlnode); - - XmlNode newnode = sdoc.ImportNode(state, true); - sdoc.AppendChild(newnode); - - string spath = Path.Combine("ScriptEngines", RegionInfo.RegionID.ToString()); - spath = Path.Combine(spath, uuid.ToString()); - FileStream sfs = File.Create(spath + ".state"); - ASCIIEncoding enc = new ASCIIEncoding(); - Byte[] buf = enc.GetBytes(sdoc.InnerXml); - sfs.Write(buf, 0, buf.Length); - sfs.Close(); - } - break; - } - } - } - } - - SceneObjectPart RootPrim = GetSceneObjectPart(primID); - RootPrim.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, 1); - - return true; - } - - return true; - } - public bool IncomingCreateObject(ISceneObject sog) { //m_log.Debug(" >>> IncomingCreateObject <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); @@ -3362,7 +3265,6 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGridService.OnCloseAgentConnection += IncomingCloseAgent; //m_eventManager.OnRegionUp += OtherRegionUp; //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; - m_sceneGridService.OnExpectPrim += IncomingInterRegionPrimGroup; //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; m_sceneGridService.KiPrimitive += SendKillObject; @@ -3386,7 +3288,6 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGridService.KiPrimitive -= SendKillObject; m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; - m_sceneGridService.OnExpectPrim -= IncomingInterRegionPrimGroup; //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; //m_eventManager.OnRegionUp -= OtherRegionUp; m_sceneGridService.OnExpectUser -= HandleNewUserConnection; diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 76c6cab..3892769 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -85,7 +85,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// A Prim will arrive shortly /// - public event ExpectPrimDelegate OnExpectPrim; public event CloseAgentConnection OnCloseAgentConnection; /// @@ -116,7 +115,6 @@ namespace OpenSim.Region.Framework.Scenes private AgentCrossing handlerAvatarCrossingIntoRegion = null; // OnAvatarCrossingIntoRegion; private ExpectUserDelegate handlerExpectUser = null; // OnExpectUser; - private ExpectPrimDelegate handlerExpectPrim = null; // OnExpectPrim; private CloseAgentConnection handlerCloseAgentConnection = null; // OnCloseAgentConnection; private PrimCrossing handlerPrimCrossingIntoRegion = null; // OnPrimCrossingIntoRegion; //private RegionUp handlerRegionUp = null; // OnRegionUp; @@ -147,30 +145,6 @@ namespace OpenSim.Region.Framework.Scenes /// Thrown if region registration fails. public void RegisterRegion(IInterregionCommsOut comms_out, RegionInfo regionInfos) { - //m_interregionCommsOut = comms_out; - - //m_regionInfo = regionInfos; - //m_commsProvider.GridService.gdebugRegionName = regionInfos.RegionName; - //regionCommsHost = m_commsProvider.GridService.RegisterRegion(m_regionInfo); - - //if (regionCommsHost != null) - //{ - // //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got" + regionCommsHost.ToString()); - - // regionCommsHost.debugRegionName = regionInfos.RegionName; - // regionCommsHost.OnExpectPrim += IncomingPrimCrossing; - // regionCommsHost.OnExpectUser += NewUserConnection; - // regionCommsHost.OnAvatarCrossingIntoRegion += AgentCrossing; - // regionCommsHost.OnCloseAgentConnection += CloseConnection; - // regionCommsHost.OnRegionUp += newRegionUp; - // regionCommsHost.OnChildAgentUpdate += ChildAgentUpdate; - // regionCommsHost.OnLogOffUser += GridLogOffUser; - // regionCommsHost.OnGetLandData += FetchLandData; - //} - //else - //{ - // //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: registered with gridservice and got null"); - //} } /// @@ -179,31 +153,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void Close() { - - //if (regionCommsHost != null) - //{ - // regionCommsHost.OnLogOffUser -= GridLogOffUser; - // regionCommsHost.OnChildAgentUpdate -= ChildAgentUpdate; - // regionCommsHost.OnRegionUp -= newRegionUp; - // regionCommsHost.OnExpectUser -= NewUserConnection; - // regionCommsHost.OnExpectPrim -= IncomingPrimCrossing; - // regionCommsHost.OnAvatarCrossingIntoRegion -= AgentCrossing; - // regionCommsHost.OnCloseAgentConnection -= CloseConnection; - // regionCommsHost.OnGetLandData -= FetchLandData; - - // try - // { - // m_commsProvider.GridService.DeregisterRegion(m_regionInfo); - // } - // catch (Exception e) - // { - // m_log.ErrorFormat( - // "[GRID]: Deregistration of region {0} from the grid failed - {1}. Continuing", - // m_regionInfo.RegionName, e); - // } - - // regionCommsHost = null; - //} } #region CommsManager Event handlers @@ -263,27 +212,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// We have a new prim from a neighbor - /// - /// unique ID for the primative - /// XML2 encoded data of the primative - /// An Int that represents the version of the XMLMethod - /// True if the prim was accepted, false if it was not - protected bool IncomingPrimCrossing(UUID primID, String objXMLData, int XMLMethod) - { - handlerExpectPrim = OnExpectPrim; - if (handlerExpectPrim != null) - { - return handlerExpectPrim(primID, objXMLData, XMLMethod); - } - else - { - return false; - } - - } - protected void PrimCrossing(UUID primID, Vector3 position, bool isPhysical) { handlerPrimCrossingIntoRegion = OnPrimCrossingIntoRegion; -- cgit v1.1 From bd3b9f79c2ac25c39d531c3d0c390eacab8ab958 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 26 Nov 2009 17:59:28 +0000 Subject: Update CM version --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index ec94b2d..0d4215b 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,7 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.6.9"; + private const string VERSION_NUMBER = "0.6.9-CM"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour -- cgit v1.1 From ad2f0a1290b9260393a27291fdd8a1592222c368 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 26 Nov 2009 18:04:58 +0000 Subject: Remove OS version crap from about dialog --- OpenSim/Framework/Util.cs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 87ba5a8..c052745 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -990,19 +990,19 @@ namespace OpenSim.Framework { string os = String.Empty; - if (Environment.OSVersion.Platform != PlatformID.Unix) - { - os = Environment.OSVersion.ToString(); - } - else - { - os = ReadEtcIssue(); - } - - if (os.Length > 45) - { - os = os.Substring(0, 45); - } +// if (Environment.OSVersion.Platform != PlatformID.Unix) +// { +// os = Environment.OSVersion.ToString(); +// } +// else +// { +// os = ReadEtcIssue(); +// } +// +// if (os.Length > 45) +// { +// os = os.Substring(0, 45); +// } return os; } -- cgit v1.1 From 5dedacca3c9692948f29f5198dd444efe7c8526d Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Thu, 26 Nov 2009 20:37:08 +0100 Subject: First attempt at mult-sit on large single prims. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 91 +++++++++++++++--------- 1 file changed, 58 insertions(+), 33 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index a65b84b..e677cfd 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -117,6 +117,7 @@ namespace OpenSim.Region.Framework.Scenes public Vector4 CollisionPlane = Vector4.UnitW; private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation + private Vector3 m_avUnscriptedSitPos; // for non-scripted prims private Vector3 m_lastPosition; private Quaternion m_lastRotation; private Vector3 m_lastVelocity; @@ -1644,9 +1645,9 @@ namespace OpenSim.Region.Framework.Scenes { AddToPhysicalScene(false); } - m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); m_parentPosition = Vector3.Zero; +//Console.WriteLine("Stand Pos {0}", m_pos); m_parentID = 0; SendFullUpdateToAllClients(); @@ -1740,21 +1741,37 @@ namespace OpenSim.Region.Framework.Scenes //Console.WriteLine("SendSitResponse offset=" + offset + " UnOccup=" + SitTargetUnOccupied + // " TargSet=" + SitTargetisSet); - - if (SitTargetisSet && SitTargetUnOccupied) - { - part.SetAvatarOnSitTarget(UUID); - offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); - sitOrientation = avSitOrientation; - autopilot = false; // Jump direct to scripted llSitPos() - } + // Sit analysis rewritten by KF 091125 + if (SitTargetisSet) // scipted sit + { + if (SitTargetUnOccupied) + { + part.SetAvatarOnSitTarget(UUID); // set that Av will be on it + offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one + sitOrientation = avSitOrientation; // Change rotatione to the scripted one + autopilot = false; // Jump direct to scripted llSitPos() + } + else return; + } + else // Not Scripted + { + if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) // large prim + { + Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); + m_avUnscriptedSitPos = offset * partIRot; // sit where clicked + pos = part.AbsolutePosition + (offset * partIRot); + } + else // small prim + { + if (SitTargetUnOccupied) + { + m_avUnscriptedSitPos = Vector3.Zero; // Sit on unoccupied small prim center + pos = part.AbsolutePosition; + } + else return; // occupied small + } // end large/small + } // end Scripted/not - pos = part.AbsolutePosition + offset; // Region position where clicked - //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) - //{ - // offset = pos; - //autopilot = false; - //} if (m_physicsActor != null) { // If we're not using the client autopilot, we're immediately warping the avatar to the location @@ -1887,8 +1904,9 @@ namespace OpenSim.Region.Framework.Scenes { // Non-scripted sit by Kitto Flora 21Nov09 // Calculate angle of line from prim to Av - float y_diff = (m_avInitialPos.Y - part.AbsolutePosition.Y); - float x_diff = ( m_avInitialPos.X - part.AbsolutePosition.X); + Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos; + float y_diff = (m_avInitialPos.Y - sitTargetPos.Y); + float x_diff = ( m_avInitialPos.X - sitTargetPos.X); if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff); @@ -1896,23 +1914,30 @@ namespace OpenSim.Region.Framework.Scenes // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'. // Av sits at world euler <0,0, z>, translated by part rotation m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click - m_pos = new Vector3(0f, 0f, 0.05f) + - (new Vector3(0.0f, 0f, 0.625f) * partIRot) + - (new Vector3(0.25f, 0f, 0.0f) * m_bodyRot); // sit at center of prim m_parentPosition = part.AbsolutePosition; - //Set up raytrace to find top surface of prim - Vector3 size = part.Scale; - float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); - Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); - Vector3 down = new Vector3(0f, 0f, -1f); - m_scene.PhysicsScene.RaycastWorld( - start, // Vector3 position, - down, // Vector3 direction, - mag, // float length, - SitAltitudeCallback); // retMethod - } - } - else + if(m_avUnscriptedSitPos != Vector3.Zero) + { // sit where clicked on big prim + m_pos = m_avUnscriptedSitPos + (new Vector3(0.0f, 0f, 0.625f) * partIRot); + } + else + { // sit at center of small prim + m_pos = new Vector3(0f, 0f, 0.05f) + + (new Vector3(0.0f, 0f, 0.625f) * partIRot) + + (new Vector3(0.25f, 0f, 0.0f) * m_bodyRot); + //Set up raytrace to find top surface of prim + Vector3 size = part.Scale; + float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); + Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); + Vector3 down = new Vector3(0f, 0f, -1f); + m_scene.PhysicsScene.RaycastWorld( + start, // Vector3 position, + down, // Vector3 direction, + mag, // float length, + SitAltitudeCallback); // retMethod + } // end small/big + } // end scripted/not + } + else // no Av { return; } -- cgit v1.1 From aa695e92f7d3b56e6e3371be021d9e6acf91077c Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 27 Nov 2009 08:58:26 +0000 Subject: Reset update flag when a SOG is deleted. This fixes llDie(); --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f36ff1d..26a843e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1199,6 +1199,7 @@ namespace OpenSim.Region.Framework.Scenes if (!silent) { + part.UpdateFlag = 0; if (part == m_rootPart) avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); } -- cgit v1.1 From 9888f95068373f1bfdb289e85560a7d873d22696 Mon Sep 17 00:00:00 2001 From: CasperW Date: Fri, 27 Nov 2009 18:29:03 +0100 Subject: Convert multiple lock()s which directly hinder script performance in linksets to ReaderWriterLockSlim. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 400 ++++++++++++++------ .../Shared/Api/Implementation/LSL_Api.cs | 11 +- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 415 ++++++++++++--------- 3 files changed, 531 insertions(+), 295 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 26a843e..fb34ddc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -98,6 +98,66 @@ namespace OpenSim.Region.Framework.Scenes private bool m_hasGroupChanged = false; private long timeFirstChanged; private long timeLastChanged; + private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); + + public void lockPartsForRead(bool locked) + { + if (locked) + { + if (m_partsLock.RecursiveReadCount > 0) + { + m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); + m_partsLock.ExitReadLock(); + } + if (m_partsLock.RecursiveWriteCount > 0) + { + m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed."); + m_partsLock.ExitWriteLock(); + } + + while (!m_partsLock.TryEnterReadLock(60000)) + { + m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire READ lock of m_parts in SceneObjectGroup. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); + if (m_partsLock.IsWriteLockHeld) + { + m_partsLock = new System.Threading.ReaderWriterLockSlim(); + } + } + } + else + { + m_partsLock.ExitReadLock(); + } + } + public void lockPartsForWrite(bool locked) + { + if (locked) + { + if (m_partsLock.RecursiveReadCount > 0) + { + m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); + m_partsLock.ExitReadLock(); + } + if (m_partsLock.RecursiveWriteCount > 0) + { + m_log.Error("[SceneObjectGroup.m_parts] Recursive write lock requested. This should not happen and means something needs to be fixed."); + m_partsLock.ExitWriteLock(); + } + + while (!m_partsLock.TryEnterWriteLock(60000)) + { + m_log.Error("[SceneObjectGroup.m_parts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); + if (m_partsLock.IsWriteLockHeld) + { + m_partsLock = new System.Threading.ReaderWriterLockSlim(); + } + } + } + else + { + m_partsLock.ExitWriteLock(); + } + } public bool HasGroupChanged { @@ -243,13 +303,16 @@ namespace OpenSim.Region.Framework.Scenes set { m_regionHandle = value; - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + part.RegionHandle = m_regionHandle; + } } + lockPartsForRead(false); } } @@ -275,13 +338,16 @@ namespace OpenSim.Region.Framework.Scenes m_scene.CrossPrimGroupIntoNewRegion(val, this, true); } - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + part.GroupPosition = val; + } } + lockPartsForRead(false); //if (m_rootPart.PhysActor != null) //{ @@ -432,13 +498,16 @@ namespace OpenSim.Region.Framework.Scenes public void SetFromItemID(UUID AssetId) { - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + part.FromItemID = AssetId; + } } + lockPartsForRead(false); } public UUID GetFromItemID() @@ -505,10 +574,11 @@ namespace OpenSim.Region.Framework.Scenes Vector3 maxScale = Vector3.Zero; Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f); - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + Vector3 partscale = part.Scale; Vector3 partoffset = part.OffsetPosition; @@ -519,8 +589,11 @@ namespace OpenSim.Region.Framework.Scenes maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X; maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y; maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z; + } } + lockPartsForRead(false); + finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X; finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y; finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z; @@ -536,10 +609,11 @@ namespace OpenSim.Region.Framework.Scenes EntityIntersection result = new EntityIntersection(); - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + // Temporary commented to stop compiler warning //Vector3 partPosition = // new Vector3(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); @@ -567,8 +641,10 @@ namespace OpenSim.Region.Framework.Scenes result.distance = inter.distance; } } + } } + lockPartsForRead(false); return result; } @@ -581,10 +657,11 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) { float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + Vector3 worldPos = part.GetWorldPosition(); Vector3 offset = worldPos - AbsolutePosition; Quaternion worldRot; @@ -643,6 +720,8 @@ namespace OpenSim.Region.Framework.Scenes backBottomRight.Y = orig.Y + (part.Scale.Y / 2); backBottomRight.Z = orig.Z - (part.Scale.Z / 2); + + //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); @@ -814,6 +893,7 @@ namespace OpenSim.Region.Framework.Scenes minZ = backBottomLeft.Z; } } + lockPartsForRead(false); Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); @@ -842,17 +922,20 @@ namespace OpenSim.Region.Framework.Scenes Dictionary states = new Dictionary(); // Capture script state while holding the lock - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + Dictionary pstates = part.Inventory.GetScriptStates(); foreach (UUID itemid in pstates.Keys) { states.Add(itemid, pstates[itemid]); } + } } + lockPartsForRead(false); if (states.Count > 0) { @@ -1014,13 +1097,16 @@ namespace OpenSim.Region.Framework.Scenes public override void UpdateMovement() { - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + part.UpdateMovement(); + } } + lockPartsForRead(false); } public ushort GetTimeDilation() @@ -1064,7 +1150,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void AddPart(SceneObjectPart part) { - lock (m_parts) + lockPartsForWrite(true); { part.SetParent(this); m_parts.Add(part.UUID, part); @@ -1074,6 +1160,7 @@ namespace OpenSim.Region.Framework.Scenes if (part.LinkNum == 2 && RootPart != null) RootPart.LinkNum = 1; } + lockPartsForWrite(false); } /// @@ -1081,28 +1168,33 @@ namespace OpenSim.Region.Framework.Scenes /// private void UpdateParentIDs() { - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + if (part.UUID != m_rootPart.UUID) { part.ParentID = m_rootPart.LocalId; } + } } + lockPartsForRead(false); } public void RegenerateFullIDs() { - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + part.UUID = UUID.Random(); - + } } + lockPartsForRead(false); } // helper provided for parts. @@ -1183,29 +1275,33 @@ namespace OpenSim.Region.Framework.Scenes DetachFromBackup(); - lock (m_parts) + lockPartsForRead(true); + List values = new List(m_parts.Values); + lockPartsForRead(false); + + foreach (SceneObjectPart part in values) { - foreach (SceneObjectPart part in m_parts.Values) - { // part.Inventory.RemoveScriptInstances(); - - ScenePresence[] avatars = Scene.GetScenePresences(); - for (int i = 0; i < avatars.Length; i++) + + ScenePresence[] avatars = Scene.GetScenePresences(); + for (int i = 0; i < avatars.Length; i++) + { + if (avatars[i].ParentID == LocalId) { - if (avatars[i].ParentID == LocalId) - { - avatars[i].StandUp(); - } + avatars[i].StandUp(); + } - if (!silent) - { - part.UpdateFlag = 0; - if (part == m_rootPart) - avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); - } + if (!silent) + { + part.UpdateFlag = 0; + if (part == m_rootPart) + avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); } } + } + + } public void AddScriptLPS(int count) @@ -1230,17 +1326,20 @@ namespace OpenSim.Region.Framework.Scenes scriptEvents aggregateScriptEvents=0; - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + if (part == null) continue; if (part != RootPart) part.ObjectFlags = objectflagupdate; aggregateScriptEvents |= part.AggregateScriptEvents; + } } + lockPartsForRead(false); m_scriptListens_atTarget = ((aggregateScriptEvents & scriptEvents.at_target) != 0); m_scriptListens_notAtTarget = ((aggregateScriptEvents & scriptEvents.not_at_target) != 0); @@ -1273,42 +1372,52 @@ namespace OpenSim.Region.Framework.Scenes /// public void ApplyPhysics(bool m_physicalPrim) { - lock (m_parts) + lockPartsForRead(true); + + if (m_parts.Count > 1) { - if (m_parts.Count > 1) + List values = new List(m_parts.Values); + lockPartsForRead(false); + m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); + foreach (SceneObjectPart part in values) { - m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); - foreach (SceneObjectPart part in m_parts.Values) + + if (part.LocalId != m_rootPart.LocalId) { - if (part.LocalId != m_rootPart.LocalId) - { - part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); - } + part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, m_physicalPrim); } - // Hack to get the physics scene geometries in the right spot - ResetChildPrimPhysicsPositions(); - } - else - { - m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); } + // Hack to get the physics scene geometries in the right spot + ResetChildPrimPhysicsPositions(); + } + else + { + lockPartsForRead(false); + m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_physicalPrim); } } public void SetOwnerId(UUID userId) { - ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); + ForEachPart(delegate(SceneObjectPart part) + { + + part.OwnerID = userId; + + }); } public void ForEachPart(Action whatToDo) { - lock (m_parts) + lockPartsForRead(true); + List values = new List(m_parts.Values); + lockPartsForRead(false); + foreach (SceneObjectPart part in values) { - foreach (SceneObjectPart part in m_parts.Values) - { - whatToDo(part); - } + + whatToDo(part); + } } @@ -1407,14 +1516,17 @@ namespace OpenSim.Region.Framework.Scenes { SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + if (part != RootPart) SendPartFullUpdate(remoteClient, part, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); + } } + lockPartsForRead(false); } /// @@ -1509,10 +1621,11 @@ namespace OpenSim.Region.Framework.Scenes List partList; - lock (m_parts) - { - partList = new List(m_parts.Values); - } + lockPartsForRead(true); + + partList = new List(m_parts.Values); + + lockPartsForRead(false); partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) { @@ -1835,10 +1948,11 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); newPart.SetParent(this); - lock (m_parts) + lockPartsForWrite(true); { m_parts.Add(newPart.UUID, newPart); } + lockPartsForWrite(false); SetPartAsNonRoot(newPart); @@ -1901,7 +2015,7 @@ namespace OpenSim.Region.Framework.Scenes //if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) // return; - lock (m_parts) + lockPartsForRead(true); { bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); @@ -1919,34 +2033,43 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in m_parts.Values) { + part.SendScheduledUpdates(); + } } + lockPartsForRead(false); } public void ScheduleFullUpdateToAvatar(ScenePresence presence) { RootPart.AddFullUpdateToAvatar(presence); - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + if (part != RootPart) part.AddFullUpdateToAvatar(presence); + } } + lockPartsForRead(false); } public void ScheduleTerseUpdateToAvatar(ScenePresence presence) { - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + part.AddTerseUpdateToAvatar(presence); + } } + lockPartsForRead(false); } /// @@ -1957,14 +2080,17 @@ namespace OpenSim.Region.Framework.Scenes checkAtTargets(); RootPart.ScheduleFullUpdate(); - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + if (part != RootPart) part.ScheduleFullUpdate(); + } } + lockPartsForRead(false); } /// @@ -1972,13 +2098,16 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForTerseUpdate() { - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + part.ScheduleTerseUpdate(); + } } + lockPartsForRead(false); } /// @@ -1991,14 +2120,17 @@ namespace OpenSim.Region.Framework.Scenes RootPart.SendFullUpdateToAllClients(); - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { + if (part != RootPart) part.SendFullUpdateToAllClients(); + } } + lockPartsForRead(false); } /// @@ -2029,14 +2161,15 @@ namespace OpenSim.Region.Framework.Scenes { if (IsDeleted) return; - - lock (m_parts) + + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { part.SendTerseUpdateToAllClients(); } } + lockPartsForRead(false); } #endregion @@ -2050,16 +2183,18 @@ namespace OpenSim.Region.Framework.Scenes /// null if no child part with that linknum or child part public SceneObjectPart GetLinkNumPart(int linknum) { - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { if (part.LinkNum == linknum) { + lockPartsForRead(false); return part; } } } + lockPartsForRead(false); return null; } @@ -2087,17 +2222,19 @@ namespace OpenSim.Region.Framework.Scenes public SceneObjectPart GetChildPart(uint localID) { //m_log.DebugFormat("Entered looking for {0}", localID); - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { //m_log.DebugFormat("Found {0}", part.LocalId); if (part.LocalId == localID) { + lockPartsForRead(false); return part; } } } + lockPartsForRead(false); return null; } @@ -2127,17 +2264,19 @@ namespace OpenSim.Region.Framework.Scenes public bool HasChildPrim(uint localID) { //m_log.DebugFormat("Entered HasChildPrim looking for {0}", localID); - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { //m_log.DebugFormat("Found {0}", part.LocalId); if (part.LocalId == localID) { + lockPartsForRead(false); return true; } } } + lockPartsForRead(false); return false; } @@ -2187,53 +2326,57 @@ namespace OpenSim.Region.Framework.Scenes if (m_rootPart.LinkNum == 0) m_rootPart.LinkNum = 1; - lock (m_parts) - { - m_parts.Add(linkPart.UUID, linkPart); + lockPartsForWrite(true); + + m_parts.Add(linkPart.UUID, linkPart); + + lockPartsForWrite(false); - // Insert in terms of link numbers, the new links - // before the current ones (with the exception of - // the root prim. Shuffle the old ones up - foreach (KeyValuePair kvp in m_parts) + // Insert in terms of link numbers, the new links + // before the current ones (with the exception of + // the root prim. Shuffle the old ones up + lockPartsForRead(true); + foreach (KeyValuePair kvp in m_parts) + { + if (kvp.Value.LinkNum != 1) { - if (kvp.Value.LinkNum != 1) - { - // Don't update root prim link number - kvp.Value.LinkNum += objectGroup.PrimCount; - } + // Don't update root prim link number + kvp.Value.LinkNum += objectGroup.PrimCount; } + } + lockPartsForRead(false); - linkPart.LinkNum = 2; + linkPart.LinkNum = 2; - linkPart.SetParent(this); - linkPart.AddFlag(PrimFlags.CreateSelected); + linkPart.SetParent(this); + linkPart.AddFlag(PrimFlags.CreateSelected); - //if (linkPart.PhysActor != null) - //{ - // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); - - //linkPart.PhysActor = null; - //} + //if (linkPart.PhysActor != null) + //{ + // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); + + //linkPart.PhysActor = null; + //} - //TODO: rest of parts - int linkNum = 3; - foreach (SceneObjectPart part in objectGroup.Children.Values) + //TODO: rest of parts + int linkNum = 3; + foreach (SceneObjectPart part in objectGroup.Children.Values) + { + if (part.UUID != objectGroup.m_rootPart.UUID) { - if (part.UUID != objectGroup.m_rootPart.UUID) - { - LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); - } - part.ClearUndoState(); + LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); } + part.ClearUndoState(); } m_scene.UnlinkSceneObject(objectGroup.UUID, true); objectGroup.m_isDeleted = true; + + objectGroup.lockPartsForWrite(true); - lock (objectGroup.m_parts) - { - objectGroup.m_parts.Clear(); - } + objectGroup.m_parts.Clear(); + + objectGroup.lockPartsForWrite(false); // Can't do this yet since backup still makes use of the root part without any synchronization // objectGroup.m_rootPart = null; @@ -2292,11 +2435,12 @@ namespace OpenSim.Region.Framework.Scenes Quaternion worldRot = linkPart.GetWorldRotation(); // Remove the part from this object - lock (m_parts) + lockPartsForWrite(true); { m_parts.Remove(linkPart.UUID); } - + lockPartsForWrite(false); + lockPartsForRead(true); if (m_parts.Count == 1 && RootPart != null) //Single prim is left RootPart.LinkNum = 0; else @@ -2307,6 +2451,7 @@ namespace OpenSim.Region.Framework.Scenes p.LinkNum--; } } + lockPartsForRead(false); linkPart.ParentID = 0; linkPart.LinkNum = 0; @@ -2624,22 +2769,23 @@ namespace OpenSim.Region.Framework.Scenes if (selectionPart != null) { - lock (m_parts) + lockPartsForRead(true); + List parts = new List(m_parts.Values); + lockPartsForRead(false); + foreach (SceneObjectPart part in parts) { - foreach (SceneObjectPart part in m_parts.Values) + if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) { - if (part.Scale.X > 10.0 || part.Scale.Y > 10.0 || part.Scale.Z > 10.0) - { - UsePhysics = false; // Reset physics - break; - } + UsePhysics = false; // Reset physics + break; } + } - foreach (SceneObjectPart part in m_parts.Values) - { - part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); - } + foreach (SceneObjectPart part in parts) + { + part.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); } + } } @@ -2863,7 +3009,7 @@ namespace OpenSim.Region.Framework.Scenes prevScale.Z *= z; part.Resize(prevScale); - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart obPart in m_parts.Values) { @@ -2882,6 +3028,7 @@ namespace OpenSim.Region.Framework.Scenes } } } + lockPartsForRead(false); if (part.PhysActor != null) { @@ -2962,7 +3109,7 @@ namespace OpenSim.Region.Framework.Scenes axDiff *= Quaternion.Inverse(partRotation); diff = axDiff; - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart obPart in m_parts.Values) { @@ -2972,6 +3119,7 @@ namespace OpenSim.Region.Framework.Scenes } } } + lockPartsForRead(false); AbsolutePosition = newPos; @@ -3089,7 +3237,7 @@ namespace OpenSim.Region.Framework.Scenes m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); } - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart prim in m_parts.Values) { @@ -3107,6 +3255,7 @@ namespace OpenSim.Region.Framework.Scenes } } } + lockPartsForRead(false); m_rootPart.ScheduleTerseUpdate(); } @@ -3205,7 +3354,7 @@ namespace OpenSim.Region.Framework.Scenes if (atTargets.Count > 0) { uint[] localids = new uint[0]; - lock (m_parts) + lockPartsForRead(true); { localids = new uint[m_parts.Count]; int cntr = 0; @@ -3215,6 +3364,7 @@ namespace OpenSim.Region.Framework.Scenes cntr++; } } + lockPartsForRead(false); for (int ctr = 0; ctr < localids.Length; ctr++) { @@ -3233,7 +3383,7 @@ namespace OpenSim.Region.Framework.Scenes { //trigger not_at_target uint[] localids = new uint[0]; - lock (m_parts) + lockPartsForRead(true); { localids = new uint[m_parts.Count]; int cntr = 0; @@ -3243,7 +3393,8 @@ namespace OpenSim.Region.Framework.Scenes cntr++; } } - + lockPartsForRead(false); + for (int ctr = 0; ctr < localids.Length; ctr++) { m_scene.EventManager.TriggerNotAtTargetEvent(localids[ctr]); @@ -3256,19 +3407,20 @@ namespace OpenSim.Region.Framework.Scenes public float GetMass() { float retmass = 0f; - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { retmass += part.GetMass(); } } + lockPartsForRead(false); return retmass; } public void CheckSculptAndLoad() { - lock (m_parts) + lockPartsForRead(true); { if (!IsDeleted) { @@ -3293,6 +3445,7 @@ namespace OpenSim.Region.Framework.Scenes } } } + lockPartsForRead(false); } protected void AssetReceived(string id, Object sender, AssetBase asset) @@ -3313,7 +3466,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void SetGroup(UUID GroupID, IClientAPI client) { - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) { @@ -3323,7 +3476,7 @@ namespace OpenSim.Region.Framework.Scenes HasGroupChanged = true; } - + lockPartsForRead(false); ScheduleGroupForFullUpdate(); } @@ -3342,11 +3495,12 @@ namespace OpenSim.Region.Framework.Scenes public void SetAttachmentPoint(byte point) { - lock (m_parts) + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) part.SetAttachmentPoint(point); } + lockPartsForRead(false); } #region ISceneObject diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ec771e3..267928b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2950,8 +2950,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return m_host.OwnerID.ToString(); } + [DebuggerNonUserCode] public void llInstantMessage(string user, string message) { + UUID result; + if (!UUID.TryParse(user, out result)) + { + throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user)); + return; + } + + m_host.AddScriptLPS(1); // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. @@ -2966,7 +2975,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID friendTransactionID = UUID.Random(); //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); - + GridInstantMessage msg = new GridInstantMessage(); msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; msg.toAgentID = new Guid(user); // toAgentID.Guid; diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index d997ea3..49c69ab 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -101,6 +101,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine private Dictionary m_Scripts = new Dictionary(); + private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim(); + // Maps the asset ID to the assembly private Dictionary m_Assemblies = @@ -122,6 +124,65 @@ namespace OpenSim.Region.ScriptEngine.XEngine private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue(); IWorkItemResult m_CurrentCompile = null; + private void lockScriptsForRead(bool locked) + { + if (locked) + { + if (m_scriptsLock.RecursiveReadCount > 0) + { + m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); + m_scriptsLock.ExitReadLock(); + } + if (m_scriptsLock.RecursiveWriteCount > 0) + { + m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed."); + m_scriptsLock.ExitWriteLock(); + } + + while (!m_scriptsLock.TryEnterReadLock(60000)) + { + m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire READ lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); + if (m_scriptsLock.IsWriteLockHeld) + { + m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim(); + } + } + } + else + { + m_scriptsLock.ExitReadLock(); + } + } + private void lockScriptsForWrite(bool locked) + { + if (locked) + { + if (m_scriptsLock.RecursiveReadCount > 0) + { + m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); + m_scriptsLock.ExitReadLock(); + } + if (m_scriptsLock.RecursiveWriteCount > 0) + { + m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed."); + m_scriptsLock.ExitWriteLock(); + } + + while (!m_scriptsLock.TryEnterWriteLock(60000)) + { + m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); + if (m_scriptsLock.IsWriteLockHeld) + { + m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim(); + } + } + } + else + { + m_scriptsLock.ExitWriteLock(); + } + } + public string ScriptEngineName { get { return "XEngine"; } @@ -261,43 +322,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine public void RemoveRegion(Scene scene) { - lock (m_Scripts) + lockScriptsForRead(true); + foreach (IScriptInstance instance in m_Scripts.Values) { - foreach (IScriptInstance instance in m_Scripts.Values) + // Force a final state save + // + if (m_Assemblies.ContainsKey(instance.AssetID)) { - // Force a final state save - // - if (m_Assemblies.ContainsKey(instance.AssetID)) - { - string assembly = m_Assemblies[instance.AssetID]; - instance.SaveState(assembly); - } + string assembly = m_Assemblies[instance.AssetID]; + instance.SaveState(assembly); + } - // Clear the event queue and abort the instance thread - // - instance.ClearQueue(); - instance.Stop(0); + // Clear the event queue and abort the instance thread + // + instance.ClearQueue(); + instance.Stop(0); - // Release events, timer, etc - // - instance.DestroyScriptInstance(); + // Release events, timer, etc + // + instance.DestroyScriptInstance(); - // Unload scripts and app domains - // Must be done explicitly because they have infinite - // lifetime - // - m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); - if (m_DomainScripts[instance.AppDomain].Count == 0) - { - m_DomainScripts.Remove(instance.AppDomain); - UnloadAppDomain(instance.AppDomain); - } + // Unload scripts and app domains + // Must be done explicitly because they have infinite + // lifetime + // + m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); + if (m_DomainScripts[instance.AppDomain].Count == 0) + { + m_DomainScripts.Remove(instance.AppDomain); + UnloadAppDomain(instance.AppDomain); } - m_Scripts.Clear(); - m_PrimObjects.Clear(); - m_Assemblies.Clear(); - m_DomainScripts.Clear(); } + lockScriptsForRead(false); + lockScriptsForWrite(true); + m_Scripts.Clear(); + lockScriptsForWrite(false); + m_PrimObjects.Clear(); + m_Assemblies.Clear(); + m_DomainScripts.Clear(); + lock (m_ScriptEngines) { m_ScriptEngines.Remove(this); @@ -356,22 +419,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine List instances = new List(); - lock (m_Scripts) - { - foreach (IScriptInstance instance in m_Scripts.Values) + lockScriptsForRead(true); + foreach (IScriptInstance instance in m_Scripts.Values) instances.Add(instance); - } + lockScriptsForRead(false); foreach (IScriptInstance i in instances) { string assembly = String.Empty; - lock (m_Scripts) - { + if (!m_Assemblies.ContainsKey(i.AssetID)) continue; assembly = m_Assemblies[i.AssetID]; - } + i.SaveState(assembly); } @@ -673,172 +734,183 @@ namespace OpenSim.Region.ScriptEngine.XEngine return false; } - lock (m_Scripts) + + + ScriptInstance instance = null; + // Create the object record + lockScriptsForRead(true); + if ((!m_Scripts.ContainsKey(itemID)) || + (m_Scripts[itemID].AssetID != assetID)) { - ScriptInstance instance = null; - // Create the object record + lockScriptsForRead(false); - if ((!m_Scripts.ContainsKey(itemID)) || - (m_Scripts[itemID].AssetID != assetID)) - { - UUID appDomain = assetID; + UUID appDomain = assetID; - if (part.ParentGroup.IsAttachment) - appDomain = part.ParentGroup.RootPart.UUID; + if (part.ParentGroup.IsAttachment) + appDomain = part.ParentGroup.RootPart.UUID; - if (!m_AppDomains.ContainsKey(appDomain)) + if (!m_AppDomains.ContainsKey(appDomain)) + { + try { - try - { - AppDomainSetup appSetup = new AppDomainSetup(); -// appSetup.ApplicationBase = Path.Combine( -// "ScriptEngines", -// m_Scene.RegionInfo.RegionID.ToString()); - - Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; - Evidence evidence = new Evidence(baseEvidence); - - AppDomain sandbox; - if (m_AppDomainLoading) - sandbox = AppDomain.CreateDomain( - m_Scene.RegionInfo.RegionID.ToString(), - evidence, appSetup); - else - sandbox = AppDomain.CurrentDomain; - - //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); - //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); - //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); - //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); - //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); - //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; - //sandbox.SetAppDomainPolicy(sandboxPolicy); - - m_AppDomains[appDomain] = sandbox; - - m_AppDomains[appDomain].AssemblyResolve += - new ResolveEventHandler( - AssemblyResolver.OnAssemblyResolve); - m_DomainScripts[appDomain] = new List(); - } - catch (Exception e) - { - m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); - m_ScriptErrorMessage += "Exception creating app domain:\n"; - m_ScriptFailCount++; - lock (m_AddingAssemblies) - { - m_AddingAssemblies[assembly]--; - } - return false; - } + AppDomainSetup appSetup = new AppDomainSetup(); + // appSetup.ApplicationBase = Path.Combine( + // "ScriptEngines", + // m_Scene.RegionInfo.RegionID.ToString()); + + Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; + Evidence evidence = new Evidence(baseEvidence); + + AppDomain sandbox; + if (m_AppDomainLoading) + sandbox = AppDomain.CreateDomain( + m_Scene.RegionInfo.RegionID.ToString(), + evidence, appSetup); + else + sandbox = AppDomain.CurrentDomain; + + //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); + //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); + //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); + //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); + //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); + //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; + //sandbox.SetAppDomainPolicy(sandboxPolicy); + + m_AppDomains[appDomain] = sandbox; + + m_AppDomains[appDomain].AssemblyResolve += + new ResolveEventHandler( + AssemblyResolver.OnAssemblyResolve); + m_DomainScripts[appDomain] = new List(); } - m_DomainScripts[appDomain].Add(itemID); - - instance = new ScriptInstance(this, part, - itemID, assetID, assembly, - m_AppDomains[appDomain], - part.ParentGroup.RootPart.Name, - item.Name, startParam, postOnRez, - stateSource, m_MaxScriptQueue); - - m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}", - part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString()); - - if (presence != null) + catch (Exception e) { - ShowScriptSaveResponse(item.OwnerID, - assetID, "Compile successful", true); + m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); + m_ScriptErrorMessage += "Exception creating app domain:\n"; + m_ScriptFailCount++; + lock (m_AddingAssemblies) + { + m_AddingAssemblies[assembly]--; + } + return false; } + } + m_DomainScripts[appDomain].Add(itemID); - instance.AppDomain = appDomain; - instance.LineMap = linemap; + instance = new ScriptInstance(this, part, + itemID, assetID, assembly, + m_AppDomains[appDomain], + part.ParentGroup.RootPart.Name, + item.Name, startParam, postOnRez, + stateSource, m_MaxScriptQueue); - m_Scripts[itemID] = instance; - } + m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}", + part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString()); - lock (m_PrimObjects) + if (presence != null) { - if (!m_PrimObjects.ContainsKey(localID)) - m_PrimObjects[localID] = new List(); + ShowScriptSaveResponse(item.OwnerID, + assetID, "Compile successful", true); + } - if (!m_PrimObjects[localID].Contains(itemID)) - m_PrimObjects[localID].Add(itemID); + instance.AppDomain = appDomain; + instance.LineMap = linemap; + lockScriptsForWrite(true); + m_Scripts[itemID] = instance; + lockScriptsForWrite(false); + } + else + { + lockScriptsForRead(false); + } + lock (m_PrimObjects) + { + if (!m_PrimObjects.ContainsKey(localID)) + m_PrimObjects[localID] = new List(); - } + if (!m_PrimObjects[localID].Contains(itemID)) + m_PrimObjects[localID].Add(itemID); - if (!m_Assemblies.ContainsKey(assetID)) - m_Assemblies[assetID] = assembly; + } - lock (m_AddingAssemblies) - { - m_AddingAssemblies[assembly]--; - } + if (!m_Assemblies.ContainsKey(assetID)) + m_Assemblies[assetID] = assembly; - if (instance!=null) - instance.Init(); + lock (m_AddingAssemblies) + { + m_AddingAssemblies[assembly]--; } + + if (instance!=null) + instance.Init(); + return true; } public void OnRemoveScript(uint localID, UUID itemID) { - lock (m_Scripts) + lockScriptsForRead(true); + // Do we even have it? + if (!m_Scripts.ContainsKey(itemID)) { - // Do we even have it? - if (!m_Scripts.ContainsKey(itemID)) - return; + lockScriptsForRead(false); + return; + } + - IScriptInstance instance=m_Scripts[itemID]; - m_Scripts.Remove(itemID); + IScriptInstance instance=m_Scripts[itemID]; + lockScriptsForRead(false); + lockScriptsForWrite(true); + m_Scripts.Remove(itemID); + lockScriptsForWrite(false); + instance.ClearQueue(); + instance.Stop(0); - instance.ClearQueue(); - instance.Stop(0); + SceneObjectPart part = + m_Scene.GetSceneObjectPart(localID); - SceneObjectPart part = - m_Scene.GetSceneObjectPart(localID); - - if (part != null) - part.RemoveScriptEvents(itemID); + if (part != null) + part.RemoveScriptEvents(itemID); // bool objectRemoved = false; - lock (m_PrimObjects) + lock (m_PrimObjects) + { + // Remove the script from it's prim + if (m_PrimObjects.ContainsKey(localID)) { - // Remove the script from it's prim - if (m_PrimObjects.ContainsKey(localID)) - { - // Remove inventory item record - if (m_PrimObjects[localID].Contains(itemID)) - m_PrimObjects[localID].Remove(itemID); + // Remove inventory item record + if (m_PrimObjects[localID].Contains(itemID)) + m_PrimObjects[localID].Remove(itemID); - // If there are no more scripts, remove prim - if (m_PrimObjects[localID].Count == 0) - { - m_PrimObjects.Remove(localID); + // If there are no more scripts, remove prim + if (m_PrimObjects[localID].Count == 0) + { + m_PrimObjects.Remove(localID); // objectRemoved = true; - } } } + } - instance.RemoveState(); - instance.DestroyScriptInstance(); + instance.RemoveState(); + instance.DestroyScriptInstance(); - m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); - if (m_DomainScripts[instance.AppDomain].Count == 0) - { - m_DomainScripts.Remove(instance.AppDomain); - UnloadAppDomain(instance.AppDomain); - } + m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); + if (m_DomainScripts[instance.AppDomain].Count == 0) + { + m_DomainScripts.Remove(instance.AppDomain); + UnloadAppDomain(instance.AppDomain); + } - instance = null; + instance = null; - ObjectRemoved handlerObjectRemoved = OnObjectRemoved; - if (handlerObjectRemoved != null) - handlerObjectRemoved(part.UUID); + ObjectRemoved handlerObjectRemoved = OnObjectRemoved; + if (handlerObjectRemoved != null) + handlerObjectRemoved(part.UUID); - CleanAssemblies(); - } + CleanAssemblies(); + ScriptRemoved handlerScriptRemoved = OnScriptRemoved; if (handlerScriptRemoved != null) @@ -1091,12 +1163,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine private IScriptInstance GetInstance(UUID itemID) { IScriptInstance instance; - lock (m_Scripts) + lockScriptsForRead(true); + if (!m_Scripts.ContainsKey(itemID)) { - if (!m_Scripts.ContainsKey(itemID)) - return null; - instance = m_Scripts[itemID]; + lockScriptsForRead(false); + return null; } + instance = m_Scripts[itemID]; + lockScriptsForRead(false); return instance; } @@ -1200,11 +1274,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine { List instances = new List(); - lock (m_Scripts) - { - foreach (IScriptInstance instance in m_Scripts.Values) + lockScriptsForRead(true); + foreach (IScriptInstance instance in m_Scripts.Values) instances.Add(instance); - } + lockScriptsForRead(false); foreach (IScriptInstance i in instances) { -- cgit v1.1 From 2e6dce434f1fd20664a60e464e589798287dcfe3 Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 30 Nov 2009 21:52:55 +0100 Subject: Enforce physical prim max size on single prims. Also convert a lock() to ReaderWriterLockSlim that i missed in the last commit --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 119 ++++++++++----------- 1 file changed, 58 insertions(+), 61 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index fb34ddc..42481ff 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2871,11 +2871,9 @@ namespace OpenSim.Region.Framework.Scenes scale.Y = m_scene.m_maxNonphys; if (scale.Z > m_scene.m_maxNonphys) scale.Z = m_scene.m_maxNonphys; - SceneObjectPart part = GetChildPart(localID); if (part != null) { - part.Resize(scale); if (part.PhysActor != null) { if (part.PhysActor.IsPhysical) @@ -2890,7 +2888,7 @@ namespace OpenSim.Region.Framework.Scenes part.PhysActor.Size = scale; m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); } - //if (part.UUID != m_rootPart.UUID) + part.Resize(scale); HasGroupChanged = true; ScheduleGroupForFullUpdate(); @@ -2931,77 +2929,76 @@ namespace OpenSim.Region.Framework.Scenes float y = (scale.Y / part.Scale.Y); float z = (scale.Z / part.Scale.Z); - lock (m_parts) + lockPartsForRead(true); + if (x > 1.0f || y > 1.0f || z > 1.0f) { - if (x > 1.0f || y > 1.0f || z > 1.0f) + foreach (SceneObjectPart obPart in m_parts.Values) { - foreach (SceneObjectPart obPart in m_parts.Values) + if (obPart.UUID != m_rootPart.UUID) { - if (obPart.UUID != m_rootPart.UUID) - { - Vector3 oldSize = new Vector3(obPart.Scale); + Vector3 oldSize = new Vector3(obPart.Scale); - float f = 1.0f; - float a = 1.0f; + float f = 1.0f; + float a = 1.0f; - if (part.PhysActor != null && part.PhysActor.IsPhysical) + if (part.PhysActor != null && part.PhysActor.IsPhysical) + { + if (oldSize.X*x > m_scene.m_maxPhys) { - if (oldSize.X*x > m_scene.m_maxPhys) - { - f = m_scene.m_maxPhys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y*y > m_scene.m_maxPhys) - { - f = m_scene.m_maxPhys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z*z > m_scene.m_maxPhys) - { - f = m_scene.m_maxPhys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } + f = m_scene.m_maxPhys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; } - else + if (oldSize.Y*y > m_scene.m_maxPhys) + { + f = m_scene.m_maxPhys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } + if (oldSize.Z*z > m_scene.m_maxPhys) + { + f = m_scene.m_maxPhys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; + } + } + else + { + if (oldSize.X*x > m_scene.m_maxNonphys) { - if (oldSize.X*x > m_scene.m_maxNonphys) - { - f = m_scene.m_maxNonphys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y*y > m_scene.m_maxNonphys) - { - f = m_scene.m_maxNonphys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z*z > m_scene.m_maxNonphys) - { - f = m_scene.m_maxNonphys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } + f = m_scene.m_maxNonphys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; + } + if (oldSize.Y*y > m_scene.m_maxNonphys) + { + f = m_scene.m_maxNonphys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } + if (oldSize.Z*z > m_scene.m_maxNonphys) + { + f = m_scene.m_maxNonphys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; } } } } } + lockPartsForRead(false); Vector3 prevScale = part.Scale; prevScale.X *= x; -- cgit v1.1 From cc8246206d5044aff0b306a4bcaf4b321fb826c9 Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Sat, 5 Dec 2009 09:03:02 +0100 Subject: Secnond revision of Sit and Stand for unscripted prims; Comment out spammy debug messages in Interregion.... --- OpenSim/Framework/Servers/VersionInfo.cs | 8 +- .../Interregion/RESTInterregionComms.cs | 9 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 8 + OpenSim/Region/Framework/Scenes/ScenePresence.cs | 253 ++++++++++++--------- 4 files changed, 156 insertions(+), 122 deletions(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 0d4215b..f5be1e6 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,9 +29,8 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.6.9-CM"; - private const Flavour VERSION_FLAVOUR = Flavour.Dev; - + private const string VERSION_NUMBER = "112609s"; + private const Flavour VERSION_FLAVOUR = Flavour.BetaM7; public enum Flavour { Unknown, @@ -39,7 +38,8 @@ namespace OpenSim RC1, RC2, Release, - Post_Fixes + Post_Fixes, + BetaM7 } public static string Version diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/RESTInterregionComms.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/RESTInterregionComms.cs index 710e3ca..39e2413 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/RESTInterregionComms.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/RESTInterregionComms.cs @@ -331,12 +331,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion { //m_log.Debug("[CONNECTION DEBUGGING]: AgentHandler Called"); - m_log.Debug("---------------------------"); +/* m_log.Debug("---------------------------"); m_log.Debug(" >> uri=" + request["uri"]); m_log.Debug(" >> content-type=" + request["content-type"]); m_log.Debug(" >> http-method=" + request["http-method"]); - m_log.Debug("---------------------------\n"); - + m_log.Debug("---------------------------\n"); */ Hashtable responsedata = new Hashtable(); responsedata["content_type"] = "text/html"; responsedata["keepalive"] = false; @@ -576,11 +575,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion { m_log.Debug("[CONNECTION DEBUGGING]: ObjectHandler Called"); - m_log.Debug("---------------------------"); + /* m_log.Debug("---------------------------"); m_log.Debug(" >> uri=" + request["uri"]); m_log.Debug(" >> content-type=" + request["content-type"]); m_log.Debug(" >> http-method=" + request["http-method"]); - m_log.Debug("---------------------------\n"); + m_log.Debug("---------------------------\n"); */ Hashtable responsedata = new Hashtable(); responsedata["content_type"] = "text/html"; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 19e3023..9f2c3db 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -212,6 +212,7 @@ namespace OpenSim.Region.Framework.Scenes private Quaternion m_sitTargetOrientation = Quaternion.Identity; private Vector3 m_sitTargetPosition; private string m_sitAnimation = "SIT"; + private bool m_occupied; // KF if any av is sitting on this prim private string m_text = String.Empty; private string m_touchName = String.Empty; private readonly UndoStack m_undo = new UndoStack(5); @@ -993,6 +994,13 @@ namespace OpenSim.Region.Framework.Scenes get { return _flags; } set { _flags = value; } } + + [XmlIgnore] + public bool IsOccupied // KF If an av is sittingon this prim + { + get { return m_occupied; } + set { m_occupied = value; } + } [XmlIgnore] public UUID SitTargetAvatar diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index cebd108..817b9df 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -197,6 +197,7 @@ namespace OpenSim.Region.Framework.Scenes private bool m_autopilotMoving; private Vector3 m_autoPilotTarget; private bool m_sitAtAutoTarget; + private Vector3 m_initialSitTarget; //KF: First estimate of where to sit private string m_nextSitAnimation = String.Empty; @@ -1524,7 +1525,6 @@ namespace OpenSim.Region.Framework.Scenes m_sitAtAutoTarget = false; PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; //proxy.PCode = (byte)PCode.ParticleSystem; - proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); proxyObjectGroup.AttachToScene(m_scene); @@ -1566,7 +1566,7 @@ namespace OpenSim.Region.Framework.Scenes } m_moveToPositionInProgress = true; m_moveToPositionTarget = new Vector3(locx, locy, locz); - } + } catch (Exception ex) { //Why did I get this error? @@ -1646,16 +1646,22 @@ namespace OpenSim.Region.Framework.Scenes m_parentPosition = part.GetWorldPosition(); ControllingClient.SendClearFollowCamProperties(part.ParentUUID); } + // part.GetWorldRotation() is the rotation of the object being sat on + // Rotation is the sittiing Av's rotation + + Quaternion wr = Quaternion.Inverse(Quaternion.Inverse(Rotation) * Quaternion.Inverse(part.GetWorldRotation())); // world or. of the av + Vector3 so = new Vector3(1.0f, 0f, 0f) * wr; // 1M infront of av + Vector3 wso = so + part.GetWorldPosition() + ( m_pos * part.GetWorldRotation()); // + av sit offset! if (m_physicsActor == null) { AddToPhysicalScene(false); } - m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); + AbsolutePosition = wso; //KF: Fix stand up. m_parentPosition = Vector3.Zero; -//Console.WriteLine("Stand Pos {0}", m_pos); - - m_parentID = 0; + + m_parentID = 0; + part.IsOccupied = false; SendFullUpdateToAllClients(); m_requestedSitTargetID = 0; if ((m_physicsActor != null) && (m_avHeight > 0)) @@ -1694,13 +1700,9 @@ namespace OpenSim.Region.Framework.Scenes Vector3 avSitOffSet = part.SitTargetPosition; Quaternion avSitOrientation = part.SitTargetOrientation; UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); - - bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); - bool SitTargetisSet = - (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f && - avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f)); - // this test is probably failing - if (SitTargetisSet && SitTargetUnOccupied) + bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero); + bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. + if (SitTargetisSet && !SitTargetOccupied) { //switch the target to this prim return part; @@ -1714,7 +1716,7 @@ namespace OpenSim.Region.Framework.Scenes private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset) { bool autopilot = true; - Vector3 pos = new Vector3(); + Vector3 autopilotTarget = new Vector3(); Quaternion sitOrientation = Quaternion.Identity; Vector3 cameraEyeOffset = Vector3.Zero; Vector3 cameraAtOffset = Vector3.Zero; @@ -1722,98 +1724,104 @@ namespace OpenSim.Region.Framework.Scenes //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); SceneObjectPart part = FindNextAvailableSitTarget(targetID); - if (part != null) - { - // TODO: determine position to sit at based on scene geometry; don't trust offset from client - // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it + if (part == null) return; + + // TODO: determine position to sit at based on scene geometry; don't trust offset from client + // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it - // part is the prim to sit on - // offset is the vector distance from that prim center to the click-spot - // UUID is the UUID of the Avatar doing the clicking - - m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation + // part is the prim to sit on + // offset is the world-ref vector distance from that prim center to the click-spot + // UUID is the UUID of the Avatar doing the clicking - // Is a sit target available? - Vector3 avSitOffSet = part.SitTargetPosition; - Quaternion avSitOrientation = part.SitTargetOrientation; - UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); - - bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); -// bool SitTargetisSet = -// (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f && -// avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f)); - - bool SitTargetisSet = ((Vector3.Zero != avSitOffSet) || (Quaternion.Identity != avSitOrientation)); - -//Console.WriteLine("SendSitResponse offset=" + offset + " UnOccup=" + SitTargetUnOccupied + -// " TargSet=" + SitTargetisSet); - // Sit analysis rewritten by KF 091125 - if (SitTargetisSet) // scipted sit - { - if (SitTargetUnOccupied) - { - part.SetAvatarOnSitTarget(UUID); // set that Av will be on it - offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one - sitOrientation = avSitOrientation; // Change rotatione to the scripted one - autopilot = false; // Jump direct to scripted llSitPos() - } - else return; + m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation + + // Is a sit target available? + Vector3 avSitOffSet = part.SitTargetPosition; + Quaternion avSitOrientation = part.SitTargetOrientation; + + bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. + Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); + +//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet); + // Sit analysis rewritten by KF 091125 + if (SitTargetisSet) // scipted sit + { + if (!part.IsOccupied) + { +//Console.WriteLine("Scripted, unoccupied"); + part.SetAvatarOnSitTarget(UUID); // set that Av will be on it + offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one + sitOrientation = avSitOrientation; // Change rotatione to the scripted one + autopilot = false; // Jump direct to scripted llSitPos() } - else // Not Scripted - { - if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) // large prim - { - Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); - m_avUnscriptedSitPos = offset * partIRot; // sit where clicked - pos = part.AbsolutePosition + (offset * partIRot); - } - else // small prim - { - if (SitTargetUnOccupied) - { - m_avUnscriptedSitPos = Vector3.Zero; // Sit on unoccupied small prim center - pos = part.AbsolutePosition; - } - else return; // occupied small - } // end large/small - } // end Scripted/not - - if (m_physicsActor != null) - { - // If we're not using the client autopilot, we're immediately warping the avatar to the location - // We can remove the physicsActor until they stand up. - m_sitAvatarHeight = m_physicsActor.Size.Z; - - if (autopilot) - { // its not a scripted sit - if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) - { - autopilot = false; // close enough + else + { +//Console.WriteLine("Scripted, occupied"); + return; + } + } + else // Not Scripted + { + if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) + { + // large prim & offset, ignore if other Avs sitting +// offset.Z -= 0.05f; + m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked + autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point + +//Console.WriteLine(" offset ={0}", offset); +//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos); +//Console.WriteLine(" autopilotTarget={0}", autopilotTarget); + + } + else // small offset + { +//Console.WriteLine("Small offset"); + if (!part.IsOccupied) + { + m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center + autopilotTarget = part.AbsolutePosition; + } + else return; // occupied small + } // end large/small + } // end Scripted/not + cameraAtOffset = part.GetCameraAtOffset(); + cameraEyeOffset = part.GetCameraEyeOffset(); + forceMouselook = part.GetForceMouselook(); - RemoveFromPhysicalScene(); - AbsolutePosition = pos + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to Prim - } // else the autopilot will get us close - } - else - { // its a scripted sit + if (m_physicsActor != null) + { + // If we're not using the client autopilot, we're immediately warping the avatar to the location + // We can remove the physicsActor until they stand up. + m_sitAvatarHeight = m_physicsActor.Size.Z; + if (autopilot) + { // its not a scripted sit +// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) + if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) ) + { + autopilot = false; // close enough RemoveFromPhysicalScene(); - } + AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target + } // else the autopilot will get us close + } + else + { // its a scripted sit + RemoveFromPhysicalScene(); } - - cameraAtOffset = part.GetCameraAtOffset(); - cameraEyeOffset = part.GetCameraEyeOffset(); - forceMouselook = part.GetForceMouselook(); } + else return; // physactor is null! - ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); - m_requestedSitTargetUUID = targetID; + Vector3 offsetr = offset * partIRot; + ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); + m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target // This calls HandleAgentSit twice, once from here, and the client calls // HandleAgentSit itself after it gets to the location // It doesn't get to the location until we've moved them there though // which happens in HandleAgentSit :P m_autopilotMoving = autopilot; - m_autoPilotTarget = pos; + m_autoPilotTarget = autopilotTarget; m_sitAtAutoTarget = autopilot; + m_initialSitTarget = autopilotTarget; if (!autopilot) HandleAgentSit(remoteClient, UUID); } @@ -1898,6 +1906,7 @@ namespace OpenSim.Region.Framework.Scenes { if (part.GetAvatarOnSitTarget() == UUID) { +//Console.WriteLine("Scripted Sit"); // Scripted sit Vector3 sitTargetPos = part.SitTargetPosition; Quaternion sitTargetOrient = part.SitTargetOrientation; @@ -1905,42 +1914,44 @@ namespace OpenSim.Region.Framework.Scenes m_pos += SIT_TARGET_ADJUSTMENT; m_bodyRot = sitTargetOrient; m_parentPosition = part.AbsolutePosition; + part.IsOccupied = true; } else { +//Console.WriteLine("NON Scripted Sit"); + // if m_avUnscriptedSitPos is zero then Av sits above center + // Else Av sits at m_avUnscriptedSitPos + // Non-scripted sit by Kitto Flora 21Nov09 // Calculate angle of line from prim to Av + Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos; float y_diff = (m_avInitialPos.Y - sitTargetPos.Y); float x_diff = ( m_avInitialPos.X - sitTargetPos.X); if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff); - Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'. // Av sits at world euler <0,0, z>, translated by part rotation m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click + m_parentPosition = part.AbsolutePosition; - if(m_avUnscriptedSitPos != Vector3.Zero) - { // sit where clicked on big prim - m_pos = m_avUnscriptedSitPos + (new Vector3(0.0f, 0f, 0.625f) * partIRot); - } - else - { // sit at center of small prim - m_pos = new Vector3(0f, 0f, 0.05f) + - (new Vector3(0.0f, 0f, 0.625f) * partIRot) + - (new Vector3(0.25f, 0f, 0.0f) * m_bodyRot); - //Set up raytrace to find top surface of prim - Vector3 size = part.Scale; - float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); - Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); - Vector3 down = new Vector3(0f, 0f, -1f); - m_scene.PhysicsScene.RaycastWorld( + part.IsOccupied = true; + m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation + (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center + (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) + + m_avUnscriptedSitPos; // adds click offset, if any + //Set up raytrace to find top surface of prim + Vector3 size = part.Scale; + float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); + Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); + Vector3 down = new Vector3(0f, 0f, -1f); +//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag); + m_scene.PhysicsScene.RaycastWorld( start, // Vector3 position, down, // Vector3 direction, mag, // float length, SitAltitudeCallback); // retMethod - } // end small/big } // end scripted/not } else // no Av @@ -1957,19 +1968,24 @@ namespace OpenSim.Region.Framework.Scenes SendFullUpdateToAllClients(); } - public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance) + public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance) // KF: Nov 2009 { + // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer + // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height. if(hitYN) { // m_pos = Av offset from prim center to make look like on center // m_parentPosition = Actual center pos of prim // collisionPoint = spot on prim where we want to sit + // collisionPoint.Z = global sit surface height SceneObjectPart part = m_scene.GetSceneObjectPart(localid); - Vector3 offset = (collisionPoint - m_parentPosition) * Quaternion.Inverse(part.RotationOffset); + Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); + float offZ = collisionPoint.Z - m_initialSitTarget.Z; + Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction +//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); m_pos += offset; -// Console.WriteLine("m_pos={0}, offset={1} newsit={2}", m_pos, offset, newsit); } - } + } // End SitAltitudeCallback KF. /// /// Event handler for the 'Always run' setting on the client @@ -3716,5 +3732,16 @@ namespace OpenSim.Region.Framework.Scenes m_reprioritization_called = false; } } + + private Vector3 Quat2Euler(Quaternion rot){ + float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) , + (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z))); + float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W))); + float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) , + (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z))); + return(new Vector3(x,y,z)); + } + + } } -- cgit v1.1 From 129de260329791529904c02c3515d40879d7d214 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 5 Dec 2009 23:25:30 +0000 Subject: Cause better packing of ObjectProperties --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 106 +++++++++++++++------ 1 file changed, 79 insertions(+), 27 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index e812945..71f9b90 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -352,6 +352,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP private IHyperAssetService m_hyperAssets; private const bool m_checkPackets = true; + private Timer m_propertiesPacketTimer; + private List m_propertiesBlocks = new List(); + #endregion Class Members #region Properties @@ -433,6 +436,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_udpClient.OnQueueEmpty += HandleQueueEmpty; m_udpClient.OnPacketStats += PopulateStats; + m_propertiesPacketTimer = new Timer(100); + m_propertiesPacketTimer.Elapsed += ProcessObjectPropertiesPacket; + RegisterLocalPacketHandlers(); } @@ -3562,42 +3568,88 @@ namespace OpenSim.Region.ClientStack.LindenUDP string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, uint BaseMask, byte saleType, int salePrice) { - ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); + //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); // TODO: don't create new blocks if recycling an old packet - proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[1]; - proper.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); - proper.ObjectData[0].ItemID = ItemID; - proper.ObjectData[0].CreationDate = CreationDate; - proper.ObjectData[0].CreatorID = CreatorUUID; - proper.ObjectData[0].FolderID = FolderUUID; - proper.ObjectData[0].FromTaskID = FromTaskUUID; - proper.ObjectData[0].GroupID = GroupUUID; - proper.ObjectData[0].InventorySerial = InventorySerial; - - proper.ObjectData[0].LastOwnerID = LastOwnerUUID; + ObjectPropertiesPacket.ObjectDataBlock block = + new ObjectPropertiesPacket.ObjectDataBlock(); + + block.ItemID = ItemID; + block.CreationDate = CreationDate; + block.CreatorID = CreatorUUID; + block.FolderID = FolderUUID; + block.FromTaskID = FromTaskUUID; + block.GroupID = GroupUUID; + block.InventorySerial = InventorySerial; + + block.LastOwnerID = LastOwnerUUID; // proper.ObjectData[0].LastOwnerID = UUID.Zero; - proper.ObjectData[0].ObjectID = ObjectUUID; + block.ObjectID = ObjectUUID; if (OwnerUUID == GroupUUID) - proper.ObjectData[0].OwnerID = UUID.Zero; + block.OwnerID = UUID.Zero; else - proper.ObjectData[0].OwnerID = OwnerUUID; - proper.ObjectData[0].TouchName = Util.StringToBytes256(TouchTitle); - proper.ObjectData[0].TextureID = TextureID; - proper.ObjectData[0].SitName = Util.StringToBytes256(SitTitle); - proper.ObjectData[0].Name = Util.StringToBytes256(ItemName); - proper.ObjectData[0].Description = Util.StringToBytes256(ItemDescription); - proper.ObjectData[0].OwnerMask = OwnerMask; - proper.ObjectData[0].NextOwnerMask = NextOwnerMask; - proper.ObjectData[0].GroupMask = GroupMask; - proper.ObjectData[0].EveryoneMask = EveryoneMask; - proper.ObjectData[0].BaseMask = BaseMask; + block.OwnerID = OwnerUUID; + block.TouchName = Util.StringToBytes256(TouchTitle); + block.TextureID = TextureID; + block.SitName = Util.StringToBytes256(SitTitle); + block.Name = Util.StringToBytes256(ItemName); + block.Description = Util.StringToBytes256(ItemDescription); + block.OwnerMask = OwnerMask; + block.NextOwnerMask = NextOwnerMask; + block.GroupMask = GroupMask; + block.EveryoneMask = EveryoneMask; + block.BaseMask = BaseMask; // proper.ObjectData[0].AggregatePerms = 53; // proper.ObjectData[0].AggregatePermTextures = 0; // proper.ObjectData[0].AggregatePermTexturesOwner = 0; - proper.ObjectData[0].SaleType = saleType; - proper.ObjectData[0].SalePrice = salePrice; + block.SaleType = saleType; + block.SalePrice = salePrice; + + lock (m_propertiesPacketTimer) + { + m_propertiesBlocks.Add(block); + + int length = 0; + foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) + { + length += b.Length; + } + if (length > 1100) // FIXME: use real MTU + { + ProcessObjectPropertiesPacket(null, null); + m_propertiesPacketTimer.Stop(); + return; + } + + m_propertiesPacketTimer.Stop(); + m_propertiesPacketTimer.Start(); + } + + //proper.Header.Zerocoded = true; + //OutPacket(proper, ThrottleOutPacketType.Task); + } + + private void ProcessObjectPropertiesPacket(Object sender, ElapsedEventArgs e) + { + ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); + + lock (m_propertiesPacketTimer) + { + m_propertiesPacketTimer.Stop(); + + proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; + + int index = 0; + + foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) + { + proper.ObjectData[index++] = b; + } + + m_propertiesBlocks.Clear(); + } + proper.Header.Zerocoded = true; OutPacket(proper, ThrottleOutPacketType.Task); } -- cgit v1.1 From ceccfe02d0e25c234560b6ef25306b8db4cd9875 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 00:02:24 +0000 Subject: Eliminate multiple updates on link/unlink --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 ++ OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 8 ++++---- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 2fdb48d..d87e814 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1593,6 +1593,8 @@ namespace OpenSim.Region.Framework.Scenes // occur on link to invoke this elsewhere (such as object selection) parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); parentGroup.TriggerScriptChangedEvent(Changed.LINK); + parentGroup.HasGroupChanged = true; + parentGroup.ScheduleGroupForFullUpdate(); if (client != null) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ecda80c..fa2e3ce 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2389,8 +2389,8 @@ namespace OpenSim.Region.Framework.Scenes // unmoved prims! ResetChildPrimPhysicsPositions(); - HasGroupChanged = true; - ScheduleGroupForFullUpdate(); + //HasGroupChanged = true; + //ScheduleGroupForFullUpdate(); } /// @@ -2483,8 +2483,8 @@ namespace OpenSim.Region.Framework.Scenes linkPart.Rezzed = RootPart.Rezzed; - HasGroupChanged = true; - ScheduleGroupForFullUpdate(); + //HasGroupChanged = true; + //ScheduleGroupForFullUpdate(); } /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 267928b..e694f15 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3588,6 +3588,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { parentPrim.DelinkFromGroup(part.LocalId, true); } + parentPrim.HasGroupChanged = true; + parentPrim.ScheduleGroupForFullUpdate(); parentPrim.TriggerScriptChangedEvent(Changed.LINK); if (parts.Count > 0) @@ -3599,6 +3601,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api part.UpdateFlag = 0; newRoot.ParentGroup.LinkToGroup(part.ParentGroup); } + newRoot.ParentGroup.HasGroupChanged = true; + newRoot.ParentGroup.ScheduleGroupForFullUpdate(); } } else @@ -3607,6 +3611,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; parentPrim.DelinkFromGroup(childPrim.LocalId, true); + parentPrim.HasGroupChanged = true; + parentPrim.ScheduleGroupForFullUpdate(); parentPrim.TriggerScriptChangedEvent(Changed.LINK); } } @@ -3626,6 +3632,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api parentPrim.DelinkFromGroup(part.LocalId, true); parentPrim.TriggerScriptChangedEvent(Changed.LINK); } + parentPrim.HasGroupChanged = true; + parentPrim.ScheduleGroupForFullUpdate(); } public LSL_String llGetLinkKey(int linknum) -- cgit v1.1 From fbefa8273be70d90404b37230c168fd031288e31 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 00:25:04 +0000 Subject: Lock updates out while linking and unlinking --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 255 ++++++++++++++------------ 1 file changed, 134 insertions(+), 121 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index d87e814..5efe188 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -26,6 +26,7 @@ */ using System; +using System.Threading; using System.Collections.Generic; using System.Reflection; using OpenMetaverse; @@ -96,6 +97,8 @@ namespace OpenSim.Region.Framework.Scenes protected internal Dictionary SceneObjectGroupsByFullID = new Dictionary(); private readonly Object m_dictionary_lock = new Object(); + private Object m_updateLock = new Object(); + #endregion protected internal SceneGraph(Scene parent, RegionInfo regInfo) @@ -369,6 +372,9 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void UpdateObjectGroups() { + if (!Monitor.TryEnter(m_updateLock)) + return; + List updates; // Some updates add more updates to the updateList. @@ -395,6 +401,7 @@ namespace OpenSim.Region.Framework.Scenes "[INNER SCENE]: Failed to update {0}, {1} - {2}", sog.Name, sog.UUID, e); } } + Monitor.Exit(m_updateLock); } protected internal void AddPhysicalPrim(int number) @@ -1555,56 +1562,59 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List childPrimIds) { - SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId); - - List childGroups = new List(); - if (parentGroup != null) + lock (m_updateLock) { - // We do this in reverse to get the link order of the prims correct - for (int i = childPrimIds.Count - 1; i >= 0; i--) + SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId); + + List childGroups = new List(); + if (parentGroup != null) { - SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]); - if (child != null) + // We do this in reverse to get the link order of the prims correct + for (int i = childPrimIds.Count - 1; i >= 0; i--) { - // Make sure no child prim is set for sale - // So that, on delink, no prims are unwittingly - // left for sale and sold off - child.RootPart.ObjectSaleType = 0; - child.RootPart.SalePrice = 10; - childGroups.Add(child); + SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]); + if (child != null) + { + // Make sure no child prim is set for sale + // So that, on delink, no prims are unwittingly + // left for sale and sold off + child.RootPart.ObjectSaleType = 0; + child.RootPart.SalePrice = 10; + childGroups.Add(child); + } } } - } - else - { - return; // parent is null so not in this region - } + else + { + return; // parent is null so not in this region + } - foreach (SceneObjectGroup child in childGroups) - { - parentGroup.LinkToGroup(child); + foreach (SceneObjectGroup child in childGroups) + { + parentGroup.LinkToGroup(child); - // this is here so physics gets updated! - // Don't remove! Bad juju! Stay away! or fix physics! - child.AbsolutePosition = child.AbsolutePosition; - } + // this is here so physics gets updated! + // Don't remove! Bad juju! Stay away! or fix physics! + child.AbsolutePosition = child.AbsolutePosition; + } - // We need to explicitly resend the newly link prim's object properties since no other actions - // occur on link to invoke this elsewhere (such as object selection) - parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); - parentGroup.TriggerScriptChangedEvent(Changed.LINK); - parentGroup.HasGroupChanged = true; - parentGroup.ScheduleGroupForFullUpdate(); - - if (client != null) - { - parentGroup.GetProperties(client); - } - else - { - foreach (ScenePresence p in GetScenePresences()) + // We need to explicitly resend the newly link prim's object properties since no other actions + // occur on link to invoke this elsewhere (such as object selection) + parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); + parentGroup.TriggerScriptChangedEvent(Changed.LINK); + parentGroup.HasGroupChanged = true; + parentGroup.ScheduleGroupForFullUpdate(); + + if (client != null) { - parentGroup.GetProperties(p.ControllingClient); + parentGroup.GetProperties(client); + } + else + { + foreach (ScenePresence p in GetScenePresences()) + { + parentGroup.GetProperties(p.ControllingClient); + } } } } @@ -1620,109 +1630,112 @@ namespace OpenSim.Region.Framework.Scenes protected internal void DelinkObjects(List primIds, bool sendEvents) { - List childParts = new List(); - List rootParts = new List(); - List affectedGroups = new List(); - // Look them all up in one go, since that is comparatively expensive - // - foreach (uint primID in primIds) + lock (m_updateLock) { - SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); - if (part != null) + List childParts = new List(); + List rootParts = new List(); + List affectedGroups = new List(); + // Look them all up in one go, since that is comparatively expensive + // + foreach (uint primID in primIds) { - if (part.LinkNum < 2) // Root or single - rootParts.Add(part); + SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); + if (part != null) + { + if (part.LinkNum < 2) // Root or single + rootParts.Add(part); + else + childParts.Add(part); + + SceneObjectGroup group = part.ParentGroup; + if (!affectedGroups.Contains(group)) + affectedGroups.Add(group); + } else - childParts.Add(part); - - SceneObjectGroup group = part.ParentGroup; - if (!affectedGroups.Contains(group)) - affectedGroups.Add(group); + { + m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID); + } } - else + + foreach (SceneObjectPart child in childParts) { - m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID); + // Unlink all child parts from their groups + // + child.ParentGroup.DelinkFromGroup(child, sendEvents); } - } - foreach (SceneObjectPart child in childParts) - { - // Unlink all child parts from their groups - // - child.ParentGroup.DelinkFromGroup(child, sendEvents); - } - - foreach (SceneObjectPart root in rootParts) - { - // In most cases, this will run only one time, and the prim - // will be a solo prim - // However, editing linked parts and unlinking may be different - // - SceneObjectGroup group = root.ParentGroup; - List newSet = new List(group.Children.Values); - int numChildren = group.Children.Count; - - // If there are prims left in a link set, but the root is - // slated for unlink, we need to do this - // - if (numChildren != 1) + foreach (SceneObjectPart root in rootParts) { - // Unlink the remaining set + // In most cases, this will run only one time, and the prim + // will be a solo prim + // However, editing linked parts and unlinking may be different // - bool sendEventsToRemainder = true; - if (numChildren > 1) - sendEventsToRemainder = false; - - foreach (SceneObjectPart p in newSet) - { - if (p != group.RootPart) - group.DelinkFromGroup(p, sendEventsToRemainder); - } + SceneObjectGroup group = root.ParentGroup; + List newSet = new List(group.Children.Values); + int numChildren = group.Children.Count; - // If there is more than one prim remaining, we - // need to re-link + // If there are prims left in a link set, but the root is + // slated for unlink, we need to do this // - if (numChildren > 2) + if (numChildren != 1) { - // Remove old root + // Unlink the remaining set // - if (newSet.Contains(root)) - newSet.Remove(root); + bool sendEventsToRemainder = true; + if (numChildren > 1) + sendEventsToRemainder = false; - // Preserve link ordering - // - newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) + foreach (SceneObjectPart p in newSet) { - return a.LinkNum.CompareTo(b.LinkNum); - }); + if (p != group.RootPart) + group.DelinkFromGroup(p, sendEventsToRemainder); + } - // Determine new root + // If there is more than one prim remaining, we + // need to re-link // - SceneObjectPart newRoot = newSet[0]; - newSet.RemoveAt(0); + if (numChildren > 2) + { + // Remove old root + // + if (newSet.Contains(root)) + newSet.Remove(root); + + // Preserve link ordering + // + newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) + { + return a.LinkNum.CompareTo(b.LinkNum); + }); - List linkIDs = new List(); + // Determine new root + // + SceneObjectPart newRoot = newSet[0]; + newSet.RemoveAt(0); - foreach (SceneObjectPart newChild in newSet) - { - newChild.UpdateFlag = 0; - linkIDs.Add(newChild.LocalId); - } + List linkIDs = new List(); + + foreach (SceneObjectPart newChild in newSet) + { + newChild.UpdateFlag = 0; + linkIDs.Add(newChild.LocalId); + } - LinkObjects(null, newRoot.LocalId, linkIDs); - if (!affectedGroups.Contains(newRoot.ParentGroup)) - affectedGroups.Add(newRoot.ParentGroup); + LinkObjects(null, newRoot.LocalId, linkIDs); + if (!affectedGroups.Contains(newRoot.ParentGroup)) + affectedGroups.Add(newRoot.ParentGroup); + } } } - } - // Finally, trigger events in the roots - // - foreach (SceneObjectGroup g in affectedGroups) - { - g.TriggerScriptChangedEvent(Changed.LINK); - g.HasGroupChanged = true; // Persist - g.ScheduleGroupForFullUpdate(); + // Finally, trigger events in the roots + // + foreach (SceneObjectGroup g in affectedGroups) + { + g.TriggerScriptChangedEvent(Changed.LINK); + g.HasGroupChanged = true; // Persist + g.ScheduleGroupForFullUpdate(); + } } } -- cgit v1.1 From f2891e77383f70d807f4ef1ceefbf9a0f2bf6a84 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 00:50:28 +0000 Subject: Remove extra forced updates. They're not needed for each prim. Really. --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index fa2e3ce..93888f1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2292,14 +2292,14 @@ namespace OpenSim.Region.Framework.Scenes public void LinkToGroup(SceneObjectGroup objectGroup) { // Make sure we have sent any pending unlinks or stuff. - if (objectGroup.RootPart.UpdateFlag > 0) - { - m_log.WarnFormat( - "[SCENE OBJECT GROUP]: Forcing send of linkset {0}, {1} to {2}, {3} as its still waiting.", - objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); + //if (objectGroup.RootPart.UpdateFlag > 0) + //{ + // m_log.WarnFormat( + // "[SCENE OBJECT GROUP]: Forcing send of linkset {0}, {1} to {2}, {3} as its still waiting.", + // objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); - objectGroup.RootPart.SendScheduledUpdates(); - } + // objectGroup.RootPart.SendScheduledUpdates(); + //} // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", -- cgit v1.1 From da414fd509a6adfa0499b71172e1c789b3cf7ca4 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 01:20:39 +0000 Subject: Change locking to not mix explicit Monitor.* calls with lock() --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 5efe188..4bdc52c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1562,7 +1562,8 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List childPrimIds) { - lock (m_updateLock) + Monitor.Enter(m_updateLock); + try { SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId); @@ -1617,6 +1618,10 @@ namespace OpenSim.Region.Framework.Scenes } } } + finally + { + Monitor.Exit(m_updateLock); + } } /// @@ -1630,7 +1635,8 @@ namespace OpenSim.Region.Framework.Scenes protected internal void DelinkObjects(List primIds, bool sendEvents) { - lock (m_updateLock) + Monitor.Enter(m_updateLock); + try { List childParts = new List(); List rootParts = new List(); @@ -1737,6 +1743,10 @@ namespace OpenSim.Region.Framework.Scenes g.ScheduleGroupForFullUpdate(); } } + finally + { + Monitor.Exit(m_updateLock); + } } protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint localID) -- cgit v1.1 From 2fe75a62bec2f06155bf5f05b6f558d028f6b12c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 02:00:32 +0000 Subject: Skip single prims in unlink selections --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 4bdc52c..18e7b79 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1648,14 +1648,17 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); if (part != null) { - if (part.LinkNum < 2) // Root or single - rootParts.Add(part); - else - childParts.Add(part); - - SceneObjectGroup group = part.ParentGroup; - if (!affectedGroups.Contains(group)) - affectedGroups.Add(group); + if (part.ParentGroup.Children.Count != 1) // Skip single + { + if (part.LinkNum < 2) // Root + rootParts.Add(part); + else + childParts.Add(part); + + SceneObjectGroup group = part.ParentGroup; + if (!affectedGroups.Contains(group)) + affectedGroups.Add(group); + } } else { -- cgit v1.1 From 79511ecce240a864dc02575acd3399fb244a8d82 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 02:15:52 +0000 Subject: Experimental: Remove explicit property sends --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 18e7b79..f74fd5d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1606,17 +1606,17 @@ namespace OpenSim.Region.Framework.Scenes parentGroup.HasGroupChanged = true; parentGroup.ScheduleGroupForFullUpdate(); - if (client != null) - { - parentGroup.GetProperties(client); - } - else - { - foreach (ScenePresence p in GetScenePresences()) - { - parentGroup.GetProperties(p.ControllingClient); - } - } +// if (client != null) +// { +// parentGroup.GetProperties(client); +// } +// else +// { +// foreach (ScenePresence p in GetScenePresences()) +// { +// parentGroup.GetProperties(p.ControllingClient); +// } +// } } finally { -- cgit v1.1 From f9ae9afaacc82ee0284b1f7dc88ad880aabe23af Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 03:10:34 +0000 Subject: Fix build break from conflicted merge --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 3d4490a..f6bcb59 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1972,7 +1972,7 @@ namespace OpenSim.Region.Framework.Scenes SendFullUpdateToAllClients(); } - public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance) + public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal) { if(hitYN) { -- cgit v1.1 From 1e222d52e6219db4ad32338b952a94eebb0f7799 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 03:56:15 +0000 Subject: Change EntityManager to use RWlocks --- OpenSim/Region/Framework/Scenes/EntityManager.cs | 79 ++++++++++++++++++++---- 1 file changed, 67 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs index 099fcce..c246e32 100644 --- a/OpenSim/Region/Framework/Scenes/EntityManager.cs +++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs @@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Scenes private readonly Dictionary m_eb_uuid = new Dictionary(); private readonly Dictionary m_eb_localID = new Dictionary(); //private readonly Dictionary m_pres_uuid = new Dictionary(); - private readonly Object m_lock = new Object(); + private System.Threading.ReaderWriterLockSlim m_lock = new System.Threading.ReaderWriterLockSlim(); [Obsolete("Use Add() instead.")] public void Add(UUID id, EntityBase eb) @@ -50,7 +50,8 @@ namespace OpenSim.Region.Framework.Scenes public void Add(EntityBase entity) { - lock (m_lock) + m_lock.EnterWriteLock(); + try { try { @@ -62,11 +63,16 @@ namespace OpenSim.Region.Framework.Scenes m_log.ErrorFormat("Add Entity failed: {0}", e.Message); } } + finally + { + m_lock.ExitWriteLock(); + } } public void InsertOrReplace(EntityBase entity) { - lock (m_lock) + m_lock.EnterWriteLock(); + try { try { @@ -78,15 +84,24 @@ namespace OpenSim.Region.Framework.Scenes m_log.ErrorFormat("Insert or Replace Entity failed: {0}", e.Message); } } + finally + { + m_lock.ExitWriteLock(); + } } public void Clear() { - lock (m_lock) + m_lock.EnterWriteLock(); + try { m_eb_uuid.Clear(); m_eb_localID.Clear(); } + finally + { + m_lock.ExitWriteLock(); + } } public int Count @@ -123,7 +138,8 @@ namespace OpenSim.Region.Framework.Scenes public bool Remove(uint localID) { - lock (m_lock) + m_lock.EnterWriteLock(); + try { try { @@ -141,11 +157,16 @@ namespace OpenSim.Region.Framework.Scenes return false; } } + finally + { + m_lock.ExitWriteLock(); + } } public bool Remove(UUID id) { - lock (m_lock) + m_lock.EnterWriteLock(); + try { try { @@ -163,13 +184,18 @@ namespace OpenSim.Region.Framework.Scenes return false; } } + finally + { + m_lock.ExitWriteLock(); + } } public List GetAllByType() { List tmp = new List(); - lock (m_lock) + m_lock.EnterReadLock(); + try { try { @@ -187,23 +213,33 @@ namespace OpenSim.Region.Framework.Scenes tmp = null; } } + finally + { + m_lock.ExitReadLock(); + } return tmp; } public List GetEntities() { - lock (m_lock) + m_lock.EnterReadLock(); + try { return new List(m_eb_uuid.Values); } + finally + { + m_lock.ExitReadLock(); + } } public EntityBase this[UUID id] { get { - lock (m_lock) + m_lock.EnterReadLock(); + try { EntityBase entity; if (m_eb_uuid.TryGetValue(id, out entity)) @@ -211,6 +247,10 @@ namespace OpenSim.Region.Framework.Scenes else return null; } + finally + { + m_lock.ExitReadLock(); + } } set { @@ -222,7 +262,8 @@ namespace OpenSim.Region.Framework.Scenes { get { - lock (m_lock) + m_lock.EnterReadLock(); + try { EntityBase entity; if (m_eb_localID.TryGetValue(localID, out entity)) @@ -230,6 +271,10 @@ namespace OpenSim.Region.Framework.Scenes else return null; } + finally + { + m_lock.ExitReadLock(); + } } set { @@ -239,18 +284,28 @@ namespace OpenSim.Region.Framework.Scenes public bool TryGetValue(UUID key, out EntityBase obj) { - lock (m_lock) + m_lock.EnterReadLock(); + try { return m_eb_uuid.TryGetValue(key, out obj); } + finally + { + m_lock.ExitReadLock(); + } } public bool TryGetValue(uint key, out EntityBase obj) { - lock (m_lock) + m_lock.EnterReadLock(); + try { return m_eb_localID.TryGetValue(key, out obj); } + finally + { + m_lock.ExitReadLock(); + } } /// -- cgit v1.1 From cade14c58c335503221753b10ec361898ce5f9d4 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 05:14:17 +0000 Subject: Make ObjectSelect packet processing not use FireAndForget --- OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 85961b9..9996857 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -964,7 +964,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (packetInbox.Dequeue(100, ref incomingPacket)) - Util.FireAndForget(ProcessInPacket, incomingPacket); + { + if (incomingPacket.Packet.Type != PacketType.ObjectSelect) + Util.FireAndForget(ProcessInPacket, incomingPacket); + else + ProcessInPacket(incomingPacket); + } } catch (Exception ex) { -- cgit v1.1 From 23cd1b195424bb4a844e1f2397047e5d5080c5ad Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 6 Dec 2009 05:24:43 +0000 Subject: Revert "Make ObjectSelect packet processing not use FireAndForget" This reverts commit cade14c58c335503221753b10ec361898ce5f9d4. --- OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 9996857..85961b9 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -964,12 +964,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (packetInbox.Dequeue(100, ref incomingPacket)) - { - if (incomingPacket.Packet.Type != PacketType.ObjectSelect) - Util.FireAndForget(ProcessInPacket, incomingPacket); - else - ProcessInPacket(incomingPacket); - } + Util.FireAndForget(ProcessInPacket, incomingPacket); } catch (Exception ex) { -- cgit v1.1 From 172e2f4e7609c278d02ad83ca207fd79624db587 Mon Sep 17 00:00:00 2001 From: CasperW Date: Sun, 6 Dec 2009 17:23:07 +0100 Subject: Fix to existing ReaderWriterLockSlim implementations --- OpenSim/Framework/TaskInventoryDictionary.cs | 10 ++++++++-- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 10 ++++++++-- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 3 ++- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 10 ++++++++-- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index efe5f0c..4b9a509 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs @@ -109,7 +109,10 @@ namespace OpenSim.Framework } else { - m_itemLock.ExitReadLock(); + if (m_itemLock.RecursiveReadCount>0) + { + m_itemLock.ExitReadLock(); + } } } @@ -144,7 +147,10 @@ namespace OpenSim.Framework } else { - m_itemLock.ExitWriteLock(); + if (m_itemLock.RecursiveWriteCount > 0) + { + m_itemLock.ExitWriteLock(); + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 93888f1..eacd219 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -126,7 +126,10 @@ namespace OpenSim.Region.Framework.Scenes } else { - m_partsLock.ExitReadLock(); + if (m_partsLock.RecursiveReadCount > 0) + { + m_partsLock.ExitReadLock(); + } } } public void lockPartsForWrite(bool locked) @@ -155,7 +158,10 @@ namespace OpenSim.Region.Framework.Scenes } else { - m_partsLock.ExitWriteLock(); + if (m_partsLock.RecursiveWriteCount > 0) + { + m_partsLock.ExitWriteLock(); + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 4780ff2..b57d912 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -320,17 +320,18 @@ namespace OpenSim.Region.Framework.Scenes { if (m_items.ContainsKey(itemId)) { + m_items.LockItemsForRead(false); CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); } else { + m_items.LockItemsForRead(false); m_log.ErrorFormat( "[PRIM INVENTORY]: " + "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", itemId, m_part.Name, m_part.UUID, m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); } - m_items.LockItemsForRead(false); } else { diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 49c69ab..184af19 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -150,7 +150,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine } else { - m_scriptsLock.ExitReadLock(); + if (m_scriptsLock.RecursiveReadCount > 0) + { + m_scriptsLock.ExitReadLock(); + } } } private void lockScriptsForWrite(bool locked) @@ -179,7 +182,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine } else { - m_scriptsLock.ExitWriteLock(); + if (m_scriptsLock.RecursiveWriteCount > 0) + { + m_scriptsLock.ExitWriteLock(); + } } } -- cgit v1.1 From 0d1d437bd3bf608448d71ea7de8e4f7cfb0371f0 Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Sun, 6 Dec 2009 21:11:59 +0100 Subject: Fix linked physical daughter prim position update. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 17 ++++++++++++++--- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 -- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 9f2c3db..a6382ee 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -513,9 +513,16 @@ namespace OpenSim.Region.Framework.Scenes { // If this is a linkset, we don't want the physics engine mucking up our group position here. PhysicsActor actor = PhysActor; - if (actor != null && _parentID == 0) + if (actor != null) { - m_groupPosition = actor.Position; + if (_parentID == 0) + { + m_groupPosition = actor.Position; + } + else + { + m_groupPosition = ParentGroup.AbsolutePosition; // KF+Casper Update Child prims too! + } } if (IsAttachment) @@ -1743,9 +1750,13 @@ namespace OpenSim.Region.Framework.Scenes Quaternion parentRot = ParentGroup.RootPart.RotationOffset; Vector3 axPos = OffsetPosition; - axPos *= parentRot; Vector3 translationOffsetPosition = axPos; + + int tx = (int)GroupPosition.X; + int ty = (int)GroupPosition.Y; + int tz = (int)GroupPosition.Z; + return GroupPosition + translationOffsetPosition; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 817b9df..5d0218f 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1642,7 +1642,6 @@ namespace OpenSim.Region.Framework.Scenes // Reset sit target. if (part.GetAvatarOnSitTarget() == UUID) part.SetAvatarOnSitTarget(UUID.Zero); - m_parentPosition = part.GetWorldPosition(); ControllingClient.SendClearFollowCamProperties(part.ParentUUID); } @@ -1659,7 +1658,6 @@ namespace OpenSim.Region.Framework.Scenes } AbsolutePosition = wso; //KF: Fix stand up. m_parentPosition = Vector3.Zero; - m_parentID = 0; part.IsOccupied = false; SendFullUpdateToAllClients(); -- cgit v1.1 From c2d3afdeee1b1b8b9b4ef0c6588777536adc15db Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 7 Dec 2009 14:31:20 +0000 Subject: Same for the remote auth connector --- .../Authorization/RemoteAuthorizationServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs index fca2df2..68499f3 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authorization/RemoteAuthorizationServiceConnector.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authorization IConfig authorizationConfig = source.Configs["AuthorizationService"]; if (authorizationConfig == null) { - m_log.Error("[REMOTE AUTHORIZATION CONNECTOR]: AuthorizationService missing from OpenSim.ini"); + m_log.Info("[REMOTE AUTHORIZATION CONNECTOR]: AuthorizationService missing from OpenSim.ini"); return; } -- cgit v1.1 From 29a740ec8c78bfc3c1ab5b41b302ae2205c6e9aa Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Dec 2009 18:03:53 +0100 Subject: Initial windlight codebase commit --- OpenSim/Client/MXP/ClientStack/MXPClientView.cs | 2 +- .../Client/VWoHTTP/ClientStack/VWHClientView.cs | 2 +- OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs | 9 +- OpenSim/Data/MySQL/MySQLLegacyRegionData.cs | 192 +++++++++++++++++++++ OpenSim/Data/Null/NullDataStore.cs | 7 +- OpenSim/Data/SQLite/SQLiteRegionData.cs | 7 +- OpenSim/Framework/IClientAPI.cs | 2 +- OpenSim/Framework/RegionInfo.cs | 69 +++++++- .../Region/ClientStack/LindenUDP/LLClientView.cs | 6 +- .../Region/Examples/SimpleModule/MyNpcCharacter.cs | 2 +- .../Framework/Interfaces/IRegionDataStore.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.cs | 2 + .../Region/Framework/Scenes/Tests/SceneTests.cs | 7 +- .../Server/IRCClientView.cs | 2 +- .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 2 +- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 16 files changed, 297 insertions(+), 17 deletions(-) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 0cae3dd..9f9d151 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -902,7 +902,7 @@ namespace OpenSim.Client.MXP.ClientStack // Need to translate to MXP somehow } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, List message) { // Need to translate to MXP somehow } diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index fb87c15..533475f 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -483,7 +483,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack throw new System.NotImplementedException(); } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, List message) { throw new System.NotImplementedException(); } diff --git a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs index 6371307..678b251 100644 --- a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs @@ -671,7 +671,12 @@ VALUES cmd.ExecuteNonQuery(); } } - + public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionMeta7WindlightData(); + } /// /// Loads the settings of a region. /// @@ -696,7 +701,7 @@ VALUES } } - //If comes here then there is now region setting for that region + //If we reach this point then there are new region settings for that region regionSettings = new RegionSettings(); regionSettings.RegionUUID = regionUUID; regionSettings.OnSave += StoreRegionSettings; diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs index c49153f..e47d2a5 100644 --- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs @@ -691,6 +691,97 @@ namespace OpenSim.Data.MySQL } } + public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + { + RegionMeta7WindlightData nWP = new RegionMeta7WindlightData(); + nWP.OnSave += StoreRegionWindlightSettings; + lock (m_Connection) + { + + string command = "select * from `regionwindlight` where region_id = ?regionID"; + + MySqlCommand cmd = new MySqlCommand(command); + + cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); + + IDataReader result = ExecuteReader(cmd); + if (!result.Read()) + { + //No result, so store our default windlight profile and return it + nWP.regionID = regionUUID; + StoreRegionWindlightSettings(nWP); + return nWP; + } + else + { + UUID.TryParse(result["region_id"].ToString(), out nWP.regionID); + nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); + nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); + nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); + nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); + nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); + nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); + nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); + nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); + nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); + nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); + nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); + nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); + nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); + nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); + nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); + nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); + nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); + UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); + nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); + nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); + nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); + nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); + nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); + nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); + nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); + nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); + nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); + nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); + nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); + nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); + nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); + nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); + nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); + nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); + nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); + nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); + nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); + nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); + nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); + nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); + nWP.eastAngle = Convert.ToSingle(result["east_angle"]); + nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); + nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); + nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); + nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); + nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); + nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); + nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); + nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); + nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); + nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); + nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); + nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); + nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); + nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); + nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); + nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); + nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); + nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); + nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); + nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); + nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); + } + } + return nWP; + } + public RegionSettings LoadRegionSettings(UUID regionUUID) { RegionSettings rs = null; @@ -724,6 +815,107 @@ namespace OpenSim.Data.MySQL return rs; } + public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + { + lock (m_Connection) + { + using (MySqlCommand cmd = m_Connection.CreateCommand()) + { + cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; + cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; + cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, "; + cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, "; + cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, "; + cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, "; + cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, "; + cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, "; + cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, "; + cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, "; + cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, "; + cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, "; + cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, "; + cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, "; + cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, "; + cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, "; + cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, "; + cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, "; + cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, "; + cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, "; + cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, "; + cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, "; + cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, "; + cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, "; + cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)"; + + cmd.Parameters.AddWithValue("region_id", wl.regionID); + cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); + cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); + cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); + cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); + cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); + cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); + cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); + cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); + cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); + cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); + cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); + cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); + cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); + cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); + cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); + cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); + cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); + cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); + cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); + cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); + cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); + cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); + cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); + cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); + cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); + cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); + cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); + cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); + cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); + cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); + cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); + cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); + cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); + cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); + cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); + cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); + cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); + cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); + cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); + cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); + cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); + cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); + cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); + cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); + cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); + cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); + cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); + cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); + cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); + cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); + cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); + cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); + cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); + cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); + cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); + cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); + cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); + cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); + cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); + cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); + cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); + cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); + + ExecuteNonQuery(cmd); + } + } + } + public void StoreRegionSettings(RegionSettings rs) { lock (m_Connection) diff --git a/OpenSim/Data/Null/NullDataStore.cs b/OpenSim/Data/Null/NullDataStore.cs index 427fa0a..39ca8f9 100644 --- a/OpenSim/Data/Null/NullDataStore.cs +++ b/OpenSim/Data/Null/NullDataStore.cs @@ -50,7 +50,12 @@ namespace OpenSim.Data.Null public void StoreRegionSettings(RegionSettings rs) { } - + public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionMeta7WindlightData(); + } public RegionSettings LoadRegionSettings(UUID regionUUID) { return null; diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs index b68de1a..53b806c 100644 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLite/SQLiteRegionData.cs @@ -272,7 +272,12 @@ namespace OpenSim.Data.SQLite Commit(); } } - + public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionMeta7WindlightData(); + } public RegionSettings LoadRegionSettings(UUID regionUUID) { lock (ds) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 04ba9c6..cb136e2 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1077,7 +1077,7 @@ namespace OpenSim.Framework void SendInstantMessage(GridInstantMessage im); - void SendGenericMessage(string method, List message); + void SendGenericMessage(string method, List message); void SendLayerData(float[] map); void SendLayerData(int px, int py, float[] map); diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 721233d..c39cc03 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -36,8 +36,59 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework.Console; + namespace OpenSim.Framework { + public class RegionMeta7WindlightData + { + public UUID regionID = UUID.Zero; + public Vector3 waterColor = new Vector3(4.0f,38.0f,64.0f); + public float waterFogDensityExponent = 4.0f; + public float underwaterFogModifier = 0.25f; + public Vector3 reflectionWaveletScale = new Vector3(2.0f,2.0f,2.0f); + public float fresnelScale = 0.40f; + public float fresnelOffset = 0.50f; + public float refractScaleAbove = 0.03f; + public float refractScaleBelow = 0.20f; + public float blurMultiplier = 0.040f; + public Vector2 bigWaveDirection = new Vector2(1.05f,-0.42f); + public Vector2 littleWaveDirection = new Vector2(1.11f,-1.16f); + public UUID normalMapTexture = new UUID("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); + public Vector4 horizon = new Vector4(0.26f, 0.24f, 0.34f, 0.33f); + public float hazeHorizon = 0.19f; + public Vector4 blueDensity = new Vector4(0.10f, 0.93f, 0.02f, 0.93f); + public float hazeDensity = 0.70f; + public float densityMultiplier = 0.18f; + public float distanceMultiplier = 0.8f; + public UInt16 maxAltitude = 1605; + public Vector4 sunMoonColor = new Vector4(0.24f, 0.26f, 0.30f, 0.30f); + public float sunMoonPosition = 0.335f; + public Vector4 ambient = new Vector4(0.35f,0.35f,0.35f,0.35f); + public float eastAngle = 0.0f; + public float sunGlowFocus = 0.10f; + public float sunGlowSize = 0.10f; + public float sceneGamma = 1.0f; + public float starBrightness = 0.0f; + public Vector4 cloudColor = new Vector4(0.41f, 0.41f, 0.41f, 0.41f); + public Vector3 cloudXYDensity = new Vector3(1.00f, 0.53f, 1.00f); + public float cloudCoverage = 0.27f; + public float cloudScale = 0.42f; + public Vector3 cloudDetailXYDensity = new Vector3(1.00f, 0.53f, 0.12f); + public float cloudScrollX = 0.20f; + public bool cloudScrollXLock = false; + public float cloudScrollY = 0.01f; + public bool cloudScrollYLock = false; + public bool drawClassicClouds = false; + + public delegate void SaveDelegate(RegionMeta7WindlightData wl); + public event SaveDelegate OnSave; + public void Save() + { + if (OnSave != null) + OnSave(this); + } + } + [Serializable] public class SimpleRegionInfo { @@ -304,8 +355,7 @@ namespace OpenSim.Framework private bool m_clampPrimSize = false; private int m_objectCapacity = 0; private string m_regionType = String.Empty; - - + private RegionMeta7WindlightData m_windlight = new RegionMeta7WindlightData(); // Apparently, we're applying the same estatesettings regardless of whether it's local or remote. // MT: Yes. Estates can't span trust boundaries. Therefore, it can be @@ -454,6 +504,21 @@ namespace OpenSim.Framework set { m_regionSettings = value; } } + public RegionMeta7WindlightData WindlightSettings + { + get + { + if (m_windlight == null) + { + m_windlight = new RegionMeta7WindlightData(); + } + + return m_windlight; + } + + set { m_windlight = value; } + } + public int NonphysPrimMax { get { return m_nonphysPrimMax; } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index b588a2e..6cbf1a6 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -764,16 +764,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, List message) { GenericMessagePacket gmp = new GenericMessagePacket(); gmp.MethodData.Method = Util.StringToBytes256(method); gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count]; int i = 0; - foreach (string val in message) + foreach (byte[] val in message) { gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock(); - gmp.ParamList[i++].Parameter = Util.StringToBytes256(val); + gmp.ParamList[i++].Parameter = val; } OutPacket(gmp, ThrottleOutPacketType.Task); } diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 9754da3..816060f 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -433,7 +433,7 @@ namespace OpenSim.Region.Examples.SimpleModule } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, List message) { } diff --git a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs index 78bd622..225cc9a 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs @@ -103,6 +103,7 @@ namespace OpenSim.Region.Framework.Interfaces void StoreRegionSettings(RegionSettings rs); RegionSettings LoadRegionSettings(UUID regionUUID); + RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID); void Shutdown(); } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f5a1e74..f70af27 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -539,6 +539,8 @@ namespace OpenSim.Region.Framework.Scenes // Load region settings m_regInfo.RegionSettings = m_storageManager.DataStore.LoadRegionSettings(m_regInfo.RegionID); + m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(m_regInfo.RegionID); + if (m_storageManager.EstateDataStore != null) { m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index 8a27b7b..e8cda60 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -101,7 +101,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests { throw new NotImplementedException(); } - + public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionMeta7WindlightData(); + } public RegionSettings LoadRegionSettings(UUID regionUUID) { return null; diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 6c3e7eb..bdf1574 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -936,7 +936,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server // TODO } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, List message) { } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index cf36d08..975033a 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -522,7 +522,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, List message) { } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 27025d9..5f172c4 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -491,7 +491,7 @@ namespace OpenSim.Tests.Common.Mock } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, List message) { } -- cgit v1.1 From ee9d46c8255840473ed62c3b37270b35af1a9027 Mon Sep 17 00:00:00 2001 From: KittoFlora Date: Tue, 8 Dec 2009 05:49:05 +0100 Subject: Correct AbsolutePosition calculation --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a6382ee..a23c11e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -849,7 +849,8 @@ namespace OpenSim.Region.Framework.Scenes if (IsAttachment) return GroupPosition; - return m_offsetPosition + m_groupPosition; } +// return m_offsetPosition + m_groupPosition; } + return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored! } public SceneObjectGroup ParentGroup -- cgit v1.1 From e3f229225c5a1506090bfcffcce6d423a566f1fe Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 9 Dec 2009 01:34:26 +0100 Subject: Enable scripting interface for windlight --- OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs | 4 + OpenSim/Data/Null/NullDataStore.cs | 4 + OpenSim/Data/SQLite/SQLiteRegionData.cs | 4 + .../Framework/Interfaces/IRegionDataStore.cs | 1 + OpenSim/Region/Framework/Scenes/EventManager.cs | 12 + OpenSim/Region/Framework/Scenes/Scene.cs | 7 + .../Region/Framework/Scenes/Tests/SceneTests.cs | 4 + .../Shared/Api/Implementation/OSSL_Api.cs | 333 +++++++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 7 +- .../Shared/Api/Runtime/LSL_Constants.cs | 38 +++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 10 + 11 files changed, 423 insertions(+), 1 deletion(-) diff --git a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs index 678b251..0b430c7 100644 --- a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs @@ -677,6 +677,10 @@ VALUES //Return default LL windlight settings return new RegionMeta7WindlightData(); } + public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + { + //This connector doesn't support the windlight module yet + } /// /// Loads the settings of a region. /// diff --git a/OpenSim/Data/Null/NullDataStore.cs b/OpenSim/Data/Null/NullDataStore.cs index 39ca8f9..4b6d0f3 100644 --- a/OpenSim/Data/Null/NullDataStore.cs +++ b/OpenSim/Data/Null/NullDataStore.cs @@ -56,6 +56,10 @@ namespace OpenSim.Data.Null //Return default LL windlight settings return new RegionMeta7WindlightData(); } + public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + { + //This connector doesn't support the windlight module yet + } public RegionSettings LoadRegionSettings(UUID regionUUID) { return null; diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs index 53b806c..f1c1f78 100644 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLite/SQLiteRegionData.cs @@ -278,6 +278,10 @@ namespace OpenSim.Data.SQLite //Return default LL windlight settings return new RegionMeta7WindlightData(); } + public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + { + //This connector doesn't support the windlight module yet + } public RegionSettings LoadRegionSettings(UUID regionUUID) { lock (ds) diff --git a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs index 225cc9a..7312799 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs @@ -104,6 +104,7 @@ namespace OpenSim.Region.Framework.Interfaces void StoreRegionSettings(RegionSettings rs); RegionSettings LoadRegionSettings(UUID regionUUID); RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID); + void StoreRegionWindlightSettings(RegionMeta7WindlightData wl); void Shutdown(); } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 753344d..a86e263 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -193,7 +193,9 @@ namespace OpenSim.Region.Framework.Scenes public event OnMakeChildAgentDelegate OnMakeChildAgent; public delegate void OnMakeRootAgentDelegate(ScenePresence presence); + public delegate void OnSaveNewWindlightProfileDelegate(); public event OnMakeRootAgentDelegate OnMakeRootAgent; + public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile; public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); @@ -411,6 +413,7 @@ namespace OpenSim.Region.Framework.Scenes private IncomingInstantMessage handlerUnhandledInstantMessage = null; //OnUnhandledInstantMessage; private ClientClosed handlerClientClosed = null; //OnClientClosed; private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent; + private OnSaveNewWindlightProfileDelegate handlerSaveNewWindlightProfile = null; //OnSaveNewWindlightProfile; private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent; private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick; private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; @@ -772,6 +775,15 @@ namespace OpenSim.Region.Framework.Scenes } } + public void TriggerOnSaveNewWindlightProfile() + { + handlerSaveNewWindlightProfile = OnSaveNewWindlightProfile; + if (handlerSaveNewWindlightProfile != null) + { + handlerSaveNewWindlightProfile(); + } + } + public void TriggerOnMakeRootAgent(ScenePresence presence) { handlerMakeRootAgent = OnMakeRootAgent; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8d91d65..475d775 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1505,6 +1505,13 @@ namespace OpenSim.Region.Framework.Scenes m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); } + public void StoreWindlightProfile(RegionMeta7WindlightData wl) + { + m_regInfo.WindlightSettings = wl; + m_storageManager.DataStore.StoreRegionWindlightSettings(wl); + m_eventManager.TriggerOnSaveNewWindlightProfile(); + } + /// /// Loads the World heightmap /// diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index e8cda60..5abbb82 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -107,6 +107,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests //Return default LL windlight settings return new RegionMeta7WindlightData(); } + public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + { + //This connector doesn't support the windlight module yet + } public RegionSettings LoadRegionSettings(UUID regionUUID) { return null; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 7f739b1..33c67d5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -42,6 +42,7 @@ using OpenSim.Region.CoreModules.Avatar.NPC; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Hypergrid; +using OpenSim.Region.CoreModules.World.Meta7Windlight; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; using OpenSim.Region.ScriptEngine.Shared.ScriptBase; @@ -1974,5 +1975,337 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return ret; } + /// + /// Get the current Windlight scene + /// + /// List of windlight parameters + public LSL_List osGetWindlightScene(LSL_List rules) + { + CheckThreatLevel(ThreatLevel.Low, "osGetWindlightScene"); + m_host.AddScriptLPS(1); + RegionMeta7WindlightData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; + + LSL_List values = new LSL_List(); + int idx = 0; + while (idx < rules.Length) + { + uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_List toadd = new LSL_List(); + + switch (rule) + { + case (int)ScriptBaseClass.WL_AMBIENT: + toadd.Add(new LSL_Rotation(wl.ambient.X, wl.ambient.Y, wl.ambient.Z, wl.ambient.W)); + break; + case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: + toadd.Add(new LSL_Vector(wl.bigWaveDirection.X, wl.bigWaveDirection.Y, 0.0f)); + break; + case (int)ScriptBaseClass.WL_BLUE_DENSITY: + toadd.Add(new LSL_Rotation(wl.blueDensity.X, wl.blueDensity.Y, wl.blueDensity.Z, wl.blueDensity.W)); + break; + case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: + toadd.Add(new LSL_Float(wl.blurMultiplier)); + break; + case (int)ScriptBaseClass.WL_CLOUD_COLOR: + toadd.Add(new LSL_Rotation(wl.cloudColor.X, wl.cloudColor.Y, wl.cloudColor.Z, wl.cloudColor.W)); + break; + case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: + toadd.Add(new LSL_Float(wl.cloudCoverage)); + break; + case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: + toadd.Add(new LSL_Vector(wl.cloudDetailXYDensity.X, wl.cloudDetailXYDensity.Y, wl.cloudDetailXYDensity.Z)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCALE: + toadd.Add(new LSL_Float(wl.cloudScale)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: + toadd.Add(new LSL_Float(wl.cloudScrollX)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: + toadd.Add(new LSL_Integer(wl.cloudScrollXLock ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: + toadd.Add(new LSL_Float(wl.cloudScrollY)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: + toadd.Add(new LSL_Integer(wl.cloudScrollYLock ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: + toadd.Add(new LSL_Vector(wl.cloudXYDensity.X, wl.cloudXYDensity.Y, wl.cloudXYDensity.Z)); + break; + case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: + toadd.Add(new LSL_Float(wl.densityMultiplier)); + break; + case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: + toadd.Add(new LSL_Float(wl.distanceMultiplier)); + break; + case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: + toadd.Add(new LSL_Integer(wl.drawClassicClouds ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_EAST_ANGLE: + toadd.Add(new LSL_Float(wl.eastAngle)); + break; + case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: + toadd.Add(new LSL_Float(wl.fresnelOffset)); + break; + case (int)ScriptBaseClass.WL_FRESNEL_SCALE: + toadd.Add(new LSL_Float(wl.fresnelScale)); + break; + case (int)ScriptBaseClass.WL_HAZE_DENSITY: + toadd.Add(new LSL_Float(wl.hazeDensity)); + break; + case (int)ScriptBaseClass.WL_HAZE_HORIZON: + toadd.Add(new LSL_Float(wl.hazeHorizon)); + break; + case (int)ScriptBaseClass.WL_HORIZON: + toadd.Add(new LSL_Rotation(wl.horizon.X, wl.horizon.Y, wl.horizon.Z, wl.horizon.W)); + break; + case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: + toadd.Add(new LSL_Vector(wl.littleWaveDirection.X, wl.littleWaveDirection.Y, 0.0f)); + break; + case (int)ScriptBaseClass.WL_MAX_ALTITUDE: + toadd.Add(new LSL_Integer(wl.maxAltitude)); + break; + case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: + toadd.Add(new LSL_Key(wl.normalMapTexture.ToString())); + break; + case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: + toadd.Add(new LSL_Vector(wl.reflectionWaveletScale.X, wl.reflectionWaveletScale.Y, wl.reflectionWaveletScale.Z)); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: + toadd.Add(new LSL_Float(wl.refractScaleAbove)); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: + toadd.Add(new LSL_Float(wl.refractScaleBelow)); + break; + case (int)ScriptBaseClass.WL_SCENE_GAMMA: + toadd.Add(new LSL_Float(wl.sceneGamma)); + break; + case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: + toadd.Add(new LSL_Float(wl.starBrightness)); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: + toadd.Add(new LSL_Float(wl.sunGlowFocus)); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: + toadd.Add(new LSL_Float(wl.sunGlowSize)); + break; + case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: + toadd.Add(new LSL_Rotation(wl.sunMoonColor.X, wl.sunMoonColor.Y, wl.sunMoonColor.Z, wl.sunMoonColor.W)); + break; + case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: + toadd.Add(new LSL_Float(wl.underwaterFogModifier)); + break; + case (int)ScriptBaseClass.WL_WATER_COLOR: + toadd.Add(new LSL_Vector(wl.waterColor.X, wl.waterColor.Y, wl.waterColor.Z)); + break; + case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: + toadd.Add(new LSL_Float(wl.waterFogDensityExponent)); + break; + } + + if (toadd.Length > 0) + { + values.Add(rule); + values.Add(toadd.Data[0]); + } + idx++; + } + + + return values; + + } + + /// + /// Set the current Windlight scene + /// + /// + /// success: true or false + public int osSetWindlightScene(LSL_List rules) + { + CheckThreatLevel(ThreatLevel.High, "osSetWindlightScene"); + int success = 0; + m_host.AddScriptLPS(1); + if (Meta7WindlightModule.EnableWindlight) + { + RegionMeta7WindlightData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; + + LSL_List values = new LSL_List(); + int idx = 0; + success = 1; + while (idx < rules.Length) + { + uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_Types.Quaternion iQ; + LSL_Types.Vector3 iV; + switch (rule) + { + case (int)ScriptBaseClass.WL_AMBIENT: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_BLUE_DENSITY: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: + idx++; + wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: + idx++; + wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCALE: + idx++; + wl.cloudScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: + idx++; + wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: + idx++; + wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: + idx++; + wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: + idx++; + wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: + idx++; + wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: + idx++; + wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: + idx++; + wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_EAST_ANGLE: + idx++; + wl.eastAngle = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: + idx++; + wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_SCALE: + idx++; + wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_DENSITY: + idx++; + wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_HORIZON: + idx++; + wl.hazeHorizon= (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HORIZON: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_MAX_ALTITUDE: + idx++; + wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; + break; + case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: + idx++; + wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); + break; + case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: + idx++; + iV = rules.GetVector3Item(idx); + wl.reflectionWaveletScale= new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: + idx++; + wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: + idx++; + wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SCENE_GAMMA: + idx++; + wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: + idx++; + wl.starBrightness= (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: + idx++; + wl.sunGlowFocus= (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: + idx++; + wl.sunGlowSize= (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: + idx++; + wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_WATER_COLOR: + idx++; + iV = rules.GetVector3Item(idx); + wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: + idx++; + wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); + break; + default: + success = 0; + break; + } + idx++; + } + m_host.ParentGroup.Scene.StoreWindlightProfile(wl); + + } + return success; + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 0b0dc00..dd2869b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -80,7 +80,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces // Avatar Info Commands string osGetAgentIP(string agent); LSL_List osGetAgents(); - + // Teleport commands void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); @@ -163,5 +163,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces key osGetMapTexture(); key osGetRegionMapTexture(string regionName); LSL_List osGetRegionStats(); + + // Windlight Functions + LSL_List osGetWindlightScene(LSL_List rules); + int osSetWindlightScene(LSL_List rules); + } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index acff8fb..4956c28 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -539,5 +539,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int STATS_ACTIVE_SCRIPTS = 19; public const int STATS_SCRIPT_LPS = 20; + // Constants for osWindlight* + public const int WL_WATER_COLOR = 0; + public const int WL_WATER_FOG_DENSITY_EXPONENT = 1; + public const int WL_UNDERWATER_FOG_MODIFIER = 2; + public const int WL_REFLECTION_WAVELET_SCALE = 3; + public const int WL_FRESNEL_SCALE = 4; + public const int WL_FRESNEL_OFFSET = 5; + public const int WL_REFRACT_SCALE_ABOVE = 6; + public const int WL_REFRACT_SCALE_BELOW = 7; + public const int WL_BLUR_MULTIPLIER = 8; + public const int WL_BIG_WAVE_DIRECTION = 9; + public const int WL_LITTLE_WAVE_DIRECTION = 10; + public const int WL_NORMAL_MAP_TEXTURE = 11; + public const int WL_HORIZON = 12; + public const int WL_HAZE_HORIZON = 13; + public const int WL_BLUE_DENSITY = 14; + public const int WL_HAZE_DENSITY = 15; + public const int WL_DENSITY_MULTIPLIER = 16; + public const int WL_DISTANCE_MULTIPLIER = 17; + public const int WL_MAX_ALTITUDE = 18; + public const int WL_SUN_MOON_COLOR = 19; + public const int WL_AMBIENT = 20; + public const int WL_EAST_ANGLE = 21; + public const int WL_SUN_GLOW_FOCUS = 22; + public const int WL_SUN_GLOW_SIZE = 23; + public const int WL_SCENE_GAMMA = 24; + public const int WL_STAR_BRIGHTNESS = 25; + public const int WL_CLOUD_COLOR = 26; + public const int WL_CLOUD_XY_DENSITY = 27; + public const int WL_CLOUD_COVERAGE = 28; + public const int WL_CLOUD_SCALE = 29; + public const int WL_CLOUD_DETAIL_XY_DENSITY = 30; + public const int WL_CLOUD_SCROLL_X = 31; + public const int WL_CLOUD_SCROLL_Y = 32; + public const int WL_CLOUD_SCROLL_Y_LOCK = 33; + public const int WL_CLOUD_SCROLL_X_LOCK = 34; + public const int WL_DRAW_CLASSIC_CLOUDS = 35; + } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 519463e..1480b8b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -637,5 +637,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osGetRegionStats(); } + + public LSL_List osGetWindlightScene(LSL_List rules) + { + return m_OSSL_Functions.osGetWindlightScene(rules); + } + + public int osSetWindlightScene(LSL_List rules) + { + return m_OSSL_Functions.osSetWindlightScene(rules); + } } } -- cgit v1.1 From d092977f4a933baa990cb239d91c1bec860698e9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 9 Dec 2009 01:53:41 +0100 Subject: Windlight configuration option in ini, and migration --- OpenSim/Data/MySQL/Resources/032_RegionStore.sql | 70 ++++++++++++++++++++++++ bin/OpenSim.ini.example | 6 ++ 2 files changed, 76 insertions(+) create mode 100644 OpenSim/Data/MySQL/Resources/032_RegionStore.sql diff --git a/OpenSim/Data/MySQL/Resources/032_RegionStore.sql b/OpenSim/Data/MySQL/Resources/032_RegionStore.sql new file mode 100644 index 0000000..0545ee1 --- /dev/null +++ b/OpenSim/Data/MySQL/Resources/032_RegionStore.sql @@ -0,0 +1,70 @@ +BEGIN; + +CREATE TABLE `regionwindlight` ( + `region_id` varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000', + `water_color_r` float(9,6) unsigned NOT NULL DEFAULT '4.000000', + `water_color_g` float(9,6) unsigned NOT NULL DEFAULT '38.000000', + `water_color_b` float(9,6) unsigned NOT NULL DEFAULT '64.000000', + `water_fog_density_exponent` float(3,1) unsigned NOT NULL DEFAULT '4.0', + `underwater_fog_modifier` float(3,2) unsigned NOT NULL DEFAULT '0.25', + `reflection_wavelet_scale_1` float(3,1) unsigned NOT NULL DEFAULT '2.0', + `reflection_wavelet_scale_2` float(3,1) unsigned NOT NULL DEFAULT '2.0', + `reflection_wavelet_scale_3` float(3,1) unsigned NOT NULL DEFAULT '2.0', + `fresnel_scale` float(3,2) unsigned NOT NULL DEFAULT '0.40', + `fresnel_offset` float(3,2) unsigned NOT NULL DEFAULT '0.50', + `refract_scale_above` float(3,2) unsigned NOT NULL DEFAULT '0.03', + `refract_scale_below` float(3,2) unsigned NOT NULL DEFAULT '0.20', + `blur_multiplier` float(4,3) unsigned NOT NULL DEFAULT '0.040', + `big_wave_direction_x` float(3,2) NOT NULL DEFAULT '1.05', + `big_wave_direction_y` float(3,2) NOT NULL DEFAULT '-0.42', + `little_wave_direction_x` float(3,2) NOT NULL DEFAULT '1.11', + `little_wave_direction_y` float(3,2) NOT NULL DEFAULT '-1.16', + `normal_map_texture` varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4', + `horizon_r` float(3,2) unsigned NOT NULL DEFAULT '0.26', + `horizon_g` float(3,2) unsigned NOT NULL DEFAULT '0.24', + `horizon_b` float(3,2) unsigned NOT NULL DEFAULT '0.33', + `horizon_i` float(3,2) unsigned NOT NULL DEFAULT '0.33', + `haze_horizon` float(3,2) unsigned NOT NULL DEFAULT '0.19', + `blue_density_r` float(3,2) unsigned NOT NULL DEFAULT '0.10', + `blue_density_g` float(3,2) unsigned NOT NULL DEFAULT '0.93', + `blue_density_b` float(3,2) unsigned NOT NULL DEFAULT '0.02', + `blue_density_i` float(3,2) unsigned NOT NULL DEFAULT '0.93', + `haze_density` float(3,2) unsigned NOT NULL DEFAULT '0.70', + `density_multiplier` float(3,2) unsigned NOT NULL DEFAULT '0.18', + `distance_multiplier` float(4,1) unsigned NOT NULL DEFAULT '0.8', + `max_altitude` int(4) unsigned NOT NULL DEFAULT '1605', + `sun_moon_color_r` float(3,2) unsigned NOT NULL DEFAULT '0.24', + `sun_moon_color_g` float(3,2) unsigned NOT NULL DEFAULT '0.26', + `sun_moon_color_b` float(3,2) unsigned NOT NULL DEFAULT '0.30', + `sun_moon_color_i` float(3,2) unsigned NOT NULL DEFAULT '0.30', + `sun_moon_position` float(4,3) unsigned NOT NULL DEFAULT '0.335', + `ambient_r` float(3,2) unsigned NOT NULL DEFAULT '0.35', + `ambient_g` float(3,2) unsigned NOT NULL DEFAULT '0.35', + `ambient_b` float(3,2) unsigned NOT NULL DEFAULT '0.35', + `ambient_i` float(3,2) unsigned NOT NULL DEFAULT '0.35', + `east_angle` float(3,2) unsigned NOT NULL DEFAULT '0.00', + `sun_glow_focus` float(3,2) unsigned NOT NULL DEFAULT '0.10', + `sun_glow_size` float(3,2) unsigned NOT NULL DEFAULT '1.75', + `scene_gamma` float(4,2) unsigned NOT NULL DEFAULT '1.00', + `star_brightness` float(3,2) unsigned NOT NULL DEFAULT '0.00', + `cloud_color_r` float(3,2) unsigned NOT NULL DEFAULT '0.41', + `cloud_color_g` float(3,2) unsigned NOT NULL DEFAULT '0.41', + `cloud_color_b` float(3,2) unsigned NOT NULL DEFAULT '0.41', + `cloud_color_i` float(3,2) unsigned NOT NULL DEFAULT '0.41', + `cloud_x` float(3,2) unsigned NOT NULL DEFAULT '1.00', + `cloud_y` float(3,2) unsigned NOT NULL DEFAULT '0.53', + `cloud_density` float(3,2) unsigned NOT NULL DEFAULT '1.00', + `cloud_coverage` float(3,2) unsigned NOT NULL DEFAULT '0.27', + `cloud_scale` float(3,2) unsigned NOT NULL DEFAULT '0.42', + `cloud_detail_x` float(3,2) unsigned NOT NULL DEFAULT '1.00', + `cloud_detail_y` float(3,2) unsigned NOT NULL DEFAULT '0.53', + `cloud_detail_density` float(3,2) unsigned NOT NULL DEFAULT '0.12', + `cloud_scroll_x` float(3,2) unsigned NOT NULL DEFAULT '0.20', + `cloud_scroll_x_lock` tinyint(1) unsigned NOT NULL DEFAULT '0', + `cloud_scroll_y` float(3,2) unsigned NOT NULL DEFAULT '0.01', + `cloud_scroll_y_lock` tinyint(1) unsigned NOT NULL DEFAULT '0', + `draw_classic_clouds` tinyint(1) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`region_id`) +); + +COMMIT; \ No newline at end of file diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 62aceb1..b7f7c3c 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -825,6 +825,12 @@ ; default is 1000 cloud_update_rate = 1000 +[Meta7Windlight] + + ; This enables the transmission of Windlight scenes to supporting clients, such as the Meta7 viewer. + ; It has no ill effect on viewers which do not support server-side windlight settings. + ; Currently we only have support for MySQL databases. + enable_windlight = false; [Trees] ; Enable this to allow the tree module to manage your sim trees, including growing, reproducing and dying -- cgit v1.1 From 2a6dbd068ef48c7605f44153dcfea6b215749bed Mon Sep 17 00:00:00 2001 From: CasperW Date: Wed, 9 Dec 2009 03:58:56 +0100 Subject: Last bits and bobs to clean up the Meta7WindlightModule --- .../World/Meta7Windlight/Meta7WindlightModule.cs | 245 +++++++++++++++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 8 +- 2 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs diff --git a/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs b/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs new file mode 100644 index 0000000..f180b47 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs @@ -0,0 +1,245 @@ +/* + * Copyright (c) Thomas Grimshaw and Magne Metaverse Research + * + * This module is not open source. All rights reserved. + * Unauthorised copying, distribution or public display is prohibited. + * + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using OpenMetaverse; +using log4net; +using Nini.Config; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.Framework.InterfaceCommander; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + + +namespace OpenSim.Region.CoreModules.World.Meta7Windlight +{ + public class Meta7WindlightModule : IRegionModule, ICommandableModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private readonly Commander m_commander = new Commander("windlight"); + private Scene m_scene; + private static bool m_enableWindlight; + + #region ICommandableModule Members + + public ICommander CommandInterface + { + get { return m_commander; } + } + + #endregion + + #region IRegionModule Members + + public static bool EnableWindlight + { + get + { + return m_enableWindlight; + } + set + { + } + } + + public void Initialise(Scene scene, IConfigSource config) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; + + // ini file settings + try + { + m_enableWindlight = config.Configs["Meta7Windlight"].GetBoolean("enable_windlight", false); + } + catch (Exception) + { + m_log.Debug("[WINDLIGHT]: ini failure for enable_windlight - using default"); + } + + if (m_enableWindlight) + { + m_scene.EventManager.OnMakeRootAgent += EventManager_OnMakeRootAgent; + m_scene.EventManager.OnSaveNewWindlightProfile += EventManager_OnSaveNewWindlightProfile; + } + + InstallCommands(); + + m_log.Debug("[WINDLIGHT]: Initialised windlight module"); + } + public void SendProfileToClient(ScenePresence presence) + { + if (m_enableWindlight) + { + if (presence.IsChildAgent == false) + { + IClientAPI client = presence.ControllingClient; + RegionMeta7WindlightData wl = m_scene.RegionInfo.WindlightSettings; + byte[] mBlock = new Byte[249]; + int pos = 0; + + wl.waterColor.ToBytes(mBlock, 0); pos += 12; + Utils.FloatToBytes(wl.waterFogDensityExponent).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.underwaterFogModifier).CopyTo(mBlock, pos); pos += 4; + wl.reflectionWaveletScale.ToBytes(mBlock, pos); pos += 12; + Utils.FloatToBytes(wl.fresnelScale).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.fresnelOffset).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.refractScaleAbove).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.refractScaleBelow).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.blurMultiplier).CopyTo(mBlock, pos); pos += 4; + wl.bigWaveDirection.ToBytes(mBlock, pos); pos += 8; + wl.littleWaveDirection.ToBytes(mBlock, pos); pos += 8; + wl.normalMapTexture.ToBytes(mBlock, pos); pos += 16; + wl.horizon.ToBytes(mBlock, pos); pos += 16; + Utils.FloatToBytes(wl.hazeHorizon).CopyTo(mBlock, pos); pos += 4; + wl.blueDensity.ToBytes(mBlock, pos); pos += 16; + Utils.FloatToBytes(wl.hazeDensity).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.densityMultiplier).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.distanceMultiplier).CopyTo(mBlock, pos); pos += 4; + wl.sunMoonColor.ToBytes(mBlock, pos); pos += 16; + Utils.FloatToBytes(wl.sunMoonPosition).CopyTo(mBlock, pos); pos += 4; + wl.ambient.ToBytes(mBlock, pos); pos += 16; + Utils.FloatToBytes(wl.eastAngle).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.sunGlowFocus).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.sunGlowSize).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.sceneGamma).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.starBrightness).CopyTo(mBlock, pos); pos += 4; + wl.cloudColor.ToBytes(mBlock, pos); pos += 16; + wl.cloudXYDensity.ToBytes(mBlock, pos); pos += 12; + Utils.FloatToBytes(wl.cloudCoverage).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.cloudScale).CopyTo(mBlock, pos); pos += 4; + wl.cloudDetailXYDensity.ToBytes(mBlock, pos); pos += 12; + Utils.FloatToBytes(wl.cloudScrollX).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.cloudScrollY).CopyTo(mBlock, pos); pos += 4; + Utils.UInt16ToBytes(wl.maxAltitude).CopyTo(mBlock, pos); pos += 2; + mBlock[pos] = Convert.ToByte(wl.cloudScrollXLock); pos++; + mBlock[pos] = Convert.ToByte(wl.cloudScrollYLock); pos++; + mBlock[pos] = Convert.ToByte(wl.drawClassicClouds); pos++; + List param = new List(); + param.Add(mBlock); + + client.SendGenericMessage("Windlight", param); + } + } + else + { + //We probably don't want to spam chat with this.. probably + //m_log.Debug("[WINDLIGHT]: Module disabled"); + } + } + private void EventManager_OnMakeRootAgent(ScenePresence presence) + { + m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client"); + SendProfileToClient(presence); + } + + private void EventManager_OnSaveNewWindlightProfile() + { + m_scene.ForEachScenePresence(SendProfileToClient); + } + + public void PostInitialise() + { + + } + + public void Close() + { + } + + public string Name + { + get { return "Meta7WindlightModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + #endregion + + #region events + + #endregion + + #region ICommandableModule Members + + private void InstallCommands() + { + Command wlload = new Command("load", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleLoad, "Load windlight profile from the database and broadcast"); + Command wlenable = new Command("enable", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleEnable, "Enable the windlight plugin"); + Command wldisable = new Command("disable", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleDisable, "Enable the windlight plugin"); + + m_commander.RegisterCommand("load", wlload); + m_commander.RegisterCommand("enable", wlenable); + m_commander.RegisterCommand("disable", wldisable); + + m_scene.RegisterModuleCommander(m_commander); + } + + private void HandleLoad(Object[] args) + { + if (!m_enableWindlight) + { + m_log.InfoFormat("[WINDLIGHT]: Cannot load windlight profile, module disabled. Use 'windlight enable' first."); + } + else + { + m_log.InfoFormat("[WINDLIGHT]: Loading Windlight profile from database"); + m_scene.LoadWindlightProfile(); + m_log.InfoFormat("[WINDLIGHT]: Load complete"); + } + } + + private void HandleDisable(Object[] args) + { + m_log.InfoFormat("[WINDLIGHT]: Plugin now disabled"); + m_enableWindlight=false; + } + + private void HandleEnable(Object[] args) + { + m_log.InfoFormat("[WINDLIGHT]: Plugin now enabled"); + m_enableWindlight = true; + } + + /// + /// Processes commandline input. Do not call directly. + /// + /// Commandline arguments + private void EventManager_OnPluginConsole(string[] args) + { + if (args[0] == "windlight") + { + if (args.Length == 1) + { + m_commander.ProcessConsoleCommand("add", new string[0]); + return; + } + + string[] tmpArgs = new string[args.Length - 2]; + int i; + for (i = 2; i < args.Length; i++) + { + tmpArgs[i - 2] = args[i]; + } + + m_commander.ProcessConsoleCommand(args[1], tmpArgs); + } + } + #endregion + + } +} + diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 475d775..1b275b0 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1504,7 +1504,7 @@ namespace OpenSim.Region.Framework.Scenes { m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); } - + public void StoreWindlightProfile(RegionMeta7WindlightData wl) { m_regInfo.WindlightSettings = wl; @@ -1512,6 +1512,12 @@ namespace OpenSim.Region.Framework.Scenes m_eventManager.TriggerOnSaveNewWindlightProfile(); } + public void LoadWindlightProfile() + { + m_regInfo.WindlightSettings = m_storageManager.DataStore.LoadRegionWindlightSettings(RegionInfo.RegionID); + m_eventManager.TriggerOnSaveNewWindlightProfile(); + } + /// /// Loads the World heightmap /// -- cgit v1.1 From a6a6bf007a2fb0e33daefc0ea7c4ad968a85d08e Mon Sep 17 00:00:00 2001 From: CasperW Date: Wed, 9 Dec 2009 22:57:35 +0100 Subject: Move osFunctions into a new Careminster script interface --- .../Shared/Api/Implementation/CM_Api.cs | 430 +++++++++++++++++++++ .../Shared/Api/Implementation/OSSL_Api.cs | 334 ---------------- .../ScriptEngine/Shared/Api/Interface/ICM_Api.cs | 20 + .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 5 - .../Shared/Api/Runtime/CM_Constants.cs | 76 ++++ .../ScriptEngine/Shared/Api/Runtime/CM_Stub.cs | 71 ++++ .../Shared/Api/Runtime/LSL_Constants.cs | 38 -- .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 10 - bin/OpenSim.ini.example | 3 + 9 files changed, 600 insertions(+), 387 deletions(-) create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Constants.cs create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs new file mode 100644 index 0000000..4cc2f0a --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -0,0 +1,430 @@ +using System; +using System.Reflection; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using OpenMetaverse; +using Nini.Config; +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.World.Meta7Windlight; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.ScriptEngine.Shared; +using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; +using OpenSim.Region.ScriptEngine.Shared.ScriptBase; +using OpenSim.Region.ScriptEngine.Interfaces; +using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; + +using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; +using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; +using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; +using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; +using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; + +namespace OpenSim.Region.ScriptEngine.Shared.Api +{ + [Serializable] + public class CM_Api : MarshalByRefObject, ICM_Api, IScriptApi + { + internal IScriptEngine m_ScriptEngine; + internal SceneObjectPart m_host; + internal uint m_localID; + internal UUID m_itemID; + internal bool m_CMFunctionsEnabled = false; + internal IScriptModuleComms m_comms = null; + + public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) + { + m_ScriptEngine = ScriptEngine; + m_host = host; + m_localID = localID; + m_itemID = itemID; + + if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false)) + m_CMFunctionsEnabled = true; + + m_comms = m_ScriptEngine.World.RequestModuleInterface(); + if (m_comms == null) + m_CMFunctionsEnabled = false; + } + + public override Object InitializeLifetimeService() + { + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.FromMinutes(0); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); + } + return lease; + } + + public Scene World + { + get { return m_ScriptEngine.World; } + } + + // + //Dumps an error message on the debug console. + // + + internal void CMShoutError(string message) + { + if (message.Length > 1023) + message = message.Substring(0, 1023); + + World.SimChat(Utils.StringToBytes(message), + ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); + } + + /// + /// Get the current Windlight scene + /// + /// List of windlight parameters + public LSL_List cmGetWindlightScene(LSL_List rules) + { + if (!m_CMFunctionsEnabled) + { + CMShoutError("Careminster functions are not enabled."); + return new LSL_List(); + } + m_host.AddScriptLPS(1); + RegionMeta7WindlightData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; + + LSL_List values = new LSL_List(); + int idx = 0; + while (idx < rules.Length) + { + uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_List toadd = new LSL_List(); + + switch (rule) + { + case (int)ScriptBaseClass.WL_AMBIENT: + toadd.Add(new LSL_Rotation(wl.ambient.X, wl.ambient.Y, wl.ambient.Z, wl.ambient.W)); + break; + case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: + toadd.Add(new LSL_Vector(wl.bigWaveDirection.X, wl.bigWaveDirection.Y, 0.0f)); + break; + case (int)ScriptBaseClass.WL_BLUE_DENSITY: + toadd.Add(new LSL_Rotation(wl.blueDensity.X, wl.blueDensity.Y, wl.blueDensity.Z, wl.blueDensity.W)); + break; + case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: + toadd.Add(new LSL_Float(wl.blurMultiplier)); + break; + case (int)ScriptBaseClass.WL_CLOUD_COLOR: + toadd.Add(new LSL_Rotation(wl.cloudColor.X, wl.cloudColor.Y, wl.cloudColor.Z, wl.cloudColor.W)); + break; + case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: + toadd.Add(new LSL_Float(wl.cloudCoverage)); + break; + case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: + toadd.Add(new LSL_Vector(wl.cloudDetailXYDensity.X, wl.cloudDetailXYDensity.Y, wl.cloudDetailXYDensity.Z)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCALE: + toadd.Add(new LSL_Float(wl.cloudScale)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: + toadd.Add(new LSL_Float(wl.cloudScrollX)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: + toadd.Add(new LSL_Integer(wl.cloudScrollXLock ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: + toadd.Add(new LSL_Float(wl.cloudScrollY)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: + toadd.Add(new LSL_Integer(wl.cloudScrollYLock ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: + toadd.Add(new LSL_Vector(wl.cloudXYDensity.X, wl.cloudXYDensity.Y, wl.cloudXYDensity.Z)); + break; + case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: + toadd.Add(new LSL_Float(wl.densityMultiplier)); + break; + case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: + toadd.Add(new LSL_Float(wl.distanceMultiplier)); + break; + case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: + toadd.Add(new LSL_Integer(wl.drawClassicClouds ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_EAST_ANGLE: + toadd.Add(new LSL_Float(wl.eastAngle)); + break; + case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: + toadd.Add(new LSL_Float(wl.fresnelOffset)); + break; + case (int)ScriptBaseClass.WL_FRESNEL_SCALE: + toadd.Add(new LSL_Float(wl.fresnelScale)); + break; + case (int)ScriptBaseClass.WL_HAZE_DENSITY: + toadd.Add(new LSL_Float(wl.hazeDensity)); + break; + case (int)ScriptBaseClass.WL_HAZE_HORIZON: + toadd.Add(new LSL_Float(wl.hazeHorizon)); + break; + case (int)ScriptBaseClass.WL_HORIZON: + toadd.Add(new LSL_Rotation(wl.horizon.X, wl.horizon.Y, wl.horizon.Z, wl.horizon.W)); + break; + case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: + toadd.Add(new LSL_Vector(wl.littleWaveDirection.X, wl.littleWaveDirection.Y, 0.0f)); + break; + case (int)ScriptBaseClass.WL_MAX_ALTITUDE: + toadd.Add(new LSL_Integer(wl.maxAltitude)); + break; + case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: + toadd.Add(new LSL_Key(wl.normalMapTexture.ToString())); + break; + case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: + toadd.Add(new LSL_Vector(wl.reflectionWaveletScale.X, wl.reflectionWaveletScale.Y, wl.reflectionWaveletScale.Z)); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: + toadd.Add(new LSL_Float(wl.refractScaleAbove)); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: + toadd.Add(new LSL_Float(wl.refractScaleBelow)); + break; + case (int)ScriptBaseClass.WL_SCENE_GAMMA: + toadd.Add(new LSL_Float(wl.sceneGamma)); + break; + case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: + toadd.Add(new LSL_Float(wl.starBrightness)); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: + toadd.Add(new LSL_Float(wl.sunGlowFocus)); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: + toadd.Add(new LSL_Float(wl.sunGlowSize)); + break; + case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: + toadd.Add(new LSL_Rotation(wl.sunMoonColor.X, wl.sunMoonColor.Y, wl.sunMoonColor.Z, wl.sunMoonColor.W)); + break; + case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: + toadd.Add(new LSL_Float(wl.underwaterFogModifier)); + break; + case (int)ScriptBaseClass.WL_WATER_COLOR: + toadd.Add(new LSL_Vector(wl.waterColor.X, wl.waterColor.Y, wl.waterColor.Z)); + break; + case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: + toadd.Add(new LSL_Float(wl.waterFogDensityExponent)); + break; + } + + if (toadd.Length > 0) + { + values.Add(rule); + values.Add(toadd.Data[0]); + } + idx++; + } + + + return values; + + } + + /// + /// Set the current Windlight scene + /// + /// + /// success: true or false + public int cmSetWindlightScene(LSL_List rules) + { + if (!m_CMFunctionsEnabled) + { + CMShoutError("Careminster functions are not enabled."); + return 0; + } + int success = 0; + m_host.AddScriptLPS(1); + if (Meta7WindlightModule.EnableWindlight) + { + RegionMeta7WindlightData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; + + LSL_List values = new LSL_List(); + int idx = 0; + success = 1; + while (idx < rules.Length) + { + uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_Types.Quaternion iQ; + LSL_Types.Vector3 iV; + switch (rule) + { + case (int)ScriptBaseClass.WL_AMBIENT: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_BLUE_DENSITY: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: + idx++; + wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: + idx++; + wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCALE: + idx++; + wl.cloudScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: + idx++; + wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: + idx++; + wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: + idx++; + wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: + idx++; + wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: + idx++; + wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: + idx++; + wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: + idx++; + wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_EAST_ANGLE: + idx++; + wl.eastAngle = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: + idx++; + wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_SCALE: + idx++; + wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_DENSITY: + idx++; + wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_HORIZON: + idx++; + wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HORIZON: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_MAX_ALTITUDE: + idx++; + wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; + break; + case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: + idx++; + wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); + break; + case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: + idx++; + iV = rules.GetVector3Item(idx); + wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: + idx++; + wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: + idx++; + wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SCENE_GAMMA: + idx++; + wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: + idx++; + wl.starBrightness = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: + idx++; + wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: + idx++; + wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: + idx++; + wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_WATER_COLOR: + idx++; + iV = rules.GetVector3Item(idx); + wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: + idx++; + wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); + break; + default: + success = 0; + break; + } + idx++; + } + m_host.ParentGroup.Scene.StoreWindlightProfile(wl); + + } + return success; + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 33c67d5..836f276 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -42,7 +42,6 @@ using OpenSim.Region.CoreModules.Avatar.NPC; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Hypergrid; -using OpenSim.Region.CoreModules.World.Meta7Windlight; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; using OpenSim.Region.ScriptEngine.Shared.ScriptBase; @@ -1974,338 +1973,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } return ret; } - - /// - /// Get the current Windlight scene - /// - /// List of windlight parameters - public LSL_List osGetWindlightScene(LSL_List rules) - { - CheckThreatLevel(ThreatLevel.Low, "osGetWindlightScene"); - m_host.AddScriptLPS(1); - RegionMeta7WindlightData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; - - LSL_List values = new LSL_List(); - int idx = 0; - while (idx < rules.Length) - { - uint rule = (uint)rules.GetLSLIntegerItem(idx); - LSL_List toadd = new LSL_List(); - - switch (rule) - { - case (int)ScriptBaseClass.WL_AMBIENT: - toadd.Add(new LSL_Rotation(wl.ambient.X, wl.ambient.Y, wl.ambient.Z, wl.ambient.W)); - break; - case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: - toadd.Add(new LSL_Vector(wl.bigWaveDirection.X, wl.bigWaveDirection.Y, 0.0f)); - break; - case (int)ScriptBaseClass.WL_BLUE_DENSITY: - toadd.Add(new LSL_Rotation(wl.blueDensity.X, wl.blueDensity.Y, wl.blueDensity.Z, wl.blueDensity.W)); - break; - case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: - toadd.Add(new LSL_Float(wl.blurMultiplier)); - break; - case (int)ScriptBaseClass.WL_CLOUD_COLOR: - toadd.Add(new LSL_Rotation(wl.cloudColor.X, wl.cloudColor.Y, wl.cloudColor.Z, wl.cloudColor.W)); - break; - case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: - toadd.Add(new LSL_Float(wl.cloudCoverage)); - break; - case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: - toadd.Add(new LSL_Vector(wl.cloudDetailXYDensity.X, wl.cloudDetailXYDensity.Y, wl.cloudDetailXYDensity.Z)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCALE: - toadd.Add(new LSL_Float(wl.cloudScale)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: - toadd.Add(new LSL_Float(wl.cloudScrollX)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: - toadd.Add(new LSL_Integer(wl.cloudScrollXLock ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: - toadd.Add(new LSL_Float(wl.cloudScrollY)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: - toadd.Add(new LSL_Integer(wl.cloudScrollYLock ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: - toadd.Add(new LSL_Vector(wl.cloudXYDensity.X, wl.cloudXYDensity.Y, wl.cloudXYDensity.Z)); - break; - case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: - toadd.Add(new LSL_Float(wl.densityMultiplier)); - break; - case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: - toadd.Add(new LSL_Float(wl.distanceMultiplier)); - break; - case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: - toadd.Add(new LSL_Integer(wl.drawClassicClouds ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_EAST_ANGLE: - toadd.Add(new LSL_Float(wl.eastAngle)); - break; - case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: - toadd.Add(new LSL_Float(wl.fresnelOffset)); - break; - case (int)ScriptBaseClass.WL_FRESNEL_SCALE: - toadd.Add(new LSL_Float(wl.fresnelScale)); - break; - case (int)ScriptBaseClass.WL_HAZE_DENSITY: - toadd.Add(new LSL_Float(wl.hazeDensity)); - break; - case (int)ScriptBaseClass.WL_HAZE_HORIZON: - toadd.Add(new LSL_Float(wl.hazeHorizon)); - break; - case (int)ScriptBaseClass.WL_HORIZON: - toadd.Add(new LSL_Rotation(wl.horizon.X, wl.horizon.Y, wl.horizon.Z, wl.horizon.W)); - break; - case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: - toadd.Add(new LSL_Vector(wl.littleWaveDirection.X, wl.littleWaveDirection.Y, 0.0f)); - break; - case (int)ScriptBaseClass.WL_MAX_ALTITUDE: - toadd.Add(new LSL_Integer(wl.maxAltitude)); - break; - case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: - toadd.Add(new LSL_Key(wl.normalMapTexture.ToString())); - break; - case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: - toadd.Add(new LSL_Vector(wl.reflectionWaveletScale.X, wl.reflectionWaveletScale.Y, wl.reflectionWaveletScale.Z)); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: - toadd.Add(new LSL_Float(wl.refractScaleAbove)); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: - toadd.Add(new LSL_Float(wl.refractScaleBelow)); - break; - case (int)ScriptBaseClass.WL_SCENE_GAMMA: - toadd.Add(new LSL_Float(wl.sceneGamma)); - break; - case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: - toadd.Add(new LSL_Float(wl.starBrightness)); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: - toadd.Add(new LSL_Float(wl.sunGlowFocus)); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: - toadd.Add(new LSL_Float(wl.sunGlowSize)); - break; - case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: - toadd.Add(new LSL_Rotation(wl.sunMoonColor.X, wl.sunMoonColor.Y, wl.sunMoonColor.Z, wl.sunMoonColor.W)); - break; - case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: - toadd.Add(new LSL_Float(wl.underwaterFogModifier)); - break; - case (int)ScriptBaseClass.WL_WATER_COLOR: - toadd.Add(new LSL_Vector(wl.waterColor.X, wl.waterColor.Y, wl.waterColor.Z)); - break; - case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: - toadd.Add(new LSL_Float(wl.waterFogDensityExponent)); - break; - } - - if (toadd.Length > 0) - { - values.Add(rule); - values.Add(toadd.Data[0]); - } - idx++; - } - - - return values; - - } - - /// - /// Set the current Windlight scene - /// - /// - /// success: true or false - public int osSetWindlightScene(LSL_List rules) - { - CheckThreatLevel(ThreatLevel.High, "osSetWindlightScene"); - int success = 0; - m_host.AddScriptLPS(1); - if (Meta7WindlightModule.EnableWindlight) - { - RegionMeta7WindlightData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; - - LSL_List values = new LSL_List(); - int idx = 0; - success = 1; - while (idx < rules.Length) - { - uint rule = (uint)rules.GetLSLIntegerItem(idx); - LSL_Types.Quaternion iQ; - LSL_Types.Vector3 iV; - switch (rule) - { - case (int)ScriptBaseClass.WL_AMBIENT: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_BLUE_DENSITY: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: - idx++; - wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: - idx++; - wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCALE: - idx++; - wl.cloudScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: - idx++; - wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: - idx++; - wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: - idx++; - wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: - idx++; - wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: - idx++; - wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: - idx++; - wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: - idx++; - wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_EAST_ANGLE: - idx++; - wl.eastAngle = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: - idx++; - wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_SCALE: - idx++; - wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_DENSITY: - idx++; - wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_HORIZON: - idx++; - wl.hazeHorizon= (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HORIZON: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_MAX_ALTITUDE: - idx++; - wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; - break; - case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: - idx++; - wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); - break; - case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: - idx++; - iV = rules.GetVector3Item(idx); - wl.reflectionWaveletScale= new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: - idx++; - wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: - idx++; - wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SCENE_GAMMA: - idx++; - wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: - idx++; - wl.starBrightness= (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: - idx++; - wl.sunGlowFocus= (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: - idx++; - wl.sunGlowSize= (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: - idx++; - wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_WATER_COLOR: - idx++; - iV = rules.GetVector3Item(idx); - wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: - idx++; - wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); - break; - default: - success = 0; - break; - } - idx++; - } - m_host.ParentGroup.Scene.StoreWindlightProfile(wl); - - } - return success; - } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs new file mode 100644 index 0000000..9dd0b73 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs @@ -0,0 +1,20 @@ +using System.Collections; +using OpenSim.Region.ScriptEngine.Interfaces; + +using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; +using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; +using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; +using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; +using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; + +namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces +{ + public interface ICM_Api + { + // Windlight Functions + LSL_List cmGetWindlightScene(LSL_List rules); + int cmSetWindlightScene(LSL_List rules); + } +} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index dd2869b..c3bf7d2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -163,10 +163,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces key osGetMapTexture(); key osGetRegionMapTexture(string regionName); LSL_List osGetRegionStats(); - - // Windlight Functions - LSL_List osGetWindlightScene(LSL_List rules); - int osSetWindlightScene(LSL_List rules); - } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Constants.cs new file mode 100644 index 0000000..7b67fa3 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Constants.cs @@ -0,0 +1,76 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; +using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; +using LSLInteger = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; + +namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase +{ + public partial class ScriptBaseClass + { + // Constants for cmWindlight* + public const int WL_WATER_COLOR = 0; + public const int WL_WATER_FOG_DENSITY_EXPONENT = 1; + public const int WL_UNDERWATER_FOG_MODIFIER = 2; + public const int WL_REFLECTION_WAVELET_SCALE = 3; + public const int WL_FRESNEL_SCALE = 4; + public const int WL_FRESNEL_OFFSET = 5; + public const int WL_REFRACT_SCALE_ABOVE = 6; + public const int WL_REFRACT_SCALE_BELOW = 7; + public const int WL_BLUR_MULTIPLIER = 8; + public const int WL_BIG_WAVE_DIRECTION = 9; + public const int WL_LITTLE_WAVE_DIRECTION = 10; + public const int WL_NORMAL_MAP_TEXTURE = 11; + public const int WL_HORIZON = 12; + public const int WL_HAZE_HORIZON = 13; + public const int WL_BLUE_DENSITY = 14; + public const int WL_HAZE_DENSITY = 15; + public const int WL_DENSITY_MULTIPLIER = 16; + public const int WL_DISTANCE_MULTIPLIER = 17; + public const int WL_MAX_ALTITUDE = 18; + public const int WL_SUN_MOON_COLOR = 19; + public const int WL_AMBIENT = 20; + public const int WL_EAST_ANGLE = 21; + public const int WL_SUN_GLOW_FOCUS = 22; + public const int WL_SUN_GLOW_SIZE = 23; + public const int WL_SCENE_GAMMA = 24; + public const int WL_STAR_BRIGHTNESS = 25; + public const int WL_CLOUD_COLOR = 26; + public const int WL_CLOUD_XY_DENSITY = 27; + public const int WL_CLOUD_COVERAGE = 28; + public const int WL_CLOUD_SCALE = 29; + public const int WL_CLOUD_DETAIL_XY_DENSITY = 30; + public const int WL_CLOUD_SCROLL_X = 31; + public const int WL_CLOUD_SCROLL_Y = 32; + public const int WL_CLOUD_SCROLL_Y_LOCK = 33; + public const int WL_CLOUD_SCROLL_X_LOCK = 34; + public const int WL_DRAW_CLASSIC_CLOUDS = 35; + + } +} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs new file mode 100644 index 0000000..e85d41e --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs @@ -0,0 +1,71 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Runtime.Remoting.Lifetime; +using System.Threading; +using System.Reflection; +using System.Collections; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.ScriptEngine.Interfaces; +using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; +using integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; +using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; +using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; +using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; +using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; +using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; + +namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase +{ + public partial class ScriptBaseClass : MarshalByRefObject + { + public ICM_Api m_CM_Functions; + + public void ApiTypeCM(IScriptApi api) + { + if (!(api is ICM_Api)) + return; + + m_CM_Functions = (ICM_Api)api; + } + + public LSL_List cmGetWindlightScene(LSL_List rules) + { + return m_CM_Functions.cmGetWindlightScene(rules); + } + + public int cmSetWindlightScene(LSL_List rules) + { + return m_CM_Functions.cmSetWindlightScene(rules); + } + } +} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 4956c28..acff8fb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -539,43 +539,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int STATS_ACTIVE_SCRIPTS = 19; public const int STATS_SCRIPT_LPS = 20; - // Constants for osWindlight* - public const int WL_WATER_COLOR = 0; - public const int WL_WATER_FOG_DENSITY_EXPONENT = 1; - public const int WL_UNDERWATER_FOG_MODIFIER = 2; - public const int WL_REFLECTION_WAVELET_SCALE = 3; - public const int WL_FRESNEL_SCALE = 4; - public const int WL_FRESNEL_OFFSET = 5; - public const int WL_REFRACT_SCALE_ABOVE = 6; - public const int WL_REFRACT_SCALE_BELOW = 7; - public const int WL_BLUR_MULTIPLIER = 8; - public const int WL_BIG_WAVE_DIRECTION = 9; - public const int WL_LITTLE_WAVE_DIRECTION = 10; - public const int WL_NORMAL_MAP_TEXTURE = 11; - public const int WL_HORIZON = 12; - public const int WL_HAZE_HORIZON = 13; - public const int WL_BLUE_DENSITY = 14; - public const int WL_HAZE_DENSITY = 15; - public const int WL_DENSITY_MULTIPLIER = 16; - public const int WL_DISTANCE_MULTIPLIER = 17; - public const int WL_MAX_ALTITUDE = 18; - public const int WL_SUN_MOON_COLOR = 19; - public const int WL_AMBIENT = 20; - public const int WL_EAST_ANGLE = 21; - public const int WL_SUN_GLOW_FOCUS = 22; - public const int WL_SUN_GLOW_SIZE = 23; - public const int WL_SCENE_GAMMA = 24; - public const int WL_STAR_BRIGHTNESS = 25; - public const int WL_CLOUD_COLOR = 26; - public const int WL_CLOUD_XY_DENSITY = 27; - public const int WL_CLOUD_COVERAGE = 28; - public const int WL_CLOUD_SCALE = 29; - public const int WL_CLOUD_DETAIL_XY_DENSITY = 30; - public const int WL_CLOUD_SCROLL_X = 31; - public const int WL_CLOUD_SCROLL_Y = 32; - public const int WL_CLOUD_SCROLL_Y_LOCK = 33; - public const int WL_CLOUD_SCROLL_X_LOCK = 34; - public const int WL_DRAW_CLASSIC_CLOUDS = 35; - } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 1480b8b..519463e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -637,15 +637,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osGetRegionStats(); } - - public LSL_List osGetWindlightScene(LSL_List rules) - { - return m_OSSL_Functions.osGetWindlightScene(rules); - } - - public int osSetWindlightScene(LSL_List rules) - { - return m_OSSL_Functions.osSetWindlightScene(rules); - } } } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index b7f7c3c..04cf8e8 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -980,6 +980,9 @@ ; Allow the use of os* functions (some are dangerous) AllowOSFunctions = false + + ; Allow the user of Careminster functions + AllowCareminsterFunctions = false ; Threat level to allow, one of None, VeryLow, Low, Moderate, High, VeryHigh, Severe OSFunctionThreatLevel = VeryLow -- cgit v1.1 From 0889b5aef1b93909cb7ae5c29beb5e23bd566c47 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 10 Dec 2009 18:20:40 +0000 Subject: Fix version number --- OpenSim/Framework/Servers/VersionInfo.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index f5be1e6..d348c90 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,8 +29,8 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "112609s"; - private const Flavour VERSION_FLAVOUR = Flavour.BetaM7; + private const string VERSION_NUMBER = "0.6.9CM"; + private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour { Unknown, @@ -38,8 +38,7 @@ namespace OpenSim RC1, RC2, Release, - Post_Fixes, - BetaM7 + Post_Fixes } public static string Version -- cgit v1.1 From 5ffd59e7b870acb74ad7c6be4a1f49b62b013f21 Mon Sep 17 00:00:00 2001 From: grid Date: Thu, 10 Dec 2009 22:09:16 -0500 Subject: Kill a NRE caused by an error message trying to print unavailable data --- OpenSim/Data/MySQL/MySQLLegacyRegionData.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs index e2a5406..17977f1 100644 --- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs @@ -480,8 +480,8 @@ namespace OpenSim.Data.MySQL else { m_log.WarnFormat( - "[REGION DB]: Database contains an orphan child prim {0} {1} at {2} in region {3} pointing to missing parent {4}. This prim will not be loaded.", - prim.Name, prim.UUID, prim.AbsolutePosition, regionID, prim.ParentUUID); + "[REGION DB]: Database contains an orphan child prim {0} {1} in region {3} pointing to missing parent {4}. This prim will not be loaded.", + prim.Name, prim.UUID, regionID, prim.ParentUUID); } } } -- cgit v1.1 From f6b1344722908f0d14d6e30c4b01b2f712c584f2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 11 Dec 2009 02:40:33 +0000 Subject: Refix the fix --- OpenSim/Data/MySQL/MySQLLegacyRegionData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs index 17977f1..e57e929 100644 --- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs @@ -480,7 +480,7 @@ namespace OpenSim.Data.MySQL else { m_log.WarnFormat( - "[REGION DB]: Database contains an orphan child prim {0} {1} in region {3} pointing to missing parent {4}. This prim will not be loaded.", + "[REGION DB]: Database contains an orphan child prim {0} {1} in region {2} pointing to missing parent {3}. This prim will not be loaded.", prim.Name, prim.UUID, regionID, prim.ParentUUID); } } -- cgit v1.1 From b9cd66d510f9229952aec5594d512faf7b60c899 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 12 Dec 2009 13:33:45 +0000 Subject: test commit --- OpenSim/Framework/Servers/VersionInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index d348c90..75e4a5d 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,6 +29,7 @@ namespace OpenSim { public class VersionInfo { + private const string VERSION_NUMBER = "0.6.9CM"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour -- cgit v1.1 From fbafd2212402619ec5efa66797fd42d59da1333b Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 12 Dec 2009 13:43:49 +0000 Subject: Reverse text commit whitespace change --- OpenSim/Framework/Servers/VersionInfo.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 75e4a5d..d348c90 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,6 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.6.9CM"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour -- cgit v1.1 From 794419852b793cd0be96bafb945305fadbb95b6c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 12 Dec 2009 14:23:20 +0000 Subject: Another test --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index d348c90..714a592 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + namespace OpenSim { public class VersionInfo -- cgit v1.1 From c00158b238c863d27f1b883f2cd4e573f7036dda Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 12 Dec 2009 14:35:12 +0000 Subject: Reverse test commit (again) --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 714a592..d348c90 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + namespace OpenSim { public class VersionInfo -- cgit v1.1 From b056c243e46daa3370f8d330b70a37b5f856e9ec Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Sat, 12 Dec 2009 10:12:59 -0500 Subject: Commit partial work because of repo change --- OpenSim/Data/SQLite/SQLiteRegionData.cs | 2 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 83 ++++++++++++++++++++---- 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs index f1c1f78..83fd775 100644 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLite/SQLiteRegionData.cs @@ -329,7 +329,7 @@ namespace OpenSim.Data.SQLite { foreach (SceneObjectPart prim in obj.Children.Values) { - m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); +// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); addPrim(prim, obj.UUID, regionUUID); } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c553ca0..d0c20ff 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1660,16 +1660,27 @@ namespace OpenSim.Region.Framework.Scenes } // part.GetWorldRotation() is the rotation of the object being sat on // Rotation is the sittiing Av's rotation - - Quaternion wr = Quaternion.Inverse(Quaternion.Inverse(Rotation) * Quaternion.Inverse(part.GetWorldRotation())); // world or. of the av - Vector3 so = new Vector3(1.0f, 0f, 0f) * wr; // 1M infront of av - Vector3 wso = so + part.GetWorldPosition() + ( m_pos * part.GetWorldRotation()); // + av sit offset! + + Quaternion partRot; + if (part.LinkNum == 1) + { // Root prim of linkset + partRot = part.ParentGroup.RootPart.RotationOffset; + } + else + { // single or child prim + partRot = part.GetWorldRotation(); + } + Quaternion partIRot = Quaternion.Inverse(partRot); + + Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av + Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av + Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ( m_pos * partRot); // + av sit offset! if (m_physicsActor == null) { AddToPhysicalScene(false); } - AbsolutePosition = wso; //KF: Fix stand up. + AbsolutePosition = avWorldStandUp; //KF: Fix stand up. m_parentPosition = Vector3.Zero; m_parentID = 0; part.IsOccupied = false; @@ -1752,8 +1763,17 @@ namespace OpenSim.Region.Framework.Scenes Quaternion avSitOrientation = part.SitTargetOrientation; bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. - Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); - + // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); + Quaternion partRot; + if (part.LinkNum == 1) + { // Root prim of linkset + partRot = part.ParentGroup.RootPart.RotationOffset; + } + else + { // single or child prim + partRot = part.GetWorldRotation(); + } + Quaternion partIRot = Quaternion.Inverse(partRot); //Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet); // Sit analysis rewritten by KF 091125 if (SitTargetisSet) // scipted sit @@ -1800,6 +1820,8 @@ namespace OpenSim.Region.Framework.Scenes cameraAtOffset = part.GetCameraAtOffset(); cameraEyeOffset = part.GetCameraEyeOffset(); forceMouselook = part.GetForceMouselook(); + if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); // + if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); // if (m_physicsActor != null) { @@ -1823,7 +1845,29 @@ namespace OpenSim.Region.Framework.Scenes } else return; // physactor is null! - Vector3 offsetr = offset * partIRot; + Vector3 offsetr; // = offset * partIRot; + // KF: In a linkset, offsetr needs to be relative to the group root! 091208 + // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot); + if (part.LinkNum < 2) + { // Single, or Root prim of linkset, target is ClickOffset * RootRot + offsetr = offset * partIRot; + } + else + { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot) + offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + + (offset * partRot); + } + +Console.WriteLine(" "); +Console.WriteLine("link number ={0}", part.LinkNum); +Console.WriteLine("Prim offset ={0}", part.OffsetPosition ); +Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset); +Console.WriteLine("Click offst ={0}", offset); +Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation()); +Console.WriteLine("offsetr ={0}", offsetr); +Console.WriteLine("Camera At ={0}", cameraAtOffset); +Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); + ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target // This calls HandleAgentSit twice, once from here, and the client calls @@ -2142,13 +2186,20 @@ namespace OpenSim.Region.Framework.Scenes } else { -//Console.WriteLine("NON Scripted Sit"); // if m_avUnscriptedSitPos is zero then Av sits above center // Else Av sits at m_avUnscriptedSitPos // Non-scripted sit by Kitto Flora 21Nov09 // Calculate angle of line from prim to Av - Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); + Quaternion partIRot; + if (part.LinkNum == 1) + { // Root prim of linkset + partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); + } + else + { // single or child prim + partIRot = Quaternion.Inverse(part.GetWorldRotation()); + } Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos; float y_diff = (m_avInitialPos.Y - sitTargetPos.Y); float x_diff = ( m_avInitialPos.X - sitTargetPos.X); @@ -2203,11 +2254,21 @@ namespace OpenSim.Region.Framework.Scenes // collisionPoint = spot on prim where we want to sit // collisionPoint.Z = global sit surface height SceneObjectPart part = m_scene.GetSceneObjectPart(localid); - Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); + Quaternion partIRot; + if (part.LinkNum == 1) + { // Root prim of linkset + partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); + } + else + { // single or child prim + partIRot = Quaternion.Inverse(part.GetWorldRotation()); + } float offZ = collisionPoint.Z - m_initialSitTarget.Z; Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); m_pos += offset; + ControllingClient.SendClearFollowCamProperties(part.UUID); + } } // End SitAltitudeCallback KF. -- cgit v1.1 From 9904700dfdb7c6a111d9464eb23566fff73dc6b1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 12 Dec 2009 16:00:44 +0000 Subject: Another whitespace test commit --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index d348c90..714a592 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + namespace OpenSim { public class VersionInfo -- cgit v1.1 From 30d64444a090148e5c07f27adc19ac2925533a19 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 12 Dec 2009 16:01:53 +0000 Subject: And reverse --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 714a592..d348c90 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -24,7 +24,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + namespace OpenSim { public class VersionInfo -- cgit v1.1 From b8b4517211d332f76c022075f81cfefd41877d14 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Tue, 15 Dec 2009 01:49:23 -0500 Subject: Removed excessive call to UpdateMovementAnimations which prevented GroundSit; Corrected cause of 'sit on roof'. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 48 ++++++++++++------------ 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index d0c20ff..c67463a 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -670,8 +670,7 @@ namespace OpenSim.Region.Framework.Scenes AdjustKnownSeeds(); - - Animator.TrySetMovementAnimation("STAND"); + Animator.TrySetMovementAnimation("STAND"); // we created a new ScenePresence (a new child agent) in a fresh region. // Request info about all the (root) agents in this region // Note: This won't send data *to* other clients in that region (children don't send) @@ -1691,7 +1690,6 @@ namespace OpenSim.Region.Framework.Scenes SetHeight(m_avHeight); } } - Animator.TrySetMovementAnimation("STAND"); } @@ -1858,15 +1856,15 @@ namespace OpenSim.Region.Framework.Scenes (offset * partRot); } -Console.WriteLine(" "); -Console.WriteLine("link number ={0}", part.LinkNum); -Console.WriteLine("Prim offset ={0}", part.OffsetPosition ); -Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset); -Console.WriteLine("Click offst ={0}", offset); -Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation()); -Console.WriteLine("offsetr ={0}", offsetr); -Console.WriteLine("Camera At ={0}", cameraAtOffset); -Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); +//Console.WriteLine(" "); +//Console.WriteLine("link number ={0}", part.LinkNum); +//Console.WriteLine("Prim offset ={0}", part.OffsetPosition ); +//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset); +//Console.WriteLine("Click offst ={0}", offset); +//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation()); +//Console.WriteLine("offsetr ={0}", offsetr); +//Console.WriteLine("Camera At ={0}", cameraAtOffset); +//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target @@ -2218,7 +2216,7 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); m_avUnscriptedSitPos; // adds click offset, if any //Set up raytrace to find top surface of prim Vector3 size = part.Scale; - float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); + float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); Vector3 down = new Vector3(0f, 0f, -1f); //Console.WriteLine("st={0} do={1} ma={2}", start, down, mag); @@ -2267,7 +2265,7 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); m_pos += offset; - ControllingClient.SendClearFollowCamProperties(part.UUID); +// ControllingClient.SendClearFollowCamProperties(part.UUID); } } // End SitAltitudeCallback KF. @@ -3297,7 +3295,7 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); m_updateflag = true; Velocity = force; m_isNudging = false; - m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND" + m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND" } } } @@ -3349,19 +3347,19 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); // Event called by the physics plugin to tell the avatar about a collision. private void PhysicsCollisionUpdate(EventArgs e) { - if (m_updateCount > 0) //KF: Update Anims for a short period. Many Anim - { // changes are very asynchronous. - Animator.UpdateMovementAnimations(); - m_updateCount--; - } - if (e == null) return; - - // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents( + + // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents( // as of this comment the interval is set in AddToPhysicalScene if (Animator!=null) - Animator.UpdateMovementAnimations(); + { + if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper, + { // else its will lock out other animation changes, like ground sit. + Animator.UpdateMovementAnimations(); + m_updateCount--; + } + } CollisionEventUpdate collisionData = (CollisionEventUpdate)e; Dictionary coldata = collisionData.m_objCollisionList; @@ -3370,7 +3368,7 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); if (m_lastColCount != coldata.Count) { - m_updateCount = 10; + m_updateCount = UPDATE_COUNT; m_lastColCount = coldata.Count; } -- cgit v1.1 From 7cd44c1a818615ca0e267f64c74593ad0361350b Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Tue, 15 Dec 2009 20:04:53 -0500 Subject: Fix prim linking bug, Manis #14 --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a23c11e..778e384 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -513,18 +513,24 @@ namespace OpenSim.Region.Framework.Scenes { // If this is a linkset, we don't want the physics engine mucking up our group position here. PhysicsActor actor = PhysActor; + + if (actor != null && _parentID == 0) + { + m_groupPosition = actor.Position; + } +/* if (actor != null) { if (_parentID == 0) { - m_groupPosition = actor.Position; + m_groupPosition = actor.Position; } else { m_groupPosition = ParentGroup.AbsolutePosition; // KF+Casper Update Child prims too! } } - +*/ if (IsAttachment) { ScenePresence sp = m_parentGroup.Scene.GetScenePresence(AttachedAvatar); -- cgit v1.1 From 6483470ec5e9000fb6a85bbdfe5b79be6f336a74 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 17 Dec 2009 02:54:02 -0500 Subject: Fix GetWorldRotation(), and a host of related Sit fixes. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 73 +++++++++++----------- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 6 +- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 778e384..4495eda 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1775,7 +1775,7 @@ namespace OpenSim.Region.Framework.Scenes { Quaternion newRot; - if (this.LinkNum == 0) + if (this.LinkNum < 2) //KF Single or root prim { newRot = RotationOffset; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c67463a..865f649 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1661,14 +1661,14 @@ namespace OpenSim.Region.Framework.Scenes // Rotation is the sittiing Av's rotation Quaternion partRot; - if (part.LinkNum == 1) - { // Root prim of linkset - partRot = part.ParentGroup.RootPart.RotationOffset; - } - else - { // single or child prim +// if (part.LinkNum == 1) +// { // Root prim of linkset +// partRot = part.ParentGroup.RootPart.RotationOffset; +// } +// else +// { // single or child prim partRot = part.GetWorldRotation(); - } +// } Quaternion partIRot = Quaternion.Inverse(partRot); Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av @@ -1763,14 +1763,14 @@ namespace OpenSim.Region.Framework.Scenes bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); Quaternion partRot; - if (part.LinkNum == 1) - { // Root prim of linkset - partRot = part.ParentGroup.RootPart.RotationOffset; - } - else - { // single or child prim +// if (part.LinkNum == 1) +// { // Root prim of linkset +// partRot = part.ParentGroup.RootPart.RotationOffset; +// } +// else +// { // single or child prim partRot = part.GetWorldRotation(); - } +// } Quaternion partIRot = Quaternion.Inverse(partRot); //Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet); // Sit analysis rewritten by KF 091125 @@ -1846,15 +1846,15 @@ namespace OpenSim.Region.Framework.Scenes Vector3 offsetr; // = offset * partIRot; // KF: In a linkset, offsetr needs to be relative to the group root! 091208 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot); - if (part.LinkNum < 2) - { // Single, or Root prim of linkset, target is ClickOffset * RootRot + // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error. + // { // Single, or Root prim of linkset, target is ClickOffset * RootRot offsetr = offset * partIRot; - } - else - { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot) - offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + - (offset * partRot); - } +// + // else + // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot) + // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + + // (offset * partRot); + // } //Console.WriteLine(" "); //Console.WriteLine("link number ={0}", part.LinkNum); @@ -2170,6 +2170,7 @@ namespace OpenSim.Region.Framework.Scenes { if (part != null) { +//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation()); if (part.GetAvatarOnSitTarget() == UUID) { //Console.WriteLine("Scripted Sit"); @@ -2190,14 +2191,14 @@ namespace OpenSim.Region.Framework.Scenes // Non-scripted sit by Kitto Flora 21Nov09 // Calculate angle of line from prim to Av Quaternion partIRot; - if (part.LinkNum == 1) - { // Root prim of linkset - partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); - } - else - { // single or child prim +// if (part.LinkNum == 1) +// { // Root prim of linkset +// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); +// } +// else +// { // single or child prim partIRot = Quaternion.Inverse(part.GetWorldRotation()); - } +// } Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos; float y_diff = (m_avInitialPos.Y - sitTargetPos.Y); float x_diff = ( m_avInitialPos.X - sitTargetPos.X); @@ -2253,14 +2254,14 @@ namespace OpenSim.Region.Framework.Scenes // collisionPoint.Z = global sit surface height SceneObjectPart part = m_scene.GetSceneObjectPart(localid); Quaternion partIRot; - if (part.LinkNum == 1) - { // Root prim of linkset - partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); - } - else - { // single or child prim +// if (part.LinkNum == 1) +/// { // Root prim of linkset +// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); +// } +// else +// { // single or child prim partIRot = Quaternion.Inverse(part.GetWorldRotation()); - } +// } float offZ = collisionPoint.Z - m_initialSitTarget.Z; Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index c27c420..688be83 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -2673,7 +2673,7 @@ Console.WriteLine(" JointCreateFixed"); m_lastposition = _position; m_lastorientation = _orientation; - + l_position.X = vec.X; l_position.Y = vec.Y; l_position.Z = vec.Z; @@ -2681,6 +2681,10 @@ Console.WriteLine(" JointCreateFixed"); l_orientation.Y = ori.Y; l_orientation.Z = ori.Z; l_orientation.W = ori.W; + +// if(l_position.Y != m_lastposition.Y){ +// Console.WriteLine("UP&V {0} {1}", m_primName, l_position); +// } if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f) { -- cgit v1.1 From 6dbe25360ec3dc3c998378da8b422751d3e032a9 Mon Sep 17 00:00:00 2001 From: CasperW Date: Thu, 17 Dec 2009 18:40:34 +0100 Subject: Add cmSetWindlightSceneTargeted. Add restrictions on windlight script use. --- OpenSim/Data/MySQL/Resources/032_RegionStore.sql | 20 +- OpenSim/Framework/RegionInfo.cs | 21 +- .../World/Meta7Windlight/Meta7WindlightModule.cs | 127 ++++--- OpenSim/Region/Framework/Scenes/EventManager.cs | 12 + OpenSim/Region/Framework/Scenes/Scene.cs | 4 +- .../Shared/Api/Implementation/CM_Api.cs | 401 ++++++++++++--------- .../ScriptEngine/Shared/Api/Interface/ICM_Api.cs | 3 +- .../ScriptEngine/Shared/Api/Runtime/CM_Stub.cs | 5 + 8 files changed, 344 insertions(+), 249 deletions(-) diff --git a/OpenSim/Data/MySQL/Resources/032_RegionStore.sql b/OpenSim/Data/MySQL/Resources/032_RegionStore.sql index 0545ee1..b10ffcf 100644 --- a/OpenSim/Data/MySQL/Resources/032_RegionStore.sql +++ b/OpenSim/Data/MySQL/Resources/032_RegionStore.sql @@ -20,15 +20,15 @@ CREATE TABLE `regionwindlight` ( `little_wave_direction_x` float(3,2) NOT NULL DEFAULT '1.11', `little_wave_direction_y` float(3,2) NOT NULL DEFAULT '-1.16', `normal_map_texture` varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4', - `horizon_r` float(3,2) unsigned NOT NULL DEFAULT '0.26', - `horizon_g` float(3,2) unsigned NOT NULL DEFAULT '0.24', - `horizon_b` float(3,2) unsigned NOT NULL DEFAULT '0.33', - `horizon_i` float(3,2) unsigned NOT NULL DEFAULT '0.33', + `horizon_r` float(3,2) unsigned NOT NULL DEFAULT '0.25', + `horizon_g` float(3,2) unsigned NOT NULL DEFAULT '0.25', + `horizon_b` float(3,2) unsigned NOT NULL DEFAULT '0.32', + `horizon_i` float(3,2) unsigned NOT NULL DEFAULT '0.32', `haze_horizon` float(3,2) unsigned NOT NULL DEFAULT '0.19', - `blue_density_r` float(3,2) unsigned NOT NULL DEFAULT '0.10', - `blue_density_g` float(3,2) unsigned NOT NULL DEFAULT '0.93', - `blue_density_b` float(3,2) unsigned NOT NULL DEFAULT '0.02', - `blue_density_i` float(3,2) unsigned NOT NULL DEFAULT '0.93', + `blue_density_r` float(3,2) unsigned NOT NULL DEFAULT '0.12', + `blue_density_g` float(3,2) unsigned NOT NULL DEFAULT '0.22', + `blue_density_b` float(3,2) unsigned NOT NULL DEFAULT '0.38', + `blue_density_i` float(3,2) unsigned NOT NULL DEFAULT '0.38', `haze_density` float(3,2) unsigned NOT NULL DEFAULT '0.70', `density_multiplier` float(3,2) unsigned NOT NULL DEFAULT '0.18', `distance_multiplier` float(4,1) unsigned NOT NULL DEFAULT '0.8', @@ -37,7 +37,7 @@ CREATE TABLE `regionwindlight` ( `sun_moon_color_g` float(3,2) unsigned NOT NULL DEFAULT '0.26', `sun_moon_color_b` float(3,2) unsigned NOT NULL DEFAULT '0.30', `sun_moon_color_i` float(3,2) unsigned NOT NULL DEFAULT '0.30', - `sun_moon_position` float(4,3) unsigned NOT NULL DEFAULT '0.335', + `sun_moon_position` float(4,3) unsigned NOT NULL DEFAULT '0.317', `ambient_r` float(3,2) unsigned NOT NULL DEFAULT '0.35', `ambient_g` float(3,2) unsigned NOT NULL DEFAULT '0.35', `ambient_b` float(3,2) unsigned NOT NULL DEFAULT '0.35', @@ -63,7 +63,7 @@ CREATE TABLE `regionwindlight` ( `cloud_scroll_x_lock` tinyint(1) unsigned NOT NULL DEFAULT '0', `cloud_scroll_y` float(3,2) unsigned NOT NULL DEFAULT '0.01', `cloud_scroll_y_lock` tinyint(1) unsigned NOT NULL DEFAULT '0', - `draw_classic_clouds` tinyint(1) unsigned NOT NULL DEFAULT '0', + `draw_classic_clouds` tinyint(1) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (`region_id`) ); diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 9e00528..1ea08f9 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -38,8 +38,8 @@ using OpenSim.Framework.Console; namespace OpenSim.Framework -{ - public class RegionMeta7WindlightData +{ + public class RegionMeta7WindlightData : ICloneable { public UUID regionID = UUID.Zero; public Vector3 waterColor = new Vector3(4.0f,38.0f,64.0f); @@ -54,19 +54,19 @@ namespace OpenSim.Framework public Vector2 bigWaveDirection = new Vector2(1.05f,-0.42f); public Vector2 littleWaveDirection = new Vector2(1.11f,-1.16f); public UUID normalMapTexture = new UUID("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); - public Vector4 horizon = new Vector4(0.26f, 0.24f, 0.34f, 0.33f); + public Vector4 horizon = new Vector4(0.25f, 0.25f, 0.32f, 0.32f); public float hazeHorizon = 0.19f; - public Vector4 blueDensity = new Vector4(0.10f, 0.93f, 0.02f, 0.93f); + public Vector4 blueDensity = new Vector4(0.12f, 0.22f, 0.38f, 0.38f); public float hazeDensity = 0.70f; public float densityMultiplier = 0.18f; public float distanceMultiplier = 0.8f; public UInt16 maxAltitude = 1605; public Vector4 sunMoonColor = new Vector4(0.24f, 0.26f, 0.30f, 0.30f); - public float sunMoonPosition = 0.335f; + public float sunMoonPosition = 0.317f; public Vector4 ambient = new Vector4(0.35f,0.35f,0.35f,0.35f); public float eastAngle = 0.0f; public float sunGlowFocus = 0.10f; - public float sunGlowSize = 0.10f; + public float sunGlowSize = 1.75f; public float sceneGamma = 1.0f; public float starBrightness = 0.0f; public Vector4 cloudColor = new Vector4(0.41f, 0.41f, 0.41f, 0.41f); @@ -78,7 +78,7 @@ namespace OpenSim.Framework public bool cloudScrollXLock = false; public float cloudScrollY = 0.01f; public bool cloudScrollYLock = false; - public bool drawClassicClouds = false; + public bool drawClassicClouds = true; public delegate void SaveDelegate(RegionMeta7WindlightData wl); public event SaveDelegate OnSave; @@ -86,7 +86,12 @@ namespace OpenSim.Framework { if (OnSave != null) OnSave(this); - } + } + public object Clone() + { + return this.MemberwiseClone(); // call clone method + } + } [Serializable] diff --git a/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs b/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs index f180b47..72b0b38 100644 --- a/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs +++ b/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs @@ -70,64 +70,69 @@ namespace OpenSim.Region.CoreModules.World.Meta7Windlight if (m_enableWindlight) { m_scene.EventManager.OnMakeRootAgent += EventManager_OnMakeRootAgent; - m_scene.EventManager.OnSaveNewWindlightProfile += EventManager_OnSaveNewWindlightProfile; + m_scene.EventManager.OnSaveNewWindlightProfile += EventManager_OnSaveNewWindlightProfile; + m_scene.EventManager.OnSendNewWindlightProfileTargeted += EventManager_OnSendNewWindlightProfileTargeted; } InstallCommands(); m_log.Debug("[WINDLIGHT]: Initialised windlight module"); + } + + private List compileWindlightSettings(RegionMeta7WindlightData wl) + { + byte[] mBlock = new Byte[249]; + int pos = 0; + + wl.waterColor.ToBytes(mBlock, 0); pos += 12; + Utils.FloatToBytes(wl.waterFogDensityExponent).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.underwaterFogModifier).CopyTo(mBlock, pos); pos += 4; + wl.reflectionWaveletScale.ToBytes(mBlock, pos); pos += 12; + Utils.FloatToBytes(wl.fresnelScale).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.fresnelOffset).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.refractScaleAbove).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.refractScaleBelow).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.blurMultiplier).CopyTo(mBlock, pos); pos += 4; + wl.bigWaveDirection.ToBytes(mBlock, pos); pos += 8; + wl.littleWaveDirection.ToBytes(mBlock, pos); pos += 8; + wl.normalMapTexture.ToBytes(mBlock, pos); pos += 16; + wl.horizon.ToBytes(mBlock, pos); pos += 16; + Utils.FloatToBytes(wl.hazeHorizon).CopyTo(mBlock, pos); pos += 4; + wl.blueDensity.ToBytes(mBlock, pos); pos += 16; + Utils.FloatToBytes(wl.hazeDensity).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.densityMultiplier).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.distanceMultiplier).CopyTo(mBlock, pos); pos += 4; + wl.sunMoonColor.ToBytes(mBlock, pos); pos += 16; + Utils.FloatToBytes(wl.sunMoonPosition).CopyTo(mBlock, pos); pos += 4; + wl.ambient.ToBytes(mBlock, pos); pos += 16; + Utils.FloatToBytes(wl.eastAngle).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.sunGlowFocus).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.sunGlowSize).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.sceneGamma).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.starBrightness).CopyTo(mBlock, pos); pos += 4; + wl.cloudColor.ToBytes(mBlock, pos); pos += 16; + wl.cloudXYDensity.ToBytes(mBlock, pos); pos += 12; + Utils.FloatToBytes(wl.cloudCoverage).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.cloudScale).CopyTo(mBlock, pos); pos += 4; + wl.cloudDetailXYDensity.ToBytes(mBlock, pos); pos += 12; + Utils.FloatToBytes(wl.cloudScrollX).CopyTo(mBlock, pos); pos += 4; + Utils.FloatToBytes(wl.cloudScrollY).CopyTo(mBlock, pos); pos += 4; + Utils.UInt16ToBytes(wl.maxAltitude).CopyTo(mBlock, pos); pos += 2; + mBlock[pos] = Convert.ToByte(wl.cloudScrollXLock); pos++; + mBlock[pos] = Convert.ToByte(wl.cloudScrollYLock); pos++; + mBlock[pos] = Convert.ToByte(wl.drawClassicClouds); pos++; + List param = new List(); + param.Add(mBlock); + return param; } public void SendProfileToClient(ScenePresence presence) - { + { + IClientAPI client = presence.ControllingClient; if (m_enableWindlight) { if (presence.IsChildAgent == false) - { - IClientAPI client = presence.ControllingClient; - RegionMeta7WindlightData wl = m_scene.RegionInfo.WindlightSettings; - byte[] mBlock = new Byte[249]; - int pos = 0; - - wl.waterColor.ToBytes(mBlock, 0); pos += 12; - Utils.FloatToBytes(wl.waterFogDensityExponent).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.underwaterFogModifier).CopyTo(mBlock, pos); pos += 4; - wl.reflectionWaveletScale.ToBytes(mBlock, pos); pos += 12; - Utils.FloatToBytes(wl.fresnelScale).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.fresnelOffset).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.refractScaleAbove).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.refractScaleBelow).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.blurMultiplier).CopyTo(mBlock, pos); pos += 4; - wl.bigWaveDirection.ToBytes(mBlock, pos); pos += 8; - wl.littleWaveDirection.ToBytes(mBlock, pos); pos += 8; - wl.normalMapTexture.ToBytes(mBlock, pos); pos += 16; - wl.horizon.ToBytes(mBlock, pos); pos += 16; - Utils.FloatToBytes(wl.hazeHorizon).CopyTo(mBlock, pos); pos += 4; - wl.blueDensity.ToBytes(mBlock, pos); pos += 16; - Utils.FloatToBytes(wl.hazeDensity).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.densityMultiplier).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.distanceMultiplier).CopyTo(mBlock, pos); pos += 4; - wl.sunMoonColor.ToBytes(mBlock, pos); pos += 16; - Utils.FloatToBytes(wl.sunMoonPosition).CopyTo(mBlock, pos); pos += 4; - wl.ambient.ToBytes(mBlock, pos); pos += 16; - Utils.FloatToBytes(wl.eastAngle).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.sunGlowFocus).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.sunGlowSize).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.sceneGamma).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.starBrightness).CopyTo(mBlock, pos); pos += 4; - wl.cloudColor.ToBytes(mBlock, pos); pos += 16; - wl.cloudXYDensity.ToBytes(mBlock, pos); pos += 12; - Utils.FloatToBytes(wl.cloudCoverage).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.cloudScale).CopyTo(mBlock, pos); pos += 4; - wl.cloudDetailXYDensity.ToBytes(mBlock, pos); pos += 12; - Utils.FloatToBytes(wl.cloudScrollX).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.cloudScrollY).CopyTo(mBlock, pos); pos += 4; - Utils.UInt16ToBytes(wl.maxAltitude).CopyTo(mBlock, pos); pos += 2; - mBlock[pos] = Convert.ToByte(wl.cloudScrollXLock); pos++; - mBlock[pos] = Convert.ToByte(wl.cloudScrollYLock); pos++; - mBlock[pos] = Convert.ToByte(wl.drawClassicClouds); pos++; - List param = new List(); - param.Add(mBlock); - + { + List param = compileWindlightSettings(m_scene.RegionInfo.WindlightSettings); client.SendGenericMessage("Windlight", param); } } @@ -136,13 +141,37 @@ namespace OpenSim.Region.CoreModules.World.Meta7Windlight //We probably don't want to spam chat with this.. probably //m_log.Debug("[WINDLIGHT]: Module disabled"); } + } + public void SendProfileToClient(ScenePresence presence, RegionMeta7WindlightData wl) + { + IClientAPI client = presence.ControllingClient; + if (m_enableWindlight) + { + if (presence.IsChildAgent == false) + { + List param = compileWindlightSettings(wl); + client.SendGenericMessage("Windlight", param); + } + } + else + { + //We probably don't want to spam chat with this.. probably + //m_log.Debug("[WINDLIGHT]: Module disabled"); + } } private void EventManager_OnMakeRootAgent(ScenePresence presence) { m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client"); SendProfileToClient(presence); + } + private void EventManager_OnSendNewWindlightProfileTargeted(RegionMeta7WindlightData wl, UUID pUUID) + { + ScenePresence Sc; + if (m_scene.TryGetAvatar(pUUID,out Sc)) + { + SendProfileToClient(Sc,wl); + } } - private void EventManager_OnSaveNewWindlightProfile() { m_scene.ForEachScenePresence(SendProfileToClient); diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index a86e263..68e73b1 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -194,7 +194,9 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnMakeRootAgentDelegate(ScenePresence presence); public delegate void OnSaveNewWindlightProfileDelegate(); + public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionMeta7WindlightData wl, UUID user); public event OnMakeRootAgentDelegate OnMakeRootAgent; + public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile; public delegate void NewInventoryItemUploadComplete(UUID avatarID, UUID assetID, string name, int userlevel); @@ -414,6 +416,7 @@ namespace OpenSim.Region.Framework.Scenes private ClientClosed handlerClientClosed = null; //OnClientClosed; private OnMakeChildAgentDelegate handlerMakeChildAgent = null; //OnMakeChildAgent; private OnSaveNewWindlightProfileDelegate handlerSaveNewWindlightProfile = null; //OnSaveNewWindlightProfile; + private OnSendNewWindlightProfileTargetedDelegate handlerSendNewWindlightProfileTargeted = null; //OnSendNewWindlightProfileTargeted; private OnMakeRootAgentDelegate handlerMakeRootAgent = null; //OnMakeRootAgent; private OnTerrainTickDelegate handlerTerrainTick = null; // OnTerainTick; private RegisterCapsEvent handlerRegisterCaps = null; // OnRegisterCaps; @@ -775,6 +778,15 @@ namespace OpenSim.Region.Framework.Scenes } } + public void TriggerOnSendNewWindlightProfileTargeted(RegionMeta7WindlightData wl, UUID user) + { + handlerSendNewWindlightProfileTargeted = OnSendNewWindlightProfileTargeted; + if (handlerSendNewWindlightProfileTargeted != null) + { + handlerSendNewWindlightProfileTargeted(wl, user); + } + } + public void TriggerOnSaveNewWindlightProfile() { handlerSaveNewWindlightProfile = OnSaveNewWindlightProfile; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 104d22b..20cae5d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1519,8 +1519,8 @@ namespace OpenSim.Region.Framework.Scenes public void SaveTerrain() { m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); - } - + } + public void StoreWindlightProfile(RegionMeta7WindlightData wl) { m_regInfo.WindlightSettings = wl; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 4cc2f0a..d4250c1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -229,8 +229,181 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return values; - } + } + + private RegionMeta7WindlightData getWindlightProfileFromRules(LSL_List rules) + { + RegionMeta7WindlightData wl = (RegionMeta7WindlightData)m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.Clone(); + LSL_List values = new LSL_List(); + int idx = 0; + while (idx < rules.Length) + { + uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_Types.Quaternion iQ; + LSL_Types.Vector3 iV; + switch (rule) + { + case (int)ScriptBaseClass.WL_AMBIENT: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_BLUE_DENSITY: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: + idx++; + wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: + idx++; + wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCALE: + idx++; + wl.cloudScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: + idx++; + wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: + idx++; + wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: + idx++; + wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: + idx++; + wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: + idx++; + wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: + idx++; + wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: + idx++; + wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_EAST_ANGLE: + idx++; + wl.eastAngle = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: + idx++; + wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_SCALE: + idx++; + wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_DENSITY: + idx++; + wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_HORIZON: + idx++; + wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HORIZON: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_MAX_ALTITUDE: + idx++; + wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; + break; + case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: + idx++; + wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); + break; + case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: + idx++; + iV = rules.GetVector3Item(idx); + wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: + idx++; + wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: + idx++; + wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SCENE_GAMMA: + idx++; + wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: + idx++; + wl.starBrightness = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: + idx++; + wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: + idx++; + wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: + idx++; + wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_WATER_COLOR: + idx++; + iV = rules.GetVector3Item(idx); + wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: + idx++; + wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); + break; + } + idx++; + } + return wl; + } /// /// Set the current Windlight scene /// @@ -242,188 +415,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CMShoutError("Careminster functions are not enabled."); return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + CMShoutError("cmSetWindlightScene can only be used by estate managers or owners."); + return 0; } int success = 0; - m_host.AddScriptLPS(1); - if (Meta7WindlightModule.EnableWindlight) - { - RegionMeta7WindlightData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; - - LSL_List values = new LSL_List(); - int idx = 0; - success = 1; - while (idx < rules.Length) - { - uint rule = (uint)rules.GetLSLIntegerItem(idx); - LSL_Types.Quaternion iQ; - LSL_Types.Vector3 iV; - switch (rule) - { - case (int)ScriptBaseClass.WL_AMBIENT: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_BLUE_DENSITY: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: - idx++; - wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: - idx++; - wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCALE: - idx++; - wl.cloudScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: - idx++; - wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: - idx++; - wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: - idx++; - wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: - idx++; - wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: - idx++; - wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: - idx++; - wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: - idx++; - wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_EAST_ANGLE: - idx++; - wl.eastAngle = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: - idx++; - wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_SCALE: - idx++; - wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_DENSITY: - idx++; - wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_HORIZON: - idx++; - wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HORIZON: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_MAX_ALTITUDE: - idx++; - wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; - break; - case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: - idx++; - wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); - break; - case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: - idx++; - iV = rules.GetVector3Item(idx); - wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: - idx++; - wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: - idx++; - wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SCENE_GAMMA: - idx++; - wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: - idx++; - wl.starBrightness = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: - idx++; - wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: - idx++; - wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: - idx++; - wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_WATER_COLOR: - idx++; - iV = rules.GetVector3Item(idx); - wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: - idx++; - wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); - break; - default: - success = 0; - break; - } - idx++; - } - m_host.ParentGroup.Scene.StoreWindlightProfile(wl); - + m_host.AddScriptLPS(1); + if (Meta7WindlightModule.EnableWindlight) + { + RegionMeta7WindlightData wl = getWindlightProfileFromRules(rules); + m_host.ParentGroup.Scene.StoreWindlightProfile(wl); + success = 1; + } + else + { + CMShoutError("Windlight module is disabled"); + return 0; } return success; + } + /// + /// Set the current Windlight scene to a target avatar + /// + /// + /// success: true or false + public int cmSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) + { + if (!m_CMFunctionsEnabled) + { + CMShoutError("Careminster functions are not enabled."); + return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + CMShoutError("cmSetWindlightSceneTargeted can only be used by estate managers or owners."); + return 0; + } + int success = 0; + m_host.AddScriptLPS(1); + if (Meta7WindlightModule.EnableWindlight) + { + RegionMeta7WindlightData wl = getWindlightProfileFromRules(rules); + World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); + success = 1; + } + else + { + CMShoutError("Windlight module is disabled"); + return 0; + } + return success; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs index 9dd0b73..ef990a1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs @@ -15,6 +15,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { // Windlight Functions LSL_List cmGetWindlightScene(LSL_List rules); - int cmSetWindlightScene(LSL_List rules); + int cmSetWindlightScene(LSL_List rules); + int cmSetWindlightSceneTargeted(LSL_List rules, key target); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs index e85d41e..5bc3a88 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs @@ -66,6 +66,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public int cmSetWindlightScene(LSL_List rules) { return m_CM_Functions.cmSetWindlightScene(rules); + } + + public int cmSetWindlightSceneTargeted(LSL_List rules, key target) + { + return m_CM_Functions.cmSetWindlightSceneTargeted(rules, target); } } } -- cgit v1.1 From e38e8ae98759e403175016260edd27772b5c9e4c Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Sat, 19 Dec 2009 19:54:44 -0500 Subject: Fix mantis #10 & #14 --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 33 +++++++--------------- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index d348c90..a7d34f5 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,7 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.6.9CM"; + private const string VERSION_NUMBER = "0.6.91CM"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 778e384..0eddbfd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -513,24 +513,11 @@ namespace OpenSim.Region.Framework.Scenes { // If this is a linkset, we don't want the physics engine mucking up our group position here. PhysicsActor actor = PhysActor; - if (actor != null && _parentID == 0) { m_groupPosition = actor.Position; - } -/* - if (actor != null) - { - if (_parentID == 0) - { - m_groupPosition = actor.Position; - } - else - { - m_groupPosition = ParentGroup.AbsolutePosition; // KF+Casper Update Child prims too! - } } -*/ + if (IsAttachment) { ScenePresence sp = m_parentGroup.Scene.GetScenePresence(AttachedAvatar); @@ -545,7 +532,6 @@ namespace OpenSim.Region.Framework.Scenes StoreUndoState(); m_groupPosition = value; - PhysicsActor actor = PhysActor; if (actor != null) { @@ -1755,16 +1741,17 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 GetWorldPosition() { Quaternion parentRot = ParentGroup.RootPart.RotationOffset; - Vector3 axPos = OffsetPosition; axPos *= parentRot; Vector3 translationOffsetPosition = axPos; - - int tx = (int)GroupPosition.X; - int ty = (int)GroupPosition.Y; - int tz = (int)GroupPosition.Z; - - return GroupPosition + translationOffsetPosition; + if(_parentID == 0) + { + return GroupPosition; + } + else + { + return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position + } } /// @@ -1775,7 +1762,7 @@ namespace OpenSim.Region.Framework.Scenes { Quaternion newRot; - if (this.LinkNum == 0) + if (this.LinkNum < 2) //KF Single or root prim { newRot = RotationOffset; } -- cgit v1.1 From 31bf25d05e09395416c0427e783f8685a9e69889 Mon Sep 17 00:00:00 2001 From: CasperW Date: Sun, 20 Dec 2009 16:18:43 +0100 Subject: Reverted my changes to jhurliman's packet stack since it currently causes more problems than it resolves. The stack DOES need a rework particularly with regards to priorities, but this is not it. --- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 27 +----- .../Region/ClientStack/LindenUDP/OpenSimUDPBase.cs | 107 +-------------------- .../Region/ClientStack/LindenUDP/OutgoingPacket.cs | 4 +- 3 files changed, 6 insertions(+), 132 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 4d9f58f..3c4fa72 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -402,7 +402,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Queue or Send OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); - outgoingPacket.Type = type; if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) SendPacketFinal(outgoingPacket); @@ -514,7 +513,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte flags = buffer.Data[0]; bool isResend = (flags & Helpers.MSG_RESENT) != 0; bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; - bool sendSynchronous = false; LLUDPClient udpClient = outgoingPacket.Client; if (!udpClient.IsConnected) @@ -570,28 +568,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (isReliable) Interlocked.Add(ref udpClient.UnackedBytes, outgoingPacket.Buffer.DataLength); - //Some packet types need to be sent synchonously. - //Sorry, i know it's not optimal, but until the LL client - //manages packets correctly and re-orders them as required, this is necessary. - - // Put the UDP payload on the wire - if (outgoingPacket.Type == PacketType.ImprovedTerseObjectUpdate) - { - SyncBeginPrioritySend(buffer, 2); // highest priority - } - else if (outgoingPacket.Type == PacketType.ObjectUpdate - || outgoingPacket.Type == PacketType.LayerData) - { - SyncBeginPrioritySend(buffer, 1); // medium priority - } - else - { - SyncBeginPrioritySend(buffer, 0); // normal priority - } - - //AsyncBeginSend(buffer); - + AsyncBeginSend(buffer); + // Keep track of when this packet was sent out (right now) outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; } @@ -872,7 +851,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); - SyncBeginPrioritySend(buffer, 1); //Setting this to a medium priority should help minimise resends + AsyncBeginSend(buffer); } private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs index de2cd24..d2779ba 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs @@ -29,7 +29,6 @@ using System; using System.Net; using System.Net.Sockets; using System.Threading; -using System.Collections.Generic; using log4net; namespace OpenMetaverse @@ -53,30 +52,12 @@ namespace OpenMetaverse /// Local IP address to bind to in server mode protected IPAddress m_localBindAddress; - /// - /// Standard queue for our outgoing SyncBeginPrioritySend - /// - private List m_standardQueue = new List(); - - /// - /// Medium priority queue for our outgoing SyncBeginPrioritySend - /// - private List m_mediumPriorityQueue = new List(); - - /// - /// Prioritised queue for our outgoing SyncBeginPrioritySend - /// - private List m_priorityQueue = new List(); - /// UDP socket, used in either client or server mode private Socket m_udpSocket; /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; - /// Are we currently sending data asynchronously? - private volatile bool m_sendingData = false; - /// The all important shutdown flag private volatile bool m_shutdownFlag = true; @@ -265,51 +246,7 @@ namespace OpenMetaverse } } - public void SyncBeginPrioritySend(UDPPacketBuffer buf, int Priority) - { - if (!m_shutdownFlag) - { - if (!m_sendingData) - { - m_sendingData = true; - try - { - AsyncBeginSend(buf); - } - catch (SocketException) { } - catch (ObjectDisposedException) { } - } - else - { - if (Priority == 2) - { - lock (m_priorityQueue) - { - m_priorityQueue.Add(buf); - } - } - else - { - if (Priority != 0) - { - lock (m_mediumPriorityQueue) - { - m_mediumPriorityQueue.Add(buf); - } - } - else - { - lock (m_standardQueue) - { - m_standardQueue.Add(buf); - } - } - } - } - } - } - - private void AsyncBeginSend(UDPPacketBuffer buf) + public void AsyncBeginSend(UDPPacketBuffer buf) { if (!m_shutdownFlag) { @@ -333,48 +270,8 @@ namespace OpenMetaverse { try { +// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; m_udpSocket.EndSendTo(result); - - if (m_sendingData) - { - lock (m_priorityQueue) - { - if (m_priorityQueue.Count > 0) - { - UDPPacketBuffer buf = m_priorityQueue[0]; - m_priorityQueue.RemoveAt(0); - AsyncBeginSend(buf); - } - else - { - lock (m_mediumPriorityQueue) - { - if (m_mediumPriorityQueue.Count > 0) - { - UDPPacketBuffer buf = m_mediumPriorityQueue[0]; - m_mediumPriorityQueue.RemoveAt(0); - AsyncBeginSend(buf); - } - else - { - lock (m_standardQueue) - { - if (m_standardQueue.Count > 0) - { - UDPPacketBuffer buf = m_standardQueue[0]; - m_standardQueue.RemoveAt(0); - AsyncBeginSend(buf); - } - else - { - m_sendingData = false; - } - } - } - } - } - } - } } catch (SocketException) { } catch (ObjectDisposedException) { } diff --git a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs index 7dc42d3..1a1a1cb 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OutgoingPacket.cs @@ -28,7 +28,6 @@ using System; using OpenSim.Framework; using OpenMetaverse; -using OpenMetaverse.Packets; namespace OpenSim.Region.ClientStack.LindenUDP { @@ -53,8 +52,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public int TickCount; /// Category this packet belongs to public ThrottleOutPacketType Category; - /// The type of packet so its delivery method can be determined - public PacketType Type; + /// /// Default constructor /// -- cgit v1.1 From e3c14660478bdd3af8c792b4b6b48ffffbbe19f9 Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 21 Dec 2009 13:22:52 +0100 Subject: Fixed a nasty crash in StandUp() that occurred when the part got killed with an avatar sitting on it. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 54 ++++++++++++++++++------ 1 file changed, 41 insertions(+), 13 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 865f649..abdd1a0 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -118,7 +118,8 @@ namespace OpenSim.Region.Framework.Scenes private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation private Vector3 m_avUnscriptedSitPos; // for non-scripted prims - private Vector3 m_lastPosition; + private Vector3 m_lastPosition; + private Vector3 m_lastWorldPosition; private Quaternion m_lastRotation; private Vector3 m_lastVelocity; //private int m_lastTerseSent; @@ -1667,24 +1668,45 @@ namespace OpenSim.Region.Framework.Scenes // } // else // { // single or child prim - partRot = part.GetWorldRotation(); -// } + +// } + if (part == null) //CW: Part may be gone. llDie() for example. + { + partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + else + { + partRot = part.GetWorldRotation(); + } + Quaternion partIRot = Quaternion.Inverse(partRot); Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av - Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ( m_pos * partRot); // + av sit offset! - if (m_physicsActor == null) - { - AddToPhysicalScene(false); + + if (m_physicsActor == null) + { + AddToPhysicalScene(false); + } + //CW: If the part isn't null then we can set the current position + if (part != null) + { + Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset! + AbsolutePosition = avWorldStandUp; //KF: Fix stand up. + part.IsOccupied = false; + } + else + { + //CW: Since the part doesn't exist, a coarse standup position isn't an issue + AbsolutePosition = m_lastWorldPosition; } - AbsolutePosition = avWorldStandUp; //KF: Fix stand up. - m_parentPosition = Vector3.Zero; + + m_parentPosition = Vector3.Zero; m_parentID = 0; - part.IsOccupied = false; SendFullUpdateToAllClients(); m_requestedSitTargetID = 0; + if ((m_physicsActor != null) && (m_avHeight > 0)) { SetHeight(m_avHeight); @@ -1778,7 +1800,7 @@ namespace OpenSim.Region.Framework.Scenes { if (!part.IsOccupied) { -//Console.WriteLine("Scripted, unoccupied"); +//Console.WriteLine("Scripted, unoccupied"); part.SetAvatarOnSitTarget(UUID); // set that Av will be on it offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one sitOrientation = avSitOrientation; // Change rotatione to the scripted one @@ -1831,13 +1853,19 @@ namespace OpenSim.Region.Framework.Scenes // if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) ) { - autopilot = false; // close enough + autopilot = false; // close enough + m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup. + Not using the part's position because returning the AV to the last known standing + position is likely to be more friendly, isn't it? */ RemoveFromPhysicalScene(); AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target } // else the autopilot will get us close } else - { // its a scripted sit + { // its a scripted sit + m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup. + I *am* using the part's position this time because we have no real idea how far away + the avatar is from the sit target. */ RemoveFromPhysicalScene(); } } -- cgit v1.1 From 69b551c51686bca58c478f517f6ccfa561ad9730 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 22 Dec 2009 03:22:33 +0100 Subject: Allow 100ms for scripts to run attach(NULL_KEY) on detach --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index f74fd5d..e875525 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -542,6 +542,18 @@ namespace OpenSim.Region.Framework.Scenes if (group.GetFromItemID() == itemID) { m_parentScene.SendAttachEvent(group.LocalId, itemID, UUID.Zero); + bool hasScripts = false; + foreach (SceneObjectPart part in group.Children) + { + if (part..Inventory.ContainsScripts()) + { + hasScripts = true; + break; + } + } + + if (hasScripts) // Allow the object to execute the attach(NULL_KEY) event + System.Threading.Thread.Sleep(100); group.DetachToInventoryPrep(); m_log.Debug("[DETACH]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); -- cgit v1.1 From 46fea747265574bb056b8d1ffa189ec3725a7abc Mon Sep 17 00:00:00 2001 From: root Date: Tue, 22 Dec 2009 03:25:09 +0100 Subject: Jumped the gun... --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index e875525..fadeaf4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -545,7 +545,7 @@ namespace OpenSim.Region.Framework.Scenes bool hasScripts = false; foreach (SceneObjectPart part in group.Children) { - if (part..Inventory.ContainsScripts()) + if (part.Inventory.ContainsScripts()) { hasScripts = true; break; -- cgit v1.1 From 49fbe0ddb429b8625682255bf0cafa9ea93d274a Mon Sep 17 00:00:00 2001 From: root Date: Tue, 22 Dec 2009 03:26:47 +0100 Subject: Should not commit without compiling --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index fadeaf4..b0fb8b3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -543,7 +543,7 @@ namespace OpenSim.Region.Framework.Scenes { m_parentScene.SendAttachEvent(group.LocalId, itemID, UUID.Zero); bool hasScripts = false; - foreach (SceneObjectPart part in group.Children) + foreach (SceneObjectPart part in group.Children.Values) { if (part.Inventory.ContainsScripts()) { -- cgit v1.1 From 0a29842caf5dbe711490b9b323ae922c418c6c30 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Tue, 22 Dec 2009 00:20:04 -0500 Subject: Include ChOdePlugin --- OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs | 58 + OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs | 1353 +++++++ .../Physics/ChOdePlugin/ODEDynamics.c_comments | 630 ++++ OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs | 673 ++++ OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 3271 +++++++++++++++++ .../ChOdePlugin/ODERayCastRequestManager.cs | 375 ++ .../Region/Physics/ChOdePlugin/OdePhysicsJoint.cs | 48 + OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs | 3865 ++++++++++++++++++++ .../Physics/ChOdePlugin/Tests/ODETestClass.cs | 122 + OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs | 98 + OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 21 +- OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs | 20 +- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 108 +- prebuild.xml | 30 + 14 files changed, 10554 insertions(+), 118 deletions(-) create mode 100644 OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs create mode 100644 OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs create mode 100644 OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.c_comments create mode 100644 OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs create mode 100644 OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs create mode 100644 OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs create mode 100644 OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs create mode 100644 OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs create mode 100644 OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs create mode 100644 OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs diff --git a/OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs b/OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs new file mode 100644 index 0000000..d65929a --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/AssemblyInfo.cs @@ -0,0 +1,58 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Reflection; +using System.Runtime.InteropServices; + +// Information about this assembly is defined by the following +// attributes. +// +// change them to the information which is associated with the assembly +// you compile. + +[assembly : AssemblyTitle("OdePlugin")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("http://opensimulator.org")] +[assembly : AssemblyProduct("OdePlugin")] +[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. + +[assembly : ComVisible(false)] + +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all values by your own or you can build default build and revision +// numbers with the '*' character (the default): + +[assembly : AssemblyVersion("0.6.5.*")] diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs new file mode 100644 index 0000000..aa0acb7 --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -0,0 +1,1353 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using OpenMetaverse; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; +using log4net; + +namespace OpenSim.Region.Physics.OdePlugin +{ + /// + /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves. + /// + + public enum dParam : int + { + LowStop = 0, + HiStop = 1, + Vel = 2, + FMax = 3, + FudgeFactor = 4, + Bounce = 5, + CFM = 6, + StopERP = 7, + StopCFM = 8, + LoStop2 = 256, + HiStop2 = 257, + Vel2 = 258, + FMax2 = 259, + StopERP2 = 7 + 256, + StopCFM2 = 8 + 256, + LoStop3 = 512, + HiStop3 = 513, + Vel3 = 514, + FMax3 = 515, + StopERP3 = 7 + 512, + StopCFM3 = 8 + 512 + } + public class OdeCharacter : PhysicsActor + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Vector3 _position; + private d.Vector3 _zeroPosition; + // private d.Matrix3 m_StandUpRotation; + private bool _zeroFlag = false; + private bool m_lastUpdateSent = false; + private Vector3 _velocity; + private Vector3 _target_velocity; + private Vector3 _acceleration; + private Vector3 m_rotationalVelocity; + private float m_mass = 80f; + public float m_density = 60f; + private bool m_pidControllerActive = true; + public float PID_D = 800.0f; + public float PID_P = 900.0f; + //private static float POSTURE_SERVO = 10000.0f; + public float CAPSULE_RADIUS = 0.37f; + public float CAPSULE_LENGTH = 2.140599f; + public float m_tensor = 3800000f; + public float heightFudgeFactor = 0.52f; + public float walkDivisor = 1.3f; + public float runDivisor = 0.8f; + private bool flying = false; + private bool m_iscolliding = false; + private bool m_iscollidingGround = false; + private bool m_wascolliding = false; + private bool m_wascollidingGround = false; + private bool m_iscollidingObj = false; + private bool m_alwaysRun = false; + private bool m_hackSentFall = false; + private bool m_hackSentFly = false; + private int m_requestedUpdateFrequency = 0; + private Vector3 m_taintPosition = Vector3.Zero; + public uint m_localID = 0; + public bool m_returnCollisions = false; + // taints and their non-tainted counterparts + public bool m_isPhysical = false; // the current physical status + public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing) + public float MinimumGroundFlightOffset = 3f; + + private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes. + private float m_tiltMagnitudeWhenProjectedOnXYPlane = 0.1131371f; // used to introduce a fixed tilt because a straight-up capsule falls through terrain, probably a bug in terrain collider + + + private float m_buoyancy = 0f; + + // private CollisionLocker ode; + + private string m_name = String.Empty; + + private bool[] m_colliderarr = new bool[11]; + private bool[] m_colliderGroundarr = new bool[11]; + + // Default we're a Character + private CollisionCategories m_collisionCategories = (CollisionCategories.Character); + + // Default, Collide with Other Geometries, spaces, bodies and characters. + private CollisionCategories m_collisionFlags = (CollisionCategories.Geom + | CollisionCategories.Space + | CollisionCategories.Body + | CollisionCategories.Character + | CollisionCategories.Land); + public IntPtr Body = IntPtr.Zero; + private OdeScene _parent_scene; + public IntPtr Shell = IntPtr.Zero; + public IntPtr Amotor = IntPtr.Zero; + public d.Mass ShellMass; + public bool collidelock = false; + + public int m_eventsubscription = 0; + private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); + + // unique UUID of this character object + public UUID m_uuid; + public bool bad = false; + + public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, CollisionLocker dode, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor) + { + m_uuid = UUID.Random(); + + if (pos.IsFinite()) + { + if (pos.Z > 9999999f) + { + pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5; + } + if (pos.Z < -90000f) + { + pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5; + } + _position = pos; + m_taintPosition.X = pos.X; + m_taintPosition.Y = pos.Y; + m_taintPosition.Z = pos.Z; + } + else + { + _position = new Vector3(((float)_parent_scene.WorldExtents.X * 0.5f), ((float)_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f); + m_taintPosition.X = _position.X; + m_taintPosition.Y = _position.Y; + m_taintPosition.Z = _position.Z; + m_log.Warn("[PHYSICS]: Got NaN Position on Character Create"); + } + + _parent_scene = parent_scene; + + PID_D = pid_d; + PID_P = pid_p; + CAPSULE_RADIUS = capsule_radius; + m_tensor = tensor; + m_density = density; + heightFudgeFactor = height_fudge_factor; + walkDivisor = walk_divisor; + runDivisor = rundivisor; + + // m_StandUpRotation = + // new d.Matrix3(0.5f, 0.7071068f, 0.5f, -0.7071068f, 0f, 0.7071068f, 0.5f, -0.7071068f, + // 0.5f); + + for (int i = 0; i < 11; i++) + { + m_colliderarr[i] = false; + } + CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f; + //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); + m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH; + + m_isPhysical = false; // current status: no ODE information exists + m_tainted_isPhysical = true; // new tainted status: need to create ODE information + + _parent_scene.AddPhysicsActorTaint(this); + + m_name = avName; + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Agent; } + set { return; } + } + + /// + /// If this is set, the avatar will move faster + /// + public override bool SetAlwaysRun + { + get { return m_alwaysRun; } + set { m_alwaysRun = value; } + } + + public override uint LocalID + { + set { m_localID = value; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { return; } + } + + public override float Buoyancy + { + get { return m_buoyancy; } + set { m_buoyancy = value; } + } + + public override bool FloatOnWater + { + set { return; } + } + + public override bool IsPhysical + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return false; } + set { return; } + } + + public override bool Flying + { + get { return flying; } + set { flying = value; } + } + + /// + /// Returns if the avatar is colliding in general. + /// This includes the ground and objects and avatar. + /// + public override bool IsColliding + { + get { return m_iscolliding; } + set + { + int i; + int truecount = 0; + int falsecount = 0; + + if (m_colliderarr.Length >= 10) + { + for (i = 0; i < 10; i++) + { + m_colliderarr[i] = m_colliderarr[i + 1]; + } + } + m_colliderarr[10] = value; + + for (i = 0; i < 11; i++) + { + if (m_colliderarr[i]) + { + truecount++; + } + else + { + falsecount++; + } + } + + // Equal truecounts and false counts means we're colliding with something. + + if (falsecount > 1.2*truecount) + { + m_iscolliding = false; + } + else + { + m_iscolliding = true; + } + if (m_wascolliding != m_iscolliding) + { + //base.SendCollisionUpdate(new CollisionEventUpdate()); + } + m_wascolliding = m_iscolliding; + } + } + + /// + /// Returns if an avatar is colliding with the ground + /// + public override bool CollidingGround + { + get { return m_iscollidingGround; } + set + { + // Collisions against the ground are not really reliable + // So, to get a consistant value we have to average the current result over time + // Currently we use 1 second = 10 calls to this. + int i; + int truecount = 0; + int falsecount = 0; + + if (m_colliderGroundarr.Length >= 10) + { + for (i = 0; i < 10; i++) + { + m_colliderGroundarr[i] = m_colliderGroundarr[i + 1]; + } + } + m_colliderGroundarr[10] = value; + + for (i = 0; i < 11; i++) + { + if (m_colliderGroundarr[i]) + { + truecount++; + } + else + { + falsecount++; + } + } + + // Equal truecounts and false counts means we're colliding with something. + + if (falsecount > 1.2*truecount) + { + m_iscollidingGround = false; + } + else + { + m_iscollidingGround = true; + } + if (m_wascollidingGround != m_iscollidingGround) + { + //base.SendCollisionUpdate(new CollisionEventUpdate()); + } + m_wascollidingGround = m_iscollidingGround; + } + } + + /// + /// Returns if the avatar is colliding with an object + /// + public override bool CollidingObj + { + get { return m_iscollidingObj; } + set + { + m_iscollidingObj = value; + if (value) + m_pidControllerActive = false; + else + m_pidControllerActive = true; + } + } + + /// + /// turn the PID controller on or off. + /// The PID Controller will turn on all by itself in many situations + /// + /// + public void SetPidStatus(bool status) + { + m_pidControllerActive = status; + } + + public override bool Stopped + { + get { return _zeroFlag; } + } + + /// + /// This 'puts' an avatar somewhere in the physics space. + /// Not really a good choice unless you 'know' it's a good + /// spot otherwise you're likely to orbit the avatar. + /// + public override Vector3 Position + { + get { return _position; } + set + { + if (Body == IntPtr.Zero || Shell == IntPtr.Zero) + { + if (value.IsFinite()) + { + if (value.Z > 9999999f) + { + value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5; + } + if (value.Z < -90000f) + { + value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5; + } + + _position.X = value.X; + _position.Y = value.Y; + _position.Z = value.Z; + + m_taintPosition.X = value.X; + m_taintPosition.Y = value.Y; + m_taintPosition.Z = value.Z; + _parent_scene.AddPhysicsActorTaint(this); + } + else + { + m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character"); + } + } + } + } + + public override Vector3 RotationalVelocity + { + get { return m_rotationalVelocity; } + set { m_rotationalVelocity = value; } + } + + /// + /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight + /// and use it to offset landings properly + /// + public override Vector3 Size + { + get { return new Vector3(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); } + set + { + if (value.IsFinite()) + { + m_pidControllerActive = true; + + Vector3 SetSize = value; + m_tainted_CAPSULE_LENGTH = (SetSize.Z*1.15f) - CAPSULE_RADIUS*2.0f; + //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); + + Velocity = Vector3.Zero; + + _parent_scene.AddPhysicsActorTaint(this); + } + else + { + m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character"); + } + } + } + + private void AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3 movementVector) + { + movementVector.Z = 0f; + float magnitude = (float)Math.Sqrt((double)(movementVector.X * movementVector.X + movementVector.Y * movementVector.Y)); + if (magnitude < 0.1f) return; + + // normalize the velocity vector + float invMagnitude = 1.0f / magnitude; + movementVector.X *= invMagnitude; + movementVector.Y *= invMagnitude; + + // if we change the capsule heading too often, the capsule can fall down + // therefore we snap movement vector to just 1 of 4 predefined directions (ne, nw, se, sw), + // meaning only 4 possible capsule tilt orientations + if (movementVector.X > 0) + { + // east + if (movementVector.Y > 0) + { + // northeast + movementVector.X = (float)Math.Sqrt(2.0); + movementVector.Y = (float)Math.Sqrt(2.0); + } + else + { + // southeast + movementVector.X = (float)Math.Sqrt(2.0); + movementVector.Y = -(float)Math.Sqrt(2.0); + } + } + else + { + // west + if (movementVector.Y > 0) + { + // northwest + movementVector.X = -(float)Math.Sqrt(2.0); + movementVector.Y = (float)Math.Sqrt(2.0); + } + else + { + // southwest + movementVector.X = -(float)Math.Sqrt(2.0); + movementVector.Y = -(float)Math.Sqrt(2.0); + } + } + + + // movementVector.Z is zero + + // calculate tilt components based on desired amount of tilt and current (snapped) heading. + // the "-" sign is to force the tilt to be OPPOSITE the direction of movement. + float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane; + float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane; + + //m_log.Debug("[PHYSICS] changing avatar tilt"); + d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, yTiltComponent); // same as lowstop + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop + } + + /// + /// This creates the Avatar's physical Surrogate at the position supplied + /// + /// + /// + /// + + // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access + // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only + // place that is safe to call this routine AvatarGeomAndBodyCreation. + private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor) + { + //CAPSULE_LENGTH = -5; + //CAPSULE_RADIUS = -5; + int dAMotorEuler = 1; + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + if (CAPSULE_LENGTH <= 0) + { + m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); + CAPSULE_LENGTH = 0.01f; + + } + + if (CAPSULE_RADIUS <= 0) + { + m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); + CAPSULE_RADIUS = 0.01f; + + } + Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); + + d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); + d.GeomSetCollideBits(Shell, (int)m_collisionFlags); + + d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH); + Body = d.BodyCreate(_parent_scene.world); + d.BodySetPosition(Body, npositionX, npositionY, npositionZ); + + _position.X = npositionX; + _position.Y = npositionY; + _position.Z = npositionZ; + + + m_taintPosition.X = npositionX; + m_taintPosition.Y = npositionY; + m_taintPosition.Z = npositionZ; + + d.BodySetMass(Body, ref ShellMass); + d.Matrix3 m_caprot; + // 90 Stand up on the cap of the capped cyllinder + if (_parent_scene.IsAvCapsuleTilted) + { + d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2)); + } + else + { + d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2)); + } + + + d.GeomSetRotation(Shell, ref m_caprot); + d.BodySetRotation(Body, ref m_caprot); + + d.GeomSetBody(Shell, Body); + + + // The purpose of the AMotor here is to keep the avatar's physical + // surrogate from rotating while moving + Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); + d.JointAttach(Amotor, Body, IntPtr.Zero); + d.JointSetAMotorMode(Amotor, dAMotorEuler); + d.JointSetAMotorNumAxes(Amotor, 3); + d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0); + d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0); + d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1); + d.JointSetAMotorAngle(Amotor, 0, 0); + d.JointSetAMotorAngle(Amotor, 1, 0); + d.JointSetAMotorAngle(Amotor, 2, 0); + + // These lowstops and high stops are effectively (no wiggle room) + if (_parent_scene.IsAvCapsuleTilted) + { + d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f); + } + else + { + #region Documentation of capsule motor LowStop and HighStop parameters + // Intentionally introduce some tilt into the capsule by setting + // the motor stops to small epsilon values. This small tilt prevents + // the capsule from falling into the terrain; a straight-up capsule + // (with -0..0 motor stops) falls into the terrain for reasons yet + // to be comprehended in their entirety. + #endregion + AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero); + d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop + } + + // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the + // capped cyllinder will fall over + d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor); + + //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); + //d.QfromR( + //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068, + // + //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); + //standupStraight(); + } + + // + /// + /// Uses the capped cyllinder volume formula to calculate the avatar's mass. + /// This may be used in calculations in the scene/scenepresence + /// + public override float Mass + { + get + { + float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH); + return m_density*AVvolume; + } + } + public override void link(PhysicsActor obj) + { + + } + + public override void delink() + { + + } + + public override void LockAngularMotion(Vector3 axis) + { + + } + +// This code is very useful. Written by DanX0r. We're just not using it right now. +// Commented out to prevent a warning. +// +// private void standupStraight() +// { +// // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air. +// // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you +// // change appearance and when you enter the simulator +// // After this routine is done, the amotor stabilizes much quicker +// d.Vector3 feet; +// d.Vector3 head; +// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet); +// d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head); +// float posture = head.Z - feet.Z; + +// // restoring force proportional to lack of posture: +// float servo = (2.5f - posture) * POSTURE_SERVO; +// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f); +// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f); +// //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); +// //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); +// } + + public override Vector3 Force + { + get { return _target_velocity; } + set { return; } + } + + public override int VehicleType + { + get { return 0; } + set { return; } + } + + public override void VehicleFloatParam(int param, float value) + { + + } + + public override void VehicleVectorParam(int param, Vector3 value) + { + + } + + public override void VehicleRotationParam(int param, Quaternion rotation) + { + + } + + public override void SetVolumeDetect(int param) + { + + } + + public override Vector3 CenterOfMass + { + get { return Vector3.Zero; } + } + + public override Vector3 GeometricCenter + { + get { return Vector3.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set { return; } + } + + public override Vector3 Velocity + { + get { + // There's a problem with Vector3.Zero! Don't Use it Here! + if (_zeroFlag) + return Vector3.Zero; + m_lastUpdateSent = false; + return _velocity; + } + set + { + if (value.IsFinite()) + { + m_pidControllerActive = true; + _target_velocity = value; + } + else + { + m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character"); + } + } + } + + public override Vector3 Torque + { + get { return Vector3.Zero; } + set { return; } + } + + public override float CollisionScore + { + get { return 0f; } + set { } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override Quaternion Orientation + { + get { return Quaternion.Identity; } + set { + //Matrix3 or = Orientation.ToRotationMatrix(); + //d.Matrix3 ord = new d.Matrix3(or.m00, or.m10, or.m20, or.m01, or.m11, or.m21, or.m02, or.m12, or.m22); + //d.BodySetRotation(Body, ref ord); + } + } + + public override Vector3 Acceleration + { + get { return _acceleration; } + } + + public void SetAcceleration(Vector3 accel) + { + m_pidControllerActive = true; + _acceleration = accel; + } + + /// + /// Adds the force supplied to the Target Velocity + /// The PID controller takes this target velocity and tries to make it a reality + /// + /// + public override void AddForce(Vector3 force, bool pushforce) + { + if (force.IsFinite()) + { + if (pushforce) + { + m_pidControllerActive = false; + force *= 100f; + doForce(force); + // If uncommented, things get pushed off world + // + // m_log.Debug("Push!"); + // _target_velocity.X += force.X; + // _target_velocity.Y += force.Y; + // _target_velocity.Z += force.Z; + } + else + { + m_pidControllerActive = true; + _target_velocity.X += force.X; + _target_velocity.Y += force.Y; + _target_velocity.Z += force.Z; + } + } + else + { + m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character"); + } + //m_lastUpdateSent = false; + } + + public override void AddAngularForce(Vector3 force, bool pushforce) + { + + } + + /// + /// After all of the forces add up with 'add force' we apply them with doForce + /// + /// + public void doForce(Vector3 force) + { + if (!collidelock) + { + d.BodyAddForce(Body, force.X, force.Y, force.Z); + //d.BodySetRotation(Body, ref m_StandUpRotation); + //standupStraight(); + + } + } + + public override void SetMomentum(Vector3 momentum) + { + } + + + /// + /// Called from Simulate + /// This is the avatar's movement control + PID Controller + /// + /// + public void Move(float timeStep, List defects) + { + // no lock; for now it's only called from within Simulate() + + // If the PID Controller isn't active then we set our force + // calculating base velocity to the current position + + if (Body == IntPtr.Zero) + return; + + if (m_pidControllerActive == false) + { + _zeroPosition = d.BodyGetPosition(Body); + } + //PidStatus = true; + + d.Vector3 localpos = d.BodyGetPosition(Body); + Vector3 localPos = new Vector3(localpos.X, localpos.Y, localpos.Z); + + if (!localPos.IsFinite()) + { + + m_log.Warn("[PHYSICS]: Avatar Position is non-finite!"); + defects.Add(this); + // _parent_scene.RemoveCharacter(this); + + // destroy avatar capsule and related ODE data + if (Amotor != IntPtr.Zero) + { + // Kill the Amotor + d.JointDestroy(Amotor); + Amotor = IntPtr.Zero; + } + + //kill the Geometry + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + + if (Body != IntPtr.Zero) + { + //kill the body + d.BodyDestroy(Body); + + Body = IntPtr.Zero; + } + + if (Shell != IntPtr.Zero) + { + d.GeomDestroy(Shell); + _parent_scene.geom_name_map.Remove(Shell); + Shell = IntPtr.Zero; + } + + return; + } + + Vector3 vec = Vector3.Zero; + d.Vector3 vel = d.BodyGetLinearVel(Body); + + float movementdivisor = 1f; + + if (!m_alwaysRun) + { + movementdivisor = walkDivisor; + } + else + { + movementdivisor = runDivisor; + } + + // if velocity is zero, use position control; otherwise, velocity control + if (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f && m_iscolliding) + { + // keep track of where we stopped. No more slippin' & slidin' + if (!_zeroFlag) + { + _zeroFlag = true; + _zeroPosition = d.BodyGetPosition(Body); + } + if (m_pidControllerActive) + { + // We only want to deactivate the PID Controller if we think we want to have our surrogate + // react to the physics scene by moving it's position. + // Avatar to Avatar collisions + // Prim to avatar collisions + + d.Vector3 pos = d.BodyGetPosition(Body); + vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); + vec.Y = (_target_velocity.Y - vel.Y)*(PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2); + if (flying) + { + vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; + } + } + //PidStatus = true; + } + else + { + m_pidControllerActive = true; + _zeroFlag = false; + if (m_iscolliding && !flying) + { + // We're standing on something + vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D); + vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D); + } + else if (m_iscolliding && flying) + { + // We're flying and colliding with something + vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*(PID_D / 16); + vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*(PID_D / 16); + } + else if (!m_iscolliding && flying) + { + // we're in mid air suspended + vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D/6); + vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D/6); + } + + if (m_iscolliding && !flying && _target_velocity.Z > 0.0f) + { + // We're colliding with something and we're not flying but we're moving + // This means we're walking or running. + d.Vector3 pos = d.BodyGetPosition(Body); + vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P; + if (_target_velocity.X > 0) + { + vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; + } + if (_target_velocity.Y > 0) + { + vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; + } + } + else if (!m_iscolliding && !flying) + { + // we're not colliding and we're not flying so that means we're falling! + // m_iscolliding includes collisions with the ground. + + // d.Vector3 pos = d.BodyGetPosition(Body); + if (_target_velocity.X > 0) + { + vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; + } + if (_target_velocity.Y > 0) + { + vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; + } + } + + if (flying) + { + vec.Z = (_target_velocity.Z - vel.Z) * (PID_D); + } + } + if (flying) + { + vec.Z += ((-1 * _parent_scene.gravityz)*m_mass); + + //Added for auto fly height. Kitto Flora + //d.Vector3 pos = d.BodyGetPosition(Body); + float target_altitude = _parent_scene.GetTerrainHeightAtXY(_position.X, _position.Y) + MinimumGroundFlightOffset; + + if (_position.Z < target_altitude) + { + vec.Z += (target_altitude - _position.Z) * PID_P * 5.0f; + } + // end add Kitto Flora + } + if (vec.IsFinite()) + { + doForce(vec); + if (!_zeroFlag) + { + AlignAvatarTiltWithCurrentDirectionOfMovement(vec); + } + } + else + { + m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()"); + m_log.Warn("[PHYSICS]: Avatar Position is non-finite!"); + defects.Add(this); + // _parent_scene.RemoveCharacter(this); + // destroy avatar capsule and related ODE data + if (Amotor != IntPtr.Zero) + { + // Kill the Amotor + d.JointDestroy(Amotor); + Amotor = IntPtr.Zero; + } + //kill the Geometry + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + + if (Body != IntPtr.Zero) + { + //kill the body + d.BodyDestroy(Body); + + Body = IntPtr.Zero; + } + + if (Shell != IntPtr.Zero) + { + d.GeomDestroy(Shell); + _parent_scene.geom_name_map.Remove(Shell); + Shell = IntPtr.Zero; + } + } + } + + /// + /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence. + /// + public void UpdatePositionAndVelocity() + { + // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! + d.Vector3 vec; + try + { + vec = d.BodyGetPosition(Body); + } + catch (NullReferenceException) + { + bad = true; + _parent_scene.BadCharacter(this); + vec = new d.Vector3(_position.X, _position.Y, _position.Z); + base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem! + m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid); + } + + + // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) + if (vec.X < 0.0f) vec.X = 0.0f; + if (vec.Y < 0.0f) vec.Y = 0.0f; + if (vec.X > (int)_parent_scene.WorldExtents.X - 0.05f) vec.X = (int)_parent_scene.WorldExtents.X - 0.05f; + if (vec.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) vec.Y = (int)_parent_scene.WorldExtents.Y - 0.05f; + + _position.X = vec.X; + _position.Y = vec.Y; + _position.Z = vec.Z; + + // Did we move last? = zeroflag + // This helps keep us from sliding all over + + if (_zeroFlag) + { + _velocity.X = 0.0f; + _velocity.Y = 0.0f; + _velocity.Z = 0.0f; + + // Did we send out the 'stopped' message? + if (!m_lastUpdateSent) + { + m_lastUpdateSent = true; + //base.RequestPhysicsterseUpdate(); + + } + } + else + { + m_lastUpdateSent = false; + try + { + vec = d.BodyGetLinearVel(Body); + } + catch (NullReferenceException) + { + vec.X = _velocity.X; + vec.Y = _velocity.Y; + vec.Z = _velocity.Z; + } + _velocity.X = (vec.X); + _velocity.Y = (vec.Y); + + _velocity.Z = (vec.Z); + + if (_velocity.Z < -6 && !m_hackSentFall) + { + m_hackSentFall = true; + m_pidControllerActive = false; + } + else if (flying && !m_hackSentFly) + { + //m_hackSentFly = true; + //base.SendCollisionUpdate(new CollisionEventUpdate()); + } + else + { + m_hackSentFly = false; + m_hackSentFall = false; + } + } + } + + /// + /// Cleanup the things we use in the scene. + /// + public void Destroy() + { + m_tainted_isPhysical = false; + _parent_scene.AddPhysicsActorTaint(this); + } + + public override void CrossingFailure() + { + } + + public override Vector3 PIDTarget { set { return; } } + public override bool PIDActive { set { return; } } + public override float PIDTau { set { return; } } + + public override float PIDHoverHeight { set { return; } } + public override bool PIDHoverActive { set { return; } } + public override PIDHoverType PIDHoverType { set { return; } } + public override float PIDHoverTau { set { return; } } + + public override Quaternion APIDTarget{ set { return; } } + + public override bool APIDActive{ set { return; } } + + public override float APIDStrength{ set { return; } } + + public override float APIDDamping{ set { return; } } + + + public override void SubscribeEvents(int ms) + { + m_requestedUpdateFrequency = ms; + m_eventsubscription = ms; + _parent_scene.addCollisionEventReporting(this); + } + public override void UnSubscribeEvents() + { + _parent_scene.remCollisionEventReporting(this); + m_requestedUpdateFrequency = 0; + m_eventsubscription = 0; + } + public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) + { + if (m_eventsubscription > 0) + { + CollisionEventsThisFrame.addCollider(CollidedWith, contact); + } + } + + public void SendCollisions() + { + if (m_eventsubscription > m_requestedUpdateFrequency) + { + if (CollisionEventsThisFrame != null) + { + base.SendCollisionUpdate(CollisionEventsThisFrame); + } + CollisionEventsThisFrame = new CollisionEventUpdate(); + m_eventsubscription = 0; + } + } + public override bool SubscribedEvents() + { + if (m_eventsubscription > 0) + return true; + return false; + } + + public void ProcessTaints(float timestep) + { + + if (m_tainted_isPhysical != m_isPhysical) + { + if (m_tainted_isPhysical) + { + // Create avatar capsule and related ODE data + if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) + { + m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - " + + (Shell!=IntPtr.Zero ? "Shell ":"") + + (Body!=IntPtr.Zero ? "Body ":"") + + (Amotor!=IntPtr.Zero ? "Amotor ":"")); + } + AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor); + + _parent_scene.geom_name_map[Shell] = m_name; + _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; + _parent_scene.AddCharacter(this); + } + else + { + _parent_scene.RemoveCharacter(this); + // destroy avatar capsule and related ODE data + if (Amotor != IntPtr.Zero) + { + // Kill the Amotor + d.JointDestroy(Amotor); + Amotor = IntPtr.Zero; + } + //kill the Geometry + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + + if (Body != IntPtr.Zero) + { + //kill the body + d.BodyDestroy(Body); + + Body = IntPtr.Zero; + } + + if (Shell != IntPtr.Zero) + { + d.GeomDestroy(Shell); + _parent_scene.geom_name_map.Remove(Shell); + Shell = IntPtr.Zero; + } + + } + + m_isPhysical = m_tainted_isPhysical; + } + + if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH) + { + if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero) + { + + m_pidControllerActive = true; + // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate() + d.JointDestroy(Amotor); + float prevCapsule = CAPSULE_LENGTH; + CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; + //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); + d.BodyDestroy(Body); + d.GeomDestroy(Shell); + AvatarGeomAndBodyCreation(_position.X, _position.Y, + _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); + Velocity = Vector3.Zero; + + _parent_scene.geom_name_map[Shell] = m_name; + _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; + } + else + { + m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - " + + (Shell==IntPtr.Zero ? "Shell ":"") + + (Body==IntPtr.Zero ? "Body ":"") + + (Amotor==IntPtr.Zero ? "Amotor ":"")); + } + } + + if (!m_taintPosition.ApproxEquals(_position, 0.05f)) + { + if (Body != IntPtr.Zero) + { + d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z); + + _position.X = m_taintPosition.X; + _position.Y = m_taintPosition.Y; + _position.Z = m_taintPosition.Z; + } + } + + } + + internal void AddCollisionFrameTime(int p) + { + // protect it from overflow crashing + if (m_eventsubscription + p >= int.MaxValue) + m_eventsubscription = 0; + m_eventsubscription += p; + } + } +} diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.c_comments b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.c_comments new file mode 100644 index 0000000..1060aa6 --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.c_comments @@ -0,0 +1,630 @@ +/* + * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces + * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: + * ODEPrim.cs contains methods dealing with Prim editing, Prim + * characteristics and Kinetic motion. + * ODEDynamics.cs contains methods dealing with Prim Physical motion + * (dynamics) and the associated settings. Old Linear and angular + * motors for dynamic motion have been replace with MoveLinear() + * and MoveAngular(); 'Physical' is used only to switch ODE dynamic + * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to + * switch between 'VEHICLE' parameter use and general dynamics + * settings use. + * + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using log4net; +using OpenMetaverse; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.OdePlugin +{ + public class ODEDynamics + { + public Vehicle Type + { + get { return m_type; } + } + + public IntPtr Body + { + get { return m_body; } + } + + private int frcount = 0; // Used to limit dynamics debug output to + // every 100th frame + + // private OdeScene m_parentScene = null; + private IntPtr m_body = IntPtr.Zero; + private IntPtr m_jointGroup = IntPtr.Zero; + private IntPtr m_aMotor = IntPtr.Zero; + + + // Vehicle properties + private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind + // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier + private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: + // HOVER_TERRAIN_ONLY + // HOVER_GLOBAL_HEIGHT + // NO_DEFLECTION_UP + // HOVER_WATER_ONLY + // HOVER_UP_ONLY + // LIMIT_MOTOR_UP + // LIMIT_ROLL_ONLY + + // Linear properties + private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time + private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL + private Vector3 m_dir = Vector3.Zero; // velocity applied to body + private Vector3 m_linearFrictionTimescale = Vector3.Zero; + private float m_linearMotorDecayTimescale = 0; + private float m_linearMotorTimescale = 0; + private Vector3 m_lastLinearVelocityVector = Vector3.Zero; + // private bool m_LinearMotorSetLastFrame = false; + // private Vector3 m_linearMotorOffset = Vector3.Zero; + + //Angular properties + private Vector3 m_angularMotorDirection = Vector3.Zero; + private Vector3 m_angularMotorDirectionLASTSET = Vector3.Zero; + private Vector3 m_angularFrictionTimescale = Vector3.Zero; + private float m_angularMotorDecayTimescale = 0; + private float m_angularMotorTimescale = 0; + private Vector3 m_lastAngularVelocityVector = Vector3.Zero; + + //Deflection properties + // private float m_angularDeflectionEfficiency = 0; + // private float m_angularDeflectionTimescale = 0; + // private float m_linearDeflectionEfficiency = 0; + // private float m_linearDeflectionTimescale = 0; + + //Banking properties + // private float m_bankingEfficiency = 0; + // private float m_bankingMix = 0; + // private float m_bankingTimescale = 0; + + //Hover and Buoyancy properties + private float m_VhoverHeight = 0f; + private float m_VhoverEfficiency = 0f; + private float m_VhoverTimescale = 0f; + private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height + private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. + // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) + // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. + // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. + + //Attractor properties + private float m_verticalAttractionEfficiency = 0; + private float m_verticalAttractionTimescale = 0; + + + + + + internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) + { + switch (pParam) + { + case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionEfficiency = pValue; + break; + case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionTimescale = pValue; + break; + case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorDecayTimescale = pValue; + break; + case Vehicle.ANGULAR_MOTOR_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorTimescale = pValue; + break; + case Vehicle.BANKING_EFFICIENCY: + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingEfficiency = pValue; + break; + case Vehicle.BANKING_MIX: + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingMix = pValue; + break; + case Vehicle.BANKING_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingTimescale = pValue; + break; + case Vehicle.BUOYANCY: + if (pValue < -1f) pValue = -1f; + if (pValue > 1f) pValue = 1f; + m_VehicleBuoyancy = pValue; + break; + case Vehicle.HOVER_EFFICIENCY: + if (pValue < 0f) pValue = 0f; + if (pValue > 1f) pValue = 1f; + m_VhoverEfficiency = pValue; + break; + case Vehicle.HOVER_HEIGHT: + m_VhoverHeight = pValue; + break; + case Vehicle.HOVER_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_VhoverTimescale = pValue; + break; + case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionEfficiency = pValue; + break; + case Vehicle.LINEAR_DEFLECTION_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionTimescale = pValue; + break; + case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorDecayTimescale = pValue; + break; + case Vehicle.LINEAR_MOTOR_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorTimescale = pValue; + break; + case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: + if (pValue < 0.0f) pValue = 0.0f; + if (pValue > 1.0f) pValue = 1.0f; + m_verticalAttractionEfficiency = pValue; + break; + case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_verticalAttractionTimescale = pValue; + break; + + // These are vector properties but the engine lets you use a single float value to + // set all of the components to the same value + case Vehicle.ANGULAR_FRICTION_TIMESCALE: + m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); + break; + case Vehicle.ANGULAR_MOTOR_DIRECTION: + m_angularMotorDirection = new Vector3(pValue, pValue, pValue); + m_angularMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); + break; + case Vehicle.LINEAR_FRICTION_TIMESCALE: + m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); + break; + case Vehicle.LINEAR_MOTOR_DIRECTION: + m_linearMotorDirection = new Vector3(pValue, pValue, pValue); + m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); + break; + case Vehicle.LINEAR_MOTOR_OFFSET: + // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); + break; + + } + + }//end ProcessFloatVehicleParam + + internal void ProcessVectorVehicleParam(Vehicle pParam, PhysicsVector pValue) + { + switch (pParam) + { + case Vehicle.ANGULAR_FRICTION_TIMESCALE: + m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + case Vehicle.ANGULAR_MOTOR_DIRECTION: + m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); + m_angularMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + case Vehicle.LINEAR_FRICTION_TIMESCALE: + m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + case Vehicle.LINEAR_MOTOR_DIRECTION: + m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); + m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + case Vehicle.LINEAR_MOTOR_OFFSET: + // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + } + + }//end ProcessVectorVehicleParam + + internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) + { + switch (pParam) + { + case Vehicle.REFERENCE_FRAME: + // m_referenceFrame = pValue; + break; + } + + }//end ProcessRotationVehicleParam + + internal void ProcessTypeChange(Vehicle pType) + { +Console.WriteLine("ProcessTypeChange to " + pType); + + // Set Defaults For Type + m_type = pType; + switch (pType) + { + case Vehicle.TYPE_SLED: + m_linearFrictionTimescale = new Vector3(30, 1, 1000); + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 1000; + m_linearMotorDecayTimescale = 120; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 1000; + m_angularMotorDecayTimescale = 120; + m_VhoverHeight = 0; + m_VhoverEfficiency = 1; + m_VhoverTimescale = 10; + m_VehicleBuoyancy = 0; + // m_linearDeflectionEfficiency = 1; + // m_linearDeflectionTimescale = 1; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 1000; + // m_bankingEfficiency = 0; + // m_bankingMix = 1; + // m_bankingTimescale = 10; + // m_referenceFrame = Quaternion.Identity; + m_flags &= + ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + break; + case Vehicle.TYPE_CAR: + m_linearFrictionTimescale = new Vector3(100, 2, 1000); + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 1; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 1; + m_angularMotorDecayTimescale = 0.8f; + m_VhoverHeight = 0; + m_VhoverEfficiency = 0; + m_VhoverTimescale = 1000; + m_VehicleBuoyancy = 0; + // // m_linearDeflectionEfficiency = 1; + // // m_linearDeflectionTimescale = 2; + // // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 10; + m_verticalAttractionEfficiency = 1; + m_verticalAttractionTimescale = 10; + // m_bankingEfficiency = -0.2f; + // m_bankingMix = 1; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY | + VehicleFlag.LIMIT_MOTOR_UP); + break; + case Vehicle.TYPE_BOAT: + m_linearFrictionTimescale = new Vector3(10, 3, 2); + m_angularFrictionTimescale = new Vector3(10,10,10); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 5; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 4; + m_angularMotorDecayTimescale = 4; + m_VhoverHeight = 0; + m_VhoverEfficiency = 0.5f; + m_VhoverTimescale = 2; + m_VehicleBuoyancy = 1; + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 0.5f; + // m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 0.5f; + m_verticalAttractionTimescale = 5; + // m_bankingEfficiency = -0.3f; + // m_bankingMix = 0.8f; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | + VehicleFlag.LIMIT_MOTOR_UP); + break; + case Vehicle.TYPE_AIRPLANE: + m_linearFrictionTimescale = new Vector3(200, 10, 5); + m_angularFrictionTimescale = new Vector3(20, 20, 20); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 2; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 4; + m_angularMotorDecayTimescale = 4; + m_VhoverHeight = 0; + m_VhoverEfficiency = 0.5f; + m_VhoverTimescale = 1000; + m_VehicleBuoyancy = 0; + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 2; + m_verticalAttractionEfficiency = 0.9f; + m_verticalAttractionTimescale = 2; + // m_bankingEfficiency = 1; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 2; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); + break; + case Vehicle.TYPE_BALLOON: + m_linearFrictionTimescale = new Vector3(5, 5, 5); + m_angularFrictionTimescale = new Vector3(10, 10, 10); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 5; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 6; + m_angularMotorDecayTimescale = 10; + m_VhoverHeight = 5; + m_VhoverEfficiency = 0.8f; + m_VhoverTimescale = 10; + m_VehicleBuoyancy = 1; + // m_linearDeflectionEfficiency = 0; + // m_linearDeflectionTimescale = 5; + // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 1; + m_verticalAttractionTimescale = 1000; + // m_bankingEfficiency = 0; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 5; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + break; + + } + }//end SetDefaultsForType + + internal void Enable(IntPtr pBody, OdeScene pParentScene) + { +//Console.WriteLine("Enable m_type=" + m_type + " m_VehicleBuoyancy=" + m_VehicleBuoyancy); + if (m_type == Vehicle.TYPE_NONE) + return; + + m_body = pBody; + //KF: This used to set up the linear and angular joints + } + + internal void Step(float pTimestep, OdeScene pParentScene) + { + if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) + return; + frcount++; // used to limit debug comment output + if (frcount > 100) + frcount = 0; + + MoveLinear(pTimestep, pParentScene); + MoveAngular(pTimestep); + }// end Step + + private void MoveLinear(float pTimestep, OdeScene _pParentScene) + { + if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant + { + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + + // add drive to body + Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); + m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? + + // This will work temporarily, but we really need to compare speed on an axis + // KF: Limit body velocity to applied velocity? + if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) + m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; + if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) + m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; + if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) + m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; + + // decay applied velocity + Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); + //Console.WriteLine("decay: " + decayfraction); + m_linearMotorDirection -= m_linearMotorDirection * decayfraction; + //Console.WriteLine("actual: " + m_linearMotorDirection); + } + else + { // requested is not significant + // if what remains of applied is small, zero it. + if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) + m_lastLinearVelocityVector = Vector3.Zero; + } + + + // convert requested object velocity to world-referenced vector + m_dir = m_lastLinearVelocityVector; + d.Quaternion rot = d.BodyGetQuaternion(Body); + Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object + m_dir *= rotq; // apply obj rotation to velocity vector + + // add Gravity andBuoyancy + // KF: So far I have found no good method to combine a script-requested + // .Z velocity and gravity. Therefore only 0g will used script-requested + // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. + Vector3 grav = Vector3.Zero; + if(m_VehicleBuoyancy < 1.0f) + { + // There is some gravity, make a gravity force vector + // that is applied after object velocity. + d.Mass objMass; + d.BodyGetMass(Body, out objMass); + // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; + grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); + // Preserve the current Z velocity + d.Vector3 vel_now = d.BodyGetLinearVel(Body); + m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity + } // else its 1.0, no gravity. + + // Check if hovering + if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) + { + // We should hover, get the target height + d.Vector3 pos = d.BodyGetPosition(Body); + if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY) + { + m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; + } + else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY) + { + m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; + } + else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT) + { + m_VhoverTargetHeight = m_VhoverHeight; + } + + if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY) + { + // If body is aready heigher, use its height as target height + if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; + } + +// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped +// m_VhoverTimescale = 0f; // time to acheive height +// pTimestep is time since last frame,in secs + float herr0 = pos.Z - m_VhoverTargetHeight; +//if(frcount == 0) Console.WriteLine("herr0=" + herr0); + // Replace Vertical speed with correction figure if significant + if(Math.Abs(herr0) > 0.01f ) + { + d.Mass objMass; + d.BodyGetMass(Body, out objMass); + m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale); + // m_VhoverEfficiency is not yet implemented + } + else + { + m_dir.Z = 0f; + } + } + + // Apply velocity + d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z); +//if(frcount == 0) Console.WriteLine("Move " + Body + ":"+ m_dir.X + " " + m_dir.Y + " " + m_dir.Z); + // apply gravity force + d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); +//if(frcount == 0) Console.WriteLine("Force " + Body + ":" + grav.X + " " + grav.Y + " " + grav.Z); + + + // apply friction + Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); + m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; + } // end MoveLinear() + + private void MoveAngular(float pTimestep) + { + + // m_angularMotorDirection is the latest value from the script, and is decayed here + // m_angularMotorDirectionLASTSET is the latest value from the script + // m_lastAngularVelocityVector is what is being applied to the Body, varied up and down here + + if (!m_angularMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) + { + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + // ramp up to new value + Vector3 addAmount = m_angularMotorDirection / (m_angularMotorTimescale / pTimestep); + m_lastAngularVelocityVector += (addAmount * 10f); +//if(frcount == 0) Console.WriteLine("add: " + addAmount); + + // limit applied value to what was set by script + // This will work temporarily, but we really need to compare speed on an axis + if (Math.Abs(m_lastAngularVelocityVector.X) > Math.Abs(m_angularMotorDirectionLASTSET.X)) + m_lastAngularVelocityVector.X = m_angularMotorDirectionLASTSET.X; + if (Math.Abs(m_lastAngularVelocityVector.Y) > Math.Abs(m_angularMotorDirectionLASTSET.Y)) + m_lastAngularVelocityVector.Y = m_angularMotorDirectionLASTSET.Y; + if (Math.Abs(m_lastAngularVelocityVector.Z) > Math.Abs(m_angularMotorDirectionLASTSET.Z)) + m_lastAngularVelocityVector.Z = m_angularMotorDirectionLASTSET.Z; + + // decay the requested value + Vector3 decayfraction = ((Vector3.One / (m_angularMotorDecayTimescale / pTimestep))); + //Console.WriteLine("decay: " + decayfraction); + m_angularMotorDirection -= m_angularMotorDirection * decayfraction; + //Console.WriteLine("actual: " + m_linearMotorDirection); + } + // KF: m_lastAngularVelocityVector is rotational speed in rad/sec ? + + // Vertical attractor section + +// d.Mass objMass; +// d.BodyGetMass(Body, out objMass); +// float servo = 100f * objMass.mass * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep); + float servo = 0.1f * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep); + // get present body rotation + d.Quaternion rot = d.BodyGetQuaternion(Body); + Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); + // make a vector pointing up + Vector3 verterr = Vector3.Zero; + verterr.Z = 1.0f; + // rotate it to Body Angle + verterr = verterr * rotq; + // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. + // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go + // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. + if (verterr.Z < 0.0f) + { + verterr.X = 2.0f - verterr.X; + verterr.Y = 2.0f - verterr.Y; + } + // Error is 0 (no error) to +/- 2 (max error) + // scale it by servo + verterr = verterr * servo; + + // rotate to object frame + // verterr = verterr * rotq; + + // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so + // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. + m_lastAngularVelocityVector.X += verterr.Y; + m_lastAngularVelocityVector.Y -= verterr.X; +/* +if(frcount == 0) + { +// Console.WriteLine("AngleMotor " + m_lastAngularVelocityVector); + Console.WriteLine(String.Format("VA Body:{0} servo:{1} err:<{2},{3},{4}> VAE:{5}", + Body, servo, verterr.X, verterr.Y, verterr.Z, m_verticalAttractionEfficiency)); + } + */ + d.BodySetAngularVel (Body, m_lastAngularVelocityVector.X, m_lastAngularVelocityVector.Y, m_lastAngularVelocityVector.Z); + // apply friction + Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); + m_lastAngularVelocityVector -= m_lastAngularVelocityVector * decayamount; + + } //end MoveAngular + } +} diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs new file mode 100644 index 0000000..78b15be --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs @@ -0,0 +1,673 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces + * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: + * ODEPrim.cs contains methods dealing with Prim editing, Prim + * characteristics and Kinetic motion. + * ODEDynamics.cs contains methods dealing with Prim Physical motion + * (dynamics) and the associated settings. Old Linear and angular + * motors for dynamic motion have been replace with MoveLinear() + * and MoveAngular(); 'Physical' is used only to switch ODE dynamic + * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to + * switch between 'VEHICLE' parameter use and general dynamics + * settings use. + * + */ + +/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces + * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: + * ODEPrim.cs contains methods dealing with Prim editing, Prim + * characteristics and Kinetic motion. + * ODEDynamics.cs contains methods dealing with Prim Physical motion + * (dynamics) and the associated settings. Old Linear and angular + * motors for dynamic motion have been replace with MoveLinear() + * and MoveAngular(); 'Physical' is used only to switch ODE dynamic + * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to + * switch between 'VEHICLE' parameter use and general dynamics + * settings use. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using log4net; +using OpenMetaverse; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.OdePlugin +{ + public class ODEDynamics + { + public Vehicle Type + { + get { return m_type; } + } + + public IntPtr Body + { + get { return m_body; } + } + + private int frcount = 0; // Used to limit dynamics debug output to + // every 100th frame + + // private OdeScene m_parentScene = null; + private IntPtr m_body = IntPtr.Zero; +// private IntPtr m_jointGroup = IntPtr.Zero; +// private IntPtr m_aMotor = IntPtr.Zero; + + + // Vehicle properties + private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind + // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier + private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: + // HOVER_TERRAIN_ONLY + // HOVER_GLOBAL_HEIGHT + // NO_DEFLECTION_UP + // HOVER_WATER_ONLY + // HOVER_UP_ONLY + // LIMIT_MOTOR_UP + // LIMIT_ROLL_ONLY + + // Linear properties + private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time + private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL + private Vector3 m_dir = Vector3.Zero; // velocity applied to body + private Vector3 m_linearFrictionTimescale = Vector3.Zero; + private float m_linearMotorDecayTimescale = 0; + private float m_linearMotorTimescale = 0; + private Vector3 m_lastLinearVelocityVector = Vector3.Zero; + // private bool m_LinearMotorSetLastFrame = false; + // private Vector3 m_linearMotorOffset = Vector3.Zero; + + //Angular properties + private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor + private int m_angularMotorApply = 0; // application frame counter + private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity + private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate + private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate + private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate + private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body + // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body + + //Deflection properties + // private float m_angularDeflectionEfficiency = 0; + // private float m_angularDeflectionTimescale = 0; + // private float m_linearDeflectionEfficiency = 0; + // private float m_linearDeflectionTimescale = 0; + + //Banking properties + // private float m_bankingEfficiency = 0; + // private float m_bankingMix = 0; + // private float m_bankingTimescale = 0; + + //Hover and Buoyancy properties + private float m_VhoverHeight = 0f; +// private float m_VhoverEfficiency = 0f; + private float m_VhoverTimescale = 0f; + private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height + private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle. + // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) + // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. + // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. + + //Attractor properties + private float m_verticalAttractionEfficiency = 1.0f; // damped + private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. + + + + + + internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) + { + switch (pParam) + { + case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionEfficiency = pValue; + break; + case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionTimescale = pValue; + break; + case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorDecayTimescale = pValue; + break; + case Vehicle.ANGULAR_MOTOR_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorTimescale = pValue; + break; + case Vehicle.BANKING_EFFICIENCY: + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingEfficiency = pValue; + break; + case Vehicle.BANKING_MIX: + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingMix = pValue; + break; + case Vehicle.BANKING_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingTimescale = pValue; + break; + case Vehicle.BUOYANCY: + if (pValue < -1f) pValue = -1f; + if (pValue > 1f) pValue = 1f; + m_VehicleBuoyancy = pValue; + break; +// case Vehicle.HOVER_EFFICIENCY: +// if (pValue < 0f) pValue = 0f; +// if (pValue > 1f) pValue = 1f; +// m_VhoverEfficiency = pValue; +// break; + case Vehicle.HOVER_HEIGHT: + m_VhoverHeight = pValue; + break; + case Vehicle.HOVER_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_VhoverTimescale = pValue; + break; + case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionEfficiency = pValue; + break; + case Vehicle.LINEAR_DEFLECTION_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionTimescale = pValue; + break; + case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorDecayTimescale = pValue; + break; + case Vehicle.LINEAR_MOTOR_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorTimescale = pValue; + break; + case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: + if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable + if (pValue > 1.0f) pValue = 1.0f; + m_verticalAttractionEfficiency = pValue; + break; + case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_verticalAttractionTimescale = pValue; + break; + + // These are vector properties but the engine lets you use a single float value to + // set all of the components to the same value + case Vehicle.ANGULAR_FRICTION_TIMESCALE: + m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); + break; + case Vehicle.ANGULAR_MOTOR_DIRECTION: + m_angularMotorDirection = new Vector3(pValue, pValue, pValue); + m_angularMotorApply = 10; + break; + case Vehicle.LINEAR_FRICTION_TIMESCALE: + m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); + break; + case Vehicle.LINEAR_MOTOR_DIRECTION: + m_linearMotorDirection = new Vector3(pValue, pValue, pValue); + m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); + break; + case Vehicle.LINEAR_MOTOR_OFFSET: + // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); + break; + + } + + }//end ProcessFloatVehicleParam + + internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) + { + switch (pParam) + { + case Vehicle.ANGULAR_FRICTION_TIMESCALE: + m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + case Vehicle.ANGULAR_MOTOR_DIRECTION: + m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); + // Limit requested angular speed to 2 rps= 4 pi rads/sec + if(m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; + if(m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; + if(m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; + if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; + if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; + if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; + m_angularMotorApply = 10; + break; + case Vehicle.LINEAR_FRICTION_TIMESCALE: + m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + case Vehicle.LINEAR_MOTOR_DIRECTION: + m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); + m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + case Vehicle.LINEAR_MOTOR_OFFSET: + // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + } + + }//end ProcessVectorVehicleParam + + internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) + { + switch (pParam) + { + case Vehicle.REFERENCE_FRAME: + // m_referenceFrame = pValue; + break; + } + + }//end ProcessRotationVehicleParam + + internal void ProcessTypeChange(Vehicle pType) + { + // Set Defaults For Type + m_type = pType; + switch (pType) + { + case Vehicle.TYPE_SLED: + m_linearFrictionTimescale = new Vector3(30, 1, 1000); + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 1000; + m_linearMotorDecayTimescale = 120; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 1000; + m_angularMotorDecayTimescale = 120; + m_VhoverHeight = 0; +// m_VhoverEfficiency = 1; + m_VhoverTimescale = 10; + m_VehicleBuoyancy = 0; + // m_linearDeflectionEfficiency = 1; + // m_linearDeflectionTimescale = 1; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 1000; + // m_bankingEfficiency = 0; + // m_bankingMix = 1; + // m_bankingTimescale = 10; + // m_referenceFrame = Quaternion.Identity; + m_flags &= + ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + break; + case Vehicle.TYPE_CAR: + m_linearFrictionTimescale = new Vector3(100, 2, 1000); + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 1; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 1; + m_angularMotorDecayTimescale = 0.8f; + m_VhoverHeight = 0; +// m_VhoverEfficiency = 0; + m_VhoverTimescale = 1000; + m_VehicleBuoyancy = 0; + // // m_linearDeflectionEfficiency = 1; + // // m_linearDeflectionTimescale = 2; + // // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 10; + m_verticalAttractionEfficiency = 1f; + m_verticalAttractionTimescale = 10f; + // m_bankingEfficiency = -0.2f; + // m_bankingMix = 1; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY | + VehicleFlag.LIMIT_MOTOR_UP); + break; + case Vehicle.TYPE_BOAT: + m_linearFrictionTimescale = new Vector3(10, 3, 2); + m_angularFrictionTimescale = new Vector3(10,10,10); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 5; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 4; + m_angularMotorDecayTimescale = 4; + m_VhoverHeight = 0; +// m_VhoverEfficiency = 0.5f; + m_VhoverTimescale = 2; + m_VehicleBuoyancy = 1; + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 0.5f; + // m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 0.5f; + m_verticalAttractionTimescale = 5f; + // m_bankingEfficiency = -0.3f; + // m_bankingMix = 0.8f; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | + VehicleFlag.LIMIT_MOTOR_UP); + break; + case Vehicle.TYPE_AIRPLANE: + m_linearFrictionTimescale = new Vector3(200, 10, 5); + m_angularFrictionTimescale = new Vector3(20, 20, 20); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 2; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 4; + m_angularMotorDecayTimescale = 4; + m_VhoverHeight = 0; +// m_VhoverEfficiency = 0.5f; + m_VhoverTimescale = 1000; + m_VehicleBuoyancy = 0; + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 2; + m_verticalAttractionEfficiency = 0.9f; + m_verticalAttractionTimescale = 2f; + // m_bankingEfficiency = 1; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 2; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); + break; + case Vehicle.TYPE_BALLOON: + m_linearFrictionTimescale = new Vector3(5, 5, 5); + m_angularFrictionTimescale = new Vector3(10, 10, 10); + m_linearMotorDirection = Vector3.Zero; + m_linearMotorTimescale = 5; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorTimescale = 6; + m_angularMotorDecayTimescale = 10; + m_VhoverHeight = 5; +// m_VhoverEfficiency = 0.8f; + m_VhoverTimescale = 10; + m_VehicleBuoyancy = 1; + // m_linearDeflectionEfficiency = 0; + // m_linearDeflectionTimescale = 5; + // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 1f; + m_verticalAttractionTimescale = 100f; + // m_bankingEfficiency = 0; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 5; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + break; + + } + }//end SetDefaultsForType + + internal void Enable(IntPtr pBody, OdeScene pParentScene) + { + if (m_type == Vehicle.TYPE_NONE) + return; + + m_body = pBody; + } + + internal void Step(float pTimestep, OdeScene pParentScene) + { + if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) + return; + frcount++; // used to limit debug comment output + if (frcount > 100) + frcount = 0; + + MoveLinear(pTimestep, pParentScene); + MoveAngular(pTimestep); + }// end Step + + private void MoveLinear(float pTimestep, OdeScene _pParentScene) + { + if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant + { + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + + // add drive to body + Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); + m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? + + // This will work temporarily, but we really need to compare speed on an axis + // KF: Limit body velocity to applied velocity? + if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) + m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; + if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) + m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; + if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) + m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; + + // decay applied velocity + Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); + //Console.WriteLine("decay: " + decayfraction); + m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; + //Console.WriteLine("actual: " + m_linearMotorDirection); + } + else + { // requested is not significant + // if what remains of applied is small, zero it. + if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) + m_lastLinearVelocityVector = Vector3.Zero; + } + + + // convert requested object velocity to world-referenced vector + m_dir = m_lastLinearVelocityVector; + d.Quaternion rot = d.BodyGetQuaternion(Body); + Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object + m_dir *= rotq; // apply obj rotation to velocity vector + + // add Gravity and Buoyancy + // KF: So far I have found no good method to combine a script-requested + // .Z velocity and gravity. Therefore only 0g will used script-requested + // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. + Vector3 grav = Vector3.Zero; + if(m_VehicleBuoyancy < 1.0f) + { + // There is some gravity, make a gravity force vector + // that is applied after object velocity. + d.Mass objMass; + d.BodyGetMass(Body, out objMass); + // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; + grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); + // Preserve the current Z velocity + d.Vector3 vel_now = d.BodyGetLinearVel(Body); + m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity + } // else its 1.0, no gravity. + + // Check if hovering + if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) + { + // We should hover, get the target height + d.Vector3 pos = d.BodyGetPosition(Body); + if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY) + { + m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; + } + else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY) + { + m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; + } + else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT) + { + m_VhoverTargetHeight = m_VhoverHeight; + } + + if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY) + { + // If body is aready heigher, use its height as target height + if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; + } + +// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped +// m_VhoverTimescale = 0f; // time to acheive height +// pTimestep is time since last frame,in secs + float herr0 = pos.Z - m_VhoverTargetHeight; + // Replace Vertical speed with correction figure if significant + if(Math.Abs(herr0) > 0.01f ) + { + d.Mass objMass; + d.BodyGetMass(Body, out objMass); + m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale); + //KF: m_VhoverEfficiency is not yet implemented + } + else + { + m_dir.Z = 0f; + } + } + + // Apply velocity + d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z); + // apply gravity force + d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); + + + // apply friction + Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); + m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; + } // end MoveLinear() + + private void MoveAngular(float pTimestep) + { + /* + private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor + private int m_angularMotorApply = 0; // application frame counter + private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) + private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate + private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate + private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate + private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body + */ +//if(frcount == 0) Console.WriteLine("MoveAngular "); + + // Get what the body is doing, this includes 'external' influences + d.Vector3 angularVelocity = d.BodyGetAngularVel(Body); + // Vector3 angularVelocity = Vector3.Zero; + + if (m_angularMotorApply > 0) + { + // ramp up to new value + // current velocity += error / ( time to get there / step interval ) + // requested speed - last motor speed + m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); + m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); + m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); + + m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected + // velocity may still be acheived. + } + else + { + // no motor recently applied, keep the body velocity + /* m_angularMotorVelocity.X = angularVelocity.X; + m_angularMotorVelocity.Y = angularVelocity.Y; + m_angularMotorVelocity.Z = angularVelocity.Z; */ + + // and decay the velocity + m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); + } // end motor section + + + // Vertical attractor section + Vector3 vertattr = Vector3.Zero; + + if(m_verticalAttractionTimescale < 300) + { + float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); + // get present body rotation + d.Quaternion rot = d.BodyGetQuaternion(Body); + Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); + // make a vector pointing up + Vector3 verterr = Vector3.Zero; + verterr.Z = 1.0f; + // rotate it to Body Angle + verterr = verterr * rotq; + // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. + // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go + // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. + if (verterr.Z < 0.0f) + { + verterr.X = 2.0f - verterr.X; + verterr.Y = 2.0f - verterr.Y; + } + // Error is 0 (no error) to +/- 2 (max error) + // scale it by VAservo + verterr = verterr * VAservo; +//if(frcount == 0) Console.WriteLine("VAerr=" + verterr); + + // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so + // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. + vertattr.X = verterr.Y; + vertattr.Y = - verterr.X; + vertattr.Z = 0f; + + // scaling appears better usingsquare-law + float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); + vertattr.X += bounce * angularVelocity.X; + vertattr.Y += bounce * angularVelocity.Y; + + } // else vertical attractor is off + + // m_lastVertAttractor = vertattr; + + // Bank section tba + // Deflection section tba + + // Sum velocities + m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // tba: + bank + deflection + + if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) + { + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + } + else + { + m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. + } + + // apply friction + Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); + m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; + + // Apply to the body + d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); + + } //end MoveAngular + } +} diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs new file mode 100644 index 0000000..983431d --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -0,0 +1,3271 @@ +/* Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces + * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: + * ODEPrim.cs contains methods dealing with Prim editing, Prim + * characteristics and Kinetic motion. + * ODEDynamics.cs contains methods dealing with Prim Physical motion + * (dynamics) and the associated settings. Old Linear and angular + * motors for dynamic motion have been replace with MoveLinear() + * and MoveAngular(); 'Physical' is used only to switch ODE dynamic + * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to + * switch between 'VEHICLE' parameter use and general dynamics + * settings use. + */ + +/* + * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces + * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: + * ODEPrim.cs contains methods dealing with Prim editing, Prim + * characteristics and Kinetic motion. + * ODEDynamics.cs contains methods dealing with Prim Physical motion + * (dynamics) and the associated settings. Old Linear and angular + * motors for dynamic motion have been replace with MoveLinear() + * and MoveAngular(); 'Physical' is used only to switch ODE dynamic + * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to + * switch between 'VEHICLE' parameter use and general dynamics + * settings use. + */ +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using log4net; +using OpenMetaverse; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; + +namespace OpenSim.Region.Physics.OdePlugin +{ + /// + /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves. + /// + + public class OdePrim : PhysicsActor + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Vector3 _position; + private Vector3 _velocity; + private Vector3 _torque; + private Vector3 m_lastVelocity; + private Vector3 m_lastposition; + private Quaternion m_lastorientation = new Quaternion(); + private Vector3 m_rotationalVelocity; + private Vector3 _size; + private Vector3 _acceleration; + // private d.Vector3 _zeroPosition = new d.Vector3(0.0f, 0.0f, 0.0f); + private Quaternion _orientation; + private Vector3 m_taintposition; + private Vector3 m_taintsize; + private Vector3 m_taintVelocity; + private Vector3 m_taintTorque; + private Quaternion m_taintrot; + private Vector3 m_angularlock = Vector3.One; + private Vector3 m_taintAngularLock = Vector3.One; + private IntPtr Amotor = IntPtr.Zero; + + private Vector3 m_PIDTarget; + private float m_PIDTau; + private float PID_D = 35f; + private float PID_G = 25f; + private bool m_usePID = false; + + private Quaternion m_APIDTarget = new Quaternion(); + private float m_APIDStrength = 0.5f; + private float m_APIDDamping = 0.5f; + private bool m_useAPID = false; + + // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), + // and are for non-VEHICLES only. + + private float m_PIDHoverHeight; + private float m_PIDHoverTau; + private bool m_useHoverPID; + private PIDHoverType m_PIDHoverType = PIDHoverType.Ground; + private float m_targetHoverHeight; + private float m_groundHeight; + private float m_waterHeight; + private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. + + // private float m_tensor = 5f; + private int body_autodisable_frames = 20; + + + private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom + | CollisionCategories.Space + | CollisionCategories.Body + | CollisionCategories.Character + ); + private bool m_taintshape; + private bool m_taintPhysics; + private bool m_collidesLand = true; + private bool m_collidesWater; + public bool m_returnCollisions; + + // Default we're a Geometry + private CollisionCategories m_collisionCategories = (CollisionCategories.Geom); + + // Default, Collide with Other Geometries, spaces and Bodies + private CollisionCategories m_collisionFlags = m_default_collisionFlags; + + public bool m_taintremove; + public bool m_taintdisable; + public bool m_disabled; + public bool m_taintadd; + public bool m_taintselected; + public bool m_taintCollidesWater; + + public uint m_localID; + + //public GCHandle gc; + private CollisionLocker ode; + + private bool m_taintforce = false; + private bool m_taintaddangularforce = false; + private Vector3 m_force; + private List m_forcelist = new List(); + private List m_angularforcelist = new List(); + + private IMesh _mesh; + private PrimitiveBaseShape _pbs; + private OdeScene _parent_scene; + public IntPtr m_targetSpace = IntPtr.Zero; + public IntPtr prim_geom; + public IntPtr prev_geom; + public IntPtr _triMeshData; + + private IntPtr _linkJointGroup = IntPtr.Zero; + private PhysicsActor _parent; + private PhysicsActor m_taintparent; + + private List childrenPrim = new List(); + + private bool iscolliding; + private bool m_isphysical; + private bool m_isSelected; + + internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively + + private bool m_throttleUpdates; + private int throttleCounter; + public int m_interpenetrationcount; + public float m_collisionscore; + public int m_roundsUnderMotionThreshold; + private int m_crossingfailures; + + public bool outofBounds; + private float m_density = 10.000006836f; // Aluminum g/cm3; + + public bool _zeroFlag; + private bool m_lastUpdateSent; + + public IntPtr Body = IntPtr.Zero; + public String m_primName; + private Vector3 _target_velocity; + public d.Mass pMass; + + public int m_eventsubscription; + private CollisionEventUpdate CollisionEventsThisFrame; + + private IntPtr m_linkJoint = IntPtr.Zero; + + public volatile bool childPrim; + + private ODEDynamics m_vehicle; + + internal int m_material = (int)Material.Wood; + + private int frcount = 0; // Used to limit dynamics debug output to + + + public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, + Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) + { + m_vehicle = new ODEDynamics(); + //gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned); + ode = dode; + if (!pos.IsFinite()) + { + pos = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), + parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f); + m_log.Warn("[PHYSICS]: Got nonFinite Object create Position"); + } + _position = pos; + m_taintposition = pos; + PID_D = parent_scene.bodyPIDD; + PID_G = parent_scene.bodyPIDG; + m_density = parent_scene.geomDefaultDensity; + // m_tensor = parent_scene.bodyMotorJointMaxforceTensor; + body_autodisable_frames = parent_scene.bodyFramesAutoDisable; + + + prim_geom = IntPtr.Zero; + prev_geom = IntPtr.Zero; + + if (!pos.IsFinite()) + { + size = new Vector3(0.5f, 0.5f, 0.5f); + m_log.Warn("[PHYSICS]: Got nonFinite Object create Size"); + } + + if (size.X <= 0) size.X = 0.01f; + if (size.Y <= 0) size.Y = 0.01f; + if (size.Z <= 0) size.Z = 0.01f; + + _size = size; + m_taintsize = _size; + + if (!QuaternionIsFinite(rotation)) + { + rotation = Quaternion.Identity; + m_log.Warn("[PHYSICS]: Got nonFinite Object create Rotation"); + } + + _orientation = rotation; + m_taintrot = _orientation; + _mesh = mesh; + _pbs = pbs; + + _parent_scene = parent_scene; + m_targetSpace = (IntPtr)0; + + if (pos.Z < 0) + m_isphysical = false; + else + { + m_isphysical = pisPhysical; + // If we're physical, we need to be in the master space for now. + // linksets *should* be in a space together.. but are not currently + if (m_isphysical) + m_targetSpace = _parent_scene.space; + } + m_primName = primName; + m_taintadd = true; + _parent_scene.AddPhysicsActorTaint(this); + // don't do .add() here; old geoms get recycled with the same hash + } + + public override int PhysicsActorType + { + get { return (int) ActorTypes.Prim; } + set { return; } + } + + public override bool SetAlwaysRun + { + get { return false; } + set { return; } + } + + public override uint LocalID + { + set { + //m_log.Info("[PHYSICS]: Setting TrackerID: " + value); + m_localID = value; } + } + + public override bool Grabbed + { + set { return; } + } + + public override bool Selected + { + set { + + + // This only makes the object not collidable if the object + // is physical or the object is modified somehow *IN THE FUTURE* + // without this, if an avatar selects prim, they can walk right + // through it while it's selected + m_collisionscore = 0; + if ((m_isphysical && !_zeroFlag) || !value) + { + m_taintselected = value; + _parent_scene.AddPhysicsActorTaint(this); + } + else + { + m_taintselected = value; + m_isSelected = value; + } + if(m_isSelected) disableBodySoft(); + } + } + + public void SetGeom(IntPtr geom) + { + prev_geom = prim_geom; + prim_geom = geom; +//Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName); + if (prim_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + + if (childPrim) + { + if (_parent != null && _parent is OdePrim) + { + OdePrim parent = (OdePrim)_parent; +//Console.WriteLine("SetGeom calls ChildSetGeom"); + parent.ChildSetGeom(this); + } + } + //m_log.Warn("Setting Geom to: " + prim_geom); + } + + + + public void enableBodySoft() + { + if (!childPrim) + { + if (m_isphysical && Body != IntPtr.Zero) + { + d.BodyEnable(Body); + if (m_vehicle.Type != Vehicle.TYPE_NONE) + m_vehicle.Enable(Body, _parent_scene); + } + + m_disabled = false; + } + } + + public void disableBodySoft() + { + m_disabled = true; + + if (m_isphysical && Body != IntPtr.Zero) + { + d.BodyDisable(Body); + } + } + + public void enableBody() + { + // Don't enable this body if we're a child prim + // this should be taken care of in the parent function not here + if (!childPrim) + { + // Sets the geom to a body + Body = d.BodyCreate(_parent_scene.world); + + setMass(); + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.X = _orientation.X; + myrot.Y = _orientation.Y; + myrot.Z = _orientation.Z; + myrot.W = _orientation.W; + d.BodySetQuaternion(Body, ref myrot); + d.GeomSetBody(prim_geom, Body); + m_collisionCategories |= CollisionCategories.Body; + m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + + d.BodySetAutoDisableFlag(Body, true); + d.BodySetAutoDisableSteps(Body, body_autodisable_frames); + + // disconnect from world gravity so we can apply buoyancy + d.BodySetGravityMode (Body, false); + + m_interpenetrationcount = 0; + m_collisionscore = 0; + m_disabled = false; + + // The body doesn't already have a finite rotation mode set here + if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0.0f)) && _parent == null) + { + createAMotor(m_angularlock); + } + if (m_vehicle.Type != Vehicle.TYPE_NONE) + { + m_vehicle.Enable(Body, _parent_scene); + } + + _parent_scene.addActivePrim(this); + } + } + + #region Mass Calculation + + private float CalculateMass() + { + float volume = 0; + + // No material is passed to the physics engines yet.. soo.. + // we're using the m_density constant in the class definition + + float returnMass = 0; + + switch (_pbs.ProfileShape) + { + case ProfileShape.Square: + // Profile Volume + + volume = _size.X*_size.Y*_size.Z; + + // If the user has 'hollowed out' + // ProfileHollow is one of those 0 to 50000 values :P + // we like percentages better.. so turning into a percentage + + if (((float) _pbs.ProfileHollow/50000f) > 0.0) + { + float hollowAmount = (float) _pbs.ProfileHollow/50000f; + + // calculate the hollow volume by it's shape compared to the prim shape + float hollowVolume = 0; + switch (_pbs.HollowShape) + { + case HollowShape.Square: + case HollowShape.Same: + // Cube Hollow volume calculation + float hollowsizex = _size.X*hollowAmount; + float hollowsizey = _size.Y*hollowAmount; + float hollowsizez = _size.Z*hollowAmount; + hollowVolume = hollowsizex*hollowsizey*hollowsizez; + break; + + case HollowShape.Circle: + // Hollow shape is a perfect cyllinder in respect to the cube's scale + // Cyllinder hollow volume calculation + float hRadius = _size.X/2; + float hLength = _size.Z; + + // pi * r2 * h + hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); + break; + + case HollowShape.Triangle: + // Equilateral Triangular Prism volume hollow calculation + // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + + float aLength = _size.Y; + // 1/2 abh + hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); + break; + + default: + hollowVolume = 0; + break; + } + volume = volume - hollowVolume; + } + + break; + case ProfileShape.Circle: + if (_pbs.PathCurve == (byte)Extrusion.Straight) + { + // Cylinder + float volume1 = (float)(Math.PI * Math.Pow(_size.X/2, 2) * _size.Z); + float volume2 = (float)(Math.PI * Math.Pow(_size.Y/2, 2) * _size.Z); + + // Approximating the cylinder's irregularity. + if (volume1 > volume2) + { + volume = (float)volume1 - (volume1 - volume2); + } + else if (volume2 > volume1) + { + volume = (float)volume2 - (volume2 - volume1); + } + else + { + // Regular cylinder + volume = volume1; + } + } + else + { + // We don't know what the shape is yet, so use default + volume = _size.X * _size.Y * _size.Z; + } + // If the user has 'hollowed out' + // ProfileHollow is one of those 0 to 50000 values :P + // we like percentages better.. so turning into a percentage + + if (((float)_pbs.ProfileHollow / 50000f) > 0.0) + { + float hollowAmount = (float)_pbs.ProfileHollow / 50000f; + + // calculate the hollow volume by it's shape compared to the prim shape + float hollowVolume = 0; + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Circle: + // Hollow shape is a perfect cyllinder in respect to the cube's scale + // Cyllinder hollow volume calculation + float hRadius = _size.X / 2; + float hLength = _size.Z; + + // pi * r2 * h + hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount); + break; + + case HollowShape.Square: + // Cube Hollow volume calculation + float hollowsizex = _size.X * hollowAmount; + float hollowsizey = _size.Y * hollowAmount; + float hollowsizez = _size.Z * hollowAmount; + hollowVolume = hollowsizex * hollowsizey * hollowsizez; + break; + + case HollowShape.Triangle: + // Equilateral Triangular Prism volume hollow calculation + // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + + float aLength = _size.Y; + // 1/2 abh + hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); + break; + + default: + hollowVolume = 0; + break; + } + volume = volume - hollowVolume; + } + break; + + case ProfileShape.HalfCircle: + if (_pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z) + { + // regular sphere + // v = 4/3 * pi * r^3 + float sradius3 = (float)Math.Pow((_size.X / 2), 3); + volume = (float)((4f / 3f) * Math.PI * sradius3); + } + else + { + // we treat this as a box currently + volume = _size.X * _size.Y * _size.Z; + } + } + else + { + // We don't know what the shape is yet, so use default + volume = _size.X * _size.Y * _size.Z; + } + break; + + case ProfileShape.EquilateralTriangle: + /* + v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h + + // seed mesh + Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); + Vertex PM = new Vertex(+0.5f, 0f, 0.0f); + Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); + */ + float xA = -0.25f * _size.X; + float yA = -0.45f * _size.Y; + + float xB = 0.5f * _size.X; + float yB = 0; + + float xC = -0.25f * _size.X; + float yC = 0.45f * _size.Y; + + volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z); + + // If the user has 'hollowed out' + // ProfileHollow is one of those 0 to 50000 values :P + // we like percentages better.. so turning into a percentage + float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f); + if (((float)fhollowFactor / 50000f) > 0.0) + { + float hollowAmount = (float)fhollowFactor / 50000f; + + // calculate the hollow volume by it's shape compared to the prim shape + float hollowVolume = 0; + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Triangle: + // Equilateral Triangular Prism volume hollow calculation + // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + + float aLength = _size.Y; + // 1/2 abh + hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); + break; + + case HollowShape.Square: + // Cube Hollow volume calculation + float hollowsizex = _size.X * hollowAmount; + float hollowsizey = _size.Y * hollowAmount; + float hollowsizez = _size.Z * hollowAmount; + hollowVolume = hollowsizex * hollowsizey * hollowsizez; + break; + + case HollowShape.Circle: + // Hollow shape is a perfect cyllinder in respect to the cube's scale + // Cyllinder hollow volume calculation + float hRadius = _size.X / 2; + float hLength = _size.Z; + + // pi * r2 * h + hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength)/2) * hollowAmount); + break; + + default: + hollowVolume = 0; + break; + } + volume = volume - hollowVolume; + } + break; + + default: + // we don't have all of the volume formulas yet so + // use the common volume formula for all + volume = _size.X*_size.Y*_size.Z; + break; + } + + // Calculate Path cut effect on volume + // Not exact, in the triangle hollow example + // They should never be zero or less then zero.. + // we'll ignore it if it's less then zero + + // ProfileEnd and ProfileBegin are values + // from 0 to 50000 + + // Turning them back into percentages so that I can cut that percentage off the volume + + float PathCutEndAmount = _pbs.ProfileEnd; + float PathCutStartAmount = _pbs.ProfileBegin; + if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) + { + float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f); + + // Check the return amount for sanity + if (pathCutAmount >= 0.99f) + pathCutAmount = 0.99f; + + volume = volume - (volume*pathCutAmount); + } + UInt16 taperX = _pbs.PathScaleX; + UInt16 taperY = _pbs.PathScaleY; + float taperFactorX = 0; + float taperFactorY = 0; + + // Mass = density * volume + if (taperX != 100) + { + if (taperX > 100) + { + taperFactorX = 1.0f - ((float)taperX / 200); + //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); + } + else + { + taperFactorX = 1.0f - ((100 - (float)taperX) / 100); + //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); + } + volume = (float)volume * ((taperFactorX / 3f) + 0.001f); + } + + if (taperY != 100) + { + if (taperY > 100) + { + taperFactorY = 1.0f - ((float)taperY / 200); + //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); + } + else + { + taperFactorY = 1.0f - ((100 - (float)taperY) / 100); + //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); + } + volume = (float)volume * ((taperFactorY / 3f) + 0.001f); + } + returnMass = m_density*volume; + if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. + + + + // Recursively calculate mass + bool HasChildPrim = false; + lock (childrenPrim) + { + if (childrenPrim.Count > 0) + { + HasChildPrim = true; + } + + } + if (HasChildPrim) + { + OdePrim[] childPrimArr = new OdePrim[0]; + + lock (childrenPrim) + childPrimArr = childrenPrim.ToArray(); + + for (int i = 0; i < childPrimArr.Length; i++) + { + if (childPrimArr[i] != null && !childPrimArr[i].m_taintremove) + returnMass += childPrimArr[i].CalculateMass(); + // failsafe, this shouldn't happen but with OpenSim, you never know :) + if (i > 256) + break; + } + } + if (returnMass > _parent_scene.maximumMassObject) + returnMass = _parent_scene.maximumMassObject; + return returnMass; + }// end CalculateMass + + #endregion + + public void setMass() + { + if (Body != (IntPtr) 0) + { + float newmass = CalculateMass(); + + //m_log.Info("[PHYSICS]: New Mass: " + newmass.ToString()); + + d.MassSetBoxTotal(out pMass, newmass, _size.X, _size.Y, _size.Z); + d.BodySetMass(Body, ref pMass); + } + } + + public void disableBody() + { + //this kills the body so things like 'mesh' can re-create it. + lock (this) + { + if (!childPrim) + { + if (Body != IntPtr.Zero) + { + _parent_scene.remActivePrim(this); + m_collisionCategories &= ~CollisionCategories.Body; + m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); + + if (prim_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + + + d.BodyDestroy(Body); + lock (childrenPrim) + { + if (childrenPrim.Count > 0) + { + foreach (OdePrim prm in childrenPrim) + { + _parent_scene.remActivePrim(prm); + prm.Body = IntPtr.Zero; + } + } + } + Body = IntPtr.Zero; + } + } + else + { + _parent_scene.remActivePrim(this); + + m_collisionCategories &= ~CollisionCategories.Body; + m_collisionFlags &= ~(CollisionCategories.Wind | CollisionCategories.Land); + + if (prim_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + + + Body = IntPtr.Zero; + } + } + m_disabled = true; + m_collisionscore = 0; + } + + private static Dictionary m_MeshToTriMeshMap = new Dictionary(); + + public void setMesh(OdeScene parent_scene, IMesh mesh) + { + // This sleeper is there to moderate how long it takes between + // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object + + //Thread.Sleep(10); + + //Kill Body so that mesh can re-make the geom + if (IsPhysical && Body != IntPtr.Zero) + { + if (childPrim) + { + if (_parent != null) + { + OdePrim parent = (OdePrim)_parent; + parent.ChildDelink(this); + } + } + else + { + disableBody(); + } + } + + IntPtr vertices, indices; + int vertexCount, indexCount; + int vertexStride, triStride; + mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap + mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage + + mesh.releaseSourceMeshData(); // free up the original mesh data to save memory + if (m_MeshToTriMeshMap.ContainsKey(mesh)) + { + _triMeshData = m_MeshToTriMeshMap[mesh]; + } + else + { + _triMeshData = d.GeomTriMeshDataCreate(); + + d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); + d.GeomTriMeshDataPreprocess(_triMeshData); + m_MeshToTriMeshMap[mesh] = _triMeshData; + } + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { + if (prim_geom == IntPtr.Zero) + { + SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); + } + } + catch (AccessViolationException) + { + m_log.Error("[PHYSICS]: MESH LOCKED"); + return; + } + + + // if (IsPhysical && Body == (IntPtr) 0) + // { + // Recreate the body + // m_interpenetrationcount = 0; + // m_collisionscore = 0; + + // enableBody(); + // } + } + + public void ProcessTaints(float timestep) + { +//Console.WriteLine("ProcessTaints for " + m_primName ); + if (m_taintadd) + { + changeadd(timestep); + } + + if (prim_geom != IntPtr.Zero) + { + if (!_position.ApproxEquals(m_taintposition, 0f)) + changemove(timestep); + + if (m_taintrot != _orientation) + { + if(childPrim && IsPhysical) // For physical child prim... + { + rotate(timestep); + // KF: ODE will also rotate the parent prim! + // so rotate the root back to where it was + OdePrim parent = (OdePrim)_parent; + parent.rotate(timestep); + } + else + { + //Just rotate the prim + rotate(timestep); + } + } + // + + if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) + changePhysicsStatus(timestep); + // + + if (!_size.ApproxEquals(m_taintsize,0f)) + changesize(timestep); + // + + if (m_taintshape) + changeshape(timestep); + // + + if (m_taintforce) + changeAddForce(timestep); + + if (m_taintaddangularforce) + changeAddAngularForce(timestep); + + if (!m_taintTorque.ApproxEquals(Vector3.Zero, 0.001f)) + changeSetTorque(timestep); + + if (m_taintdisable) + changedisable(timestep); + + if (m_taintselected != m_isSelected) + changeSelectedStatus(timestep); + + if (!m_taintVelocity.ApproxEquals(Vector3.Zero, 0.001f)) + changevelocity(timestep); + + if (m_taintparent != _parent) + changelink(timestep); + + if (m_taintCollidesWater != m_collidesWater) + changefloatonwater(timestep); + + if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) + changeAngularLock(timestep); + + } + else + { + m_log.Error("[PHYSICS]: The scene reused a disposed PhysActor! *waves finger*, Don't be evil. A couple of things can cause this. An improper prim breakdown(be sure to set prim_geom to zero after d.GeomDestroy! An improper buildup (creating the geom failed). Or, the Scene Reused a physics actor after disposing it.)"); + } + } + + + private void changeAngularLock(float timestep) + { + // do we have a Physical object? + if (Body != IntPtr.Zero) + { + //Check that we have a Parent + //If we have a parent then we're not authorative here + if (_parent == null) + { + if (!m_taintAngularLock.ApproxEquals(Vector3.One, 0f)) + { + //d.BodySetFiniteRotationMode(Body, 0); + //d.BodySetFiniteRotationAxis(Body,m_taintAngularLock.X,m_taintAngularLock.Y,m_taintAngularLock.Z); + createAMotor(m_taintAngularLock); + } + else + { + if (Amotor != IntPtr.Zero) + { + d.JointDestroy(Amotor); + Amotor = IntPtr.Zero; + } + } + } + } + // Store this for later in case we get turned into a separate body + m_angularlock = m_taintAngularLock; + + } + + private void changelink(float timestep) + { + // If the newly set parent is not null + // create link + if (_parent == null && m_taintparent != null) + { + if (m_taintparent.PhysicsActorType == (int)ActorTypes.Prim) + { + OdePrim obj = (OdePrim)m_taintparent; + //obj.disableBody(); +//Console.WriteLine("changelink calls ParentPrim"); + obj.ParentPrim(this); + + /* + if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body) + { + _linkJointGroup = d.JointGroupCreate(0); + m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup); + d.JointAttach(m_linkJoint, obj.Body, Body); + d.JointSetFixed(m_linkJoint); + } + */ + } + } + // If the newly set parent is null + // destroy link + else if (_parent != null && m_taintparent == null) + { +//Console.WriteLine(" changelink B"); + + if (_parent is OdePrim) + { + OdePrim obj = (OdePrim)_parent; + obj.ChildDelink(this); + childPrim = false; + //_parent = null; + } + + /* + if (Body != (IntPtr)0 && _linkJointGroup != (IntPtr)0) + d.JointGroupDestroy(_linkJointGroup); + + _linkJointGroup = (IntPtr)0; + m_linkJoint = (IntPtr)0; + */ + } + + _parent = m_taintparent; + m_taintPhysics = m_isphysical; + } + + // I'm the parent + // prim is the child + public void ParentPrim(OdePrim prim) + { +//Console.WriteLine("ParentPrim " + m_primName); + if (this.m_localID != prim.m_localID) + { + if (Body == IntPtr.Zero) + { + Body = d.BodyCreate(_parent_scene.world); + setMass(); + } + if (Body != IntPtr.Zero) + { + lock (childrenPrim) + { + if (!childrenPrim.Contains(prim)) + { +//Console.WriteLine("childrenPrim.Add " + prim); + childrenPrim.Add(prim); + + foreach (OdePrim prm in childrenPrim) + { + d.Mass m2; + d.MassSetZero(out m2); + d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z); + + + d.Quaternion quat = new d.Quaternion(); + quat.W = prm._orientation.W; + quat.X = prm._orientation.X; + quat.Y = prm._orientation.Y; + quat.Z = prm._orientation.Z; + + d.Matrix3 mat = new d.Matrix3(); + d.RfromQ(out mat, ref quat); + d.MassRotate(ref m2, ref mat); + d.MassTranslate(ref m2, Position.X - prm.Position.X, Position.Y - prm.Position.Y, Position.Z - prm.Position.Z); + d.MassAdd(ref pMass, ref m2); + } + foreach (OdePrim prm in childrenPrim) + { + + prm.m_collisionCategories |= CollisionCategories.Body; + prm.m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + + if (prm.prim_geom == IntPtr.Zero) + { + m_log.Warn("[PHYSICS]: Unable to link one of the linkset elements. No geom yet"); + continue; + } +//Console.WriteLine(" GeomSetCategoryBits 1: " + prm.prim_geom + " - " + (int)prm.m_collisionCategories + " for " + m_primName); + d.GeomSetCategoryBits(prm.prim_geom, (int)prm.m_collisionCategories); + d.GeomSetCollideBits(prm.prim_geom, (int)prm.m_collisionFlags); + + + d.Quaternion quat = new d.Quaternion(); + quat.W = prm._orientation.W; + quat.X = prm._orientation.X; + quat.Y = prm._orientation.Y; + quat.Z = prm._orientation.Z; + + d.Matrix3 mat = new d.Matrix3(); + d.RfromQ(out mat, ref quat); + if (Body != IntPtr.Zero) + { + d.GeomSetBody(prm.prim_geom, Body); + prm.childPrim = true; + d.GeomSetOffsetWorldPosition(prm.prim_geom, prm.Position.X , prm.Position.Y, prm.Position.Z); + //d.GeomSetOffsetPosition(prim.prim_geom, + // (Position.X - prm.Position.X) - pMass.c.X, + // (Position.Y - prm.Position.Y) - pMass.c.Y, + // (Position.Z - prm.Position.Z) - pMass.c.Z); + d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); + //d.GeomSetOffsetRotation(prm.prim_geom, ref mat); + d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z); + d.BodySetMass(Body, ref pMass); + } + else + { + m_log.Debug("[PHYSICS]:I ain't got no boooooooooddy, no body"); + } + + + prm.m_interpenetrationcount = 0; + prm.m_collisionscore = 0; + prm.m_disabled = false; + + // The body doesn't already have a finite rotation mode set here + if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) + { + prm.createAMotor(m_angularlock); + } + prm.Body = Body; + _parent_scene.addActivePrim(prm); + } + m_collisionCategories |= CollisionCategories.Body; + m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + +//Console.WriteLine("GeomSetCategoryBits 2: " + prim_geom + " - " + (int)m_collisionCategories + " for " + m_primName); + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); +//Console.WriteLine(" Post GeomSetCategoryBits 2"); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + + + d.Quaternion quat2 = new d.Quaternion(); + quat2.W = _orientation.W; + quat2.X = _orientation.X; + quat2.Y = _orientation.Y; + quat2.Z = _orientation.Z; + + d.Matrix3 mat2 = new d.Matrix3(); + d.RfromQ(out mat2, ref quat2); + d.GeomSetBody(prim_geom, Body); + d.GeomSetOffsetWorldPosition(prim_geom, Position.X - pMass.c.X, Position.Y - pMass.c.Y, Position.Z - pMass.c.Z); + //d.GeomSetOffsetPosition(prim.prim_geom, + // (Position.X - prm.Position.X) - pMass.c.X, + // (Position.Y - prm.Position.Y) - pMass.c.Y, + // (Position.Z - prm.Position.Z) - pMass.c.Z); + //d.GeomSetOffsetRotation(prim_geom, ref mat2); + d.MassTranslate(ref pMass, -pMass.c.X, -pMass.c.Y, -pMass.c.Z); + d.BodySetMass(Body, ref pMass); + + d.BodySetAutoDisableFlag(Body, true); + d.BodySetAutoDisableSteps(Body, body_autodisable_frames); + + + m_interpenetrationcount = 0; + m_collisionscore = 0; + m_disabled = false; + + // The body doesn't already have a finite rotation mode set here + if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) + { + createAMotor(m_angularlock); + } + d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); + if (m_vehicle.Type != Vehicle.TYPE_NONE) m_vehicle.Enable(Body, _parent_scene); + _parent_scene.addActivePrim(this); + } + } + } + } + + } + + private void ChildSetGeom(OdePrim odePrim) + { + //if (m_isphysical && Body != IntPtr.Zero) + lock (childrenPrim) + { + foreach (OdePrim prm in childrenPrim) + { + //prm.childPrim = true; + prm.disableBody(); + //prm.m_taintparent = null; + //prm._parent = null; + //prm.m_taintPhysics = false; + //prm.m_disabled = true; + //prm.childPrim = false; + } + } + disableBody(); + + + if (Body != IntPtr.Zero) + { + _parent_scene.remActivePrim(this); + } + + lock (childrenPrim) + { + foreach (OdePrim prm in childrenPrim) + { +//Console.WriteLine("ChildSetGeom calls ParentPrim"); + ParentPrim(prm); + } + } + + } + + private void ChildDelink(OdePrim odePrim) + { + // Okay, we have a delinked child.. need to rebuild the body. + lock (childrenPrim) + { + foreach (OdePrim prm in childrenPrim) + { + prm.childPrim = true; + prm.disableBody(); + //prm.m_taintparent = null; + //prm._parent = null; + //prm.m_taintPhysics = false; + //prm.m_disabled = true; + //prm.childPrim = false; + } + } + disableBody(); + + lock (childrenPrim) + { + //Console.WriteLine("childrenPrim.Remove " + odePrim); + childrenPrim.Remove(odePrim); + } + + + + + if (Body != IntPtr.Zero) + { + _parent_scene.remActivePrim(this); + } + + + + lock (childrenPrim) + { + foreach (OdePrim prm in childrenPrim) + { +//Console.WriteLine("ChildDelink calls ParentPrim"); + ParentPrim(prm); + } + } + + + } + + private void changeSelectedStatus(float timestep) + { + if (m_taintselected) + { + m_collisionCategories = CollisionCategories.Selected; + m_collisionFlags = (CollisionCategories.Sensor | CollisionCategories.Space); + + // We do the body disable soft twice because 'in theory' a collision could have happened + // in between the disabling and the collision properties setting + // which would wake the physical body up from a soft disabling and potentially cause it to fall + // through the ground. + + // NOTE FOR JOINTS: this doesn't always work for jointed assemblies because if you select + // just one part of the assembly, the rest of the assembly is non-selected and still simulating, + // so that causes the selected part to wake up and continue moving. + + // even if you select all parts of a jointed assembly, it is not guaranteed that the entire + // assembly will stop simulating during the selection, because of the lack of atomicity + // of select operations (their processing could be interrupted by a thread switch, causing + // simulation to continue before all of the selected object notifications trickle down to + // the physics engine). + + // e.g. we select 100 prims that are connected by joints. non-atomically, the first 50 are + // selected and disabled. then, due to a thread switch, the selection processing is + // interrupted and the physics engine continues to simulate, so the last 50 items, whose + // selection was not yet processed, continues to simulate. this wakes up ALL of the + // first 50 again. then the last 50 are disabled. then the first 50, which were just woken + // up, start simulating again, which in turn wakes up the last 50. + + if (m_isphysical) + { + disableBodySoft(); + } + + if (prim_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + + if (m_isphysical) + { + disableBodySoft(); + } + } + else + { + m_collisionCategories = CollisionCategories.Geom; + + if (m_isphysical) + m_collisionCategories |= CollisionCategories.Body; + + m_collisionFlags = m_default_collisionFlags; + + if (m_collidesLand) + m_collisionFlags |= CollisionCategories.Land; + if (m_collidesWater) + m_collisionFlags |= CollisionCategories.Water; + + if (prim_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + if (m_isphysical) + { + if (Body != IntPtr.Zero) + { + d.BodySetLinearVel(Body, 0f, 0f, 0f); + d.BodySetForce(Body, 0, 0, 0); + enableBodySoft(); + } + } + } + + resetCollisionAccounting(); + m_isSelected = m_taintselected; + }//end changeSelectedStatus + + public void ResetTaints() + { + m_taintposition = _position; + m_taintrot = _orientation; + m_taintPhysics = m_isphysical; + m_taintselected = m_isSelected; + m_taintsize = _size; + m_taintshape = false; + m_taintforce = false; + m_taintdisable = false; + m_taintVelocity = Vector3.Zero; + } + + public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) + { +//Console.WriteLine("CreateGeom:"); + if (_mesh != null) + { + setMesh(_parent_scene, _mesh); + } + else + { + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + { + if (((_size.X / 2f) > 0f)) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { +//Console.WriteLine(" CreateGeom 1"); + SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { +//Console.WriteLine(" CreateGeom 2"); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + } + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { +//Console.WriteLine(" CreateGeom 3"); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + } + + else + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + try + { +//Console.WriteLine(" CreateGeom 4"); + SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); + ode.dunlock(_parent_scene.world); + return; + } + } + } + } + + public void changeadd(float timestep) + { + int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position); + IntPtr targetspace = _parent_scene.calculateSpaceForGeom(_position); + + if (targetspace == IntPtr.Zero) + targetspace = _parent_scene.createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); + + m_targetSpace = targetspace; + + if (_mesh == null) + { + if (_parent_scene.needsMeshing(_pbs)) + { + // Don't need to re-enable body.. it's done in SetMesh + _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); + // createmesh returns null when it's a shape that isn't a cube. + // m_log.Debug(m_localID); + } + } + + + lock (_parent_scene.OdeLock) + { +//Console.WriteLine("changeadd 1"); + CreateGeom(m_targetSpace, _mesh); + + if (prim_geom != IntPtr.Zero) + { + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.X = _orientation.X; + myrot.Y = _orientation.Y; + myrot.Z = _orientation.Z; + myrot.W = _orientation.W; + d.GeomSetQuaternion(prim_geom, ref myrot); + } + + if (m_isphysical && Body == IntPtr.Zero) + { + enableBody(); + } + } + + _parent_scene.geom_name_map[prim_geom] = this.m_primName; + _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this; + + changeSelectedStatus(timestep); + + m_taintadd = false; + } + + public void changemove(float timestep) + { + if (m_isphysical) + { + + if (!m_disabled && !m_taintremove && !childPrim) + { + if (Body == IntPtr.Zero) + enableBody(); + //Prim auto disable after 20 frames, + //if you move it, re-enable the prim manually. + if (_parent != null) + { + if (m_linkJoint != IntPtr.Zero) + { + d.JointDestroy(m_linkJoint); + m_linkJoint = IntPtr.Zero; + } + } + if (Body != IntPtr.Zero) + { + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + + if (_parent != null) + { + OdePrim odParent = (OdePrim)_parent; + if (Body != (IntPtr)0 && odParent.Body != (IntPtr)0 && Body != odParent.Body) + { +// KF: Fixed Joints were removed? Anyway - this Console.WriteLine does not show up, so routine is not used?? +Console.WriteLine(" JointCreateFixed"); + m_linkJoint = d.JointCreateFixed(_parent_scene.world, _linkJointGroup); + d.JointAttach(m_linkJoint, Body, odParent.Body); + d.JointSetFixed(m_linkJoint); + } + } + d.BodyEnable(Body); + if (m_vehicle.Type != Vehicle.TYPE_NONE) + { + m_vehicle.Enable(Body, _parent_scene); + } + } + else + { + m_log.Warn("[PHYSICS]: Body Still null after enableBody(). This is a crash scenario."); + } + } + //else + // { + //m_log.Debug("[BUG]: race!"); + //} + } + else + { + // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); + // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); + _parent_scene.waitForSpaceUnlock(m_targetSpace); + + IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); + m_targetSpace = tempspace; + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + if (prim_geom != IntPtr.Zero) + { + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + + _parent_scene.waitForSpaceUnlock(m_targetSpace); + d.SpaceAdd(m_targetSpace, prim_geom); + } + } + + changeSelectedStatus(timestep); + + resetCollisionAccounting(); + m_taintposition = _position; + } + + public void Move(float timestep) + { + float fx = 0; + float fy = 0; + float fz = 0; + + frcount++; // used to limit debug comment output + if (frcount > 100) + frcount = 0; + + if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. + { +//if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_vehicle.Type + + // " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); + if (m_vehicle.Type != Vehicle.TYPE_NONE) + { + // 'VEHICLES' are dealt with in ODEDynamics.cs + m_vehicle.Step(timestep, _parent_scene); + } + else + { + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 + // NON-'VEHICLES' are dealt with here + if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f)) + { + d.Vector3 avel2 = d.BodyGetAngularVel(Body); + if (m_angularlock.X == 1) + avel2.X = 0; + if (m_angularlock.Y == 1) + avel2.Y = 0; + if (m_angularlock.Z == 1) + avel2.Z = 0; + d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); + } + //float PID_P = 900.0f; + + float m_mass = CalculateMass(); + +// fz = 0f; + //m_log.Info(m_collisionFlags.ToString()); + + + //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle. + // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up + // NB Prims in ODE are no subject to global gravity + fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass + + if (m_usePID) + { +//if(frcount == 0) Console.WriteLine("PID " + m_primName); + // KF - this is for object MoveToTarget. + + //if (!d.BodyIsEnabled(Body)) + //d.BodySetForce(Body, 0f, 0f, 0f); + + // no lock; for now it's only called from within Simulate() + + // If the PID Controller isn't active then we set our force + // calculating base velocity to the current position + + if ((m_PIDTau < 1) && (m_PIDTau != 0)) + { + //PID_G = PID_G / m_PIDTau; + m_PIDTau = 1; + } + + if ((PID_G - m_PIDTau) <= 0) + { + PID_G = m_PIDTau + 1; + } + //PidStatus = true; + + // PhysicsVector vec = new PhysicsVector(); + d.Vector3 vel = d.BodyGetLinearVel(Body); + + d.Vector3 pos = d.BodyGetPosition(Body); + _target_velocity = + new Vector3( + (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep), + (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep), + (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) + ); + + // if velocity is zero, use position control; otherwise, velocity control + + if (_target_velocity.ApproxEquals(Vector3.Zero,0.1f)) + { + // keep track of where we stopped. No more slippin' & slidin' + + // We only want to deactivate the PID Controller if we think we want to have our surrogate + // react to the physics scene by moving it's position. + // Avatar to Avatar collisions + // Prim to avatar collisions + + //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); + //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2); + //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; + d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); + d.BodySetLinearVel(Body, 0, 0, 0); + d.BodyAddForce(Body, 0, 0, fz); + return; + } + else + { + _zeroFlag = false; + + // We're flying and colliding with something + fx = ((_target_velocity.X) - vel.X) * (PID_D); + fy = ((_target_velocity.Y) - vel.Y) * (PID_D); + + // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; + + fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); + } + } // end if (m_usePID) + + // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller + if (m_useHoverPID && !m_usePID) + { +//Console.WriteLine("Hover " + m_primName); + + // If we're using the PID controller, then we have no gravity + fz = (-1 * _parent_scene.gravityz) * m_mass; + + // no lock; for now it's only called from within Simulate() + + // If the PID Controller isn't active then we set our force + // calculating base velocity to the current position + + if ((m_PIDTau < 1)) + { + PID_G = PID_G / m_PIDTau; + } + + if ((PID_G - m_PIDTau) <= 0) + { + PID_G = m_PIDTau + 1; + } + + + // Where are we, and where are we headed? + d.Vector3 pos = d.BodyGetPosition(Body); + d.Vector3 vel = d.BodyGetLinearVel(Body); + + + // Non-Vehicles have a limited set of Hover options. + // determine what our target height really is based on HoverType + switch (m_PIDHoverType) + { + case PIDHoverType.Ground: + m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); + m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; + break; + case PIDHoverType.GroundAndWater: + m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); + m_waterHeight = _parent_scene.GetWaterLevel(); + if (m_groundHeight > m_waterHeight) + { + m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; + } + else + { + m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight; + } + break; + + } // end switch (m_PIDHoverType) + + + _target_velocity = + new Vector3(0.0f, 0.0f, + (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep) + ); + + // if velocity is zero, use position control; otherwise, velocity control + + if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) + { + // keep track of where we stopped. No more slippin' & slidin' + + // We only want to deactivate the PID Controller if we think we want to have our surrogate + // react to the physics scene by moving it's position. + // Avatar to Avatar collisions + // Prim to avatar collisions + + d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); + d.BodySetLinearVel(Body, vel.X, vel.Y, 0); + d.BodyAddForce(Body, 0, 0, fz); + //KF this prevents furthur motions return; + } + else + { + _zeroFlag = false; + + // We're flying and colliding with something + fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); + } + } // end m_useHoverPID && !m_usePID + + if (m_useAPID) + { + // RotLookAt, apparently overrides all other rotation sources. Inputs: + // Quaternion m_APIDTarget + // float m_APIDStrength // From SL experiments, this is the time to get there + // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly + // Also in SL the mass of the object has no effect on time to get there. + // Factors: +//if(frcount == 0) Console.WriteLine("APID "); + // get present body rotation + float limit = 1.0f; + float scaler = 50f; // adjusts damping time + float RLAservo = 0f; + + d.Quaternion rot = d.BodyGetQuaternion(Body); + Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); + Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget; + float diff_angle; + Vector3 diff_axis; + rot_diff.GetAxisAngle(out diff_axis, out diff_angle); + diff_axis.Normalize(); + if(diff_angle > 0.01f) // diff_angle is always +ve + { +// PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z); + Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z); + rotforce = rotforce * rotq; + if(diff_angle > limit) diff_angle = limit; // cap the rotate rate +// RLAservo = timestep / m_APIDStrength * m_mass * scaler; + // rotforce = rotforce * RLAservo * diff_angle ; + // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); + RLAservo = timestep / m_APIDStrength * scaler; + rotforce = rotforce * RLAservo * diff_angle ; + d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); +//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); + } +//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); + } // end m_useAPID + + fx *= m_mass; + fy *= m_mass; + //fz *= m_mass; + + fx += m_force.X; + fy += m_force.Y; + fz += m_force.Z; + + //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString()); + if (fx != 0 || fy != 0 || fz != 0) + { + //m_taintdisable = true; + //base.RaiseOutOfBounds(Position); + //d.BodySetLinearVel(Body, fx, fy, 0f); + if (!d.BodyIsEnabled(Body)) + { + // A physical body at rest on a surface will auto-disable after a while, + // this appears to re-enable it incase the surface it is upon vanishes, + // and the body should fall again. + d.BodySetLinearVel(Body, 0f, 0f, 0f); + d.BodySetForce(Body, 0, 0, 0); + enableBodySoft(); + } + + // 35x10 = 350n times the mass per second applied maximum. + float nmax = 35f * m_mass; + float nmin = -35f * m_mass; + + + if (fx > nmax) + fx = nmax; + if (fx < nmin) + fx = nmin; + if (fy > nmax) + fy = nmax; + if (fy < nmin) + fy = nmin; + d.BodyAddForce(Body, fx, fy, fz); +//Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); + } + } + } + else + { // is not physical, or is not a body or is selected + // _zeroPosition = d.BodyGetPosition(Body); + return; +//Console.WriteLine("Nothing " + m_primName); + + } + } + + + + public void rotate(float timestep) + { + d.Quaternion myrot = new d.Quaternion(); + myrot.X = _orientation.X; + myrot.Y = _orientation.Y; + myrot.Z = _orientation.Z; + myrot.W = _orientation.W; + if (Body != IntPtr.Zero) + { + // KF: If this is a root prim do BodySet + d.BodySetQuaternion(Body, ref myrot); + if (m_isphysical) + { + if (!m_angularlock.ApproxEquals(Vector3.One, 0f)) + createAMotor(m_angularlock); + } + } + else + { + // daughter prim, do Geom set + d.GeomSetQuaternion(prim_geom, ref myrot); + } + + resetCollisionAccounting(); + m_taintrot = _orientation; + } + + private void resetCollisionAccounting() + { + m_collisionscore = 0; + m_interpenetrationcount = 0; + m_disabled = false; + } + + public void changedisable(float timestep) + { + m_disabled = true; + if (Body != IntPtr.Zero) + { + d.BodyDisable(Body); + Body = IntPtr.Zero; + } + + m_taintdisable = false; + } + + public void changePhysicsStatus(float timestep) + { + if (m_isphysical == true) + { + if (Body == IntPtr.Zero) + { + if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) + { + changeshape(2f); + } + else + { + enableBody(); + } + } + } + else + { + if (Body != IntPtr.Zero) + { + if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) + { + + + if (prim_geom != IntPtr.Zero) + { + try + { + d.GeomDestroy(prim_geom); + prim_geom = IntPtr.Zero; + _mesh = null; + } + catch (System.AccessViolationException) + { + prim_geom = IntPtr.Zero; + m_log.Error("[PHYSICS]: PrimGeom dead"); + } + } +//Console.WriteLine("changePhysicsStatus for " + m_primName ); + changeadd(2f); + } + if (childPrim) + { + if (_parent != null) + { + OdePrim parent = (OdePrim)_parent; + parent.ChildDelink(this); + } + } + else + { + disableBody(); + } + } + } + + changeSelectedStatus(timestep); + + resetCollisionAccounting(); + m_taintPhysics = m_isphysical; + } + + public void changesize(float timestamp) + { + + string oldname = _parent_scene.geom_name_map[prim_geom]; + + if (_size.X <= 0) _size.X = 0.01f; + if (_size.Y <= 0) _size.Y = 0.01f; + if (_size.Z <= 0) _size.Z = 0.01f; + + // Cleanup of old prim geometry + if (_mesh != null) + { + // Cleanup meshing here + } + //kill body to rebuild + if (IsPhysical && Body != IntPtr.Zero) + { + if (childPrim) + { + if (_parent != null) + { + OdePrim parent = (OdePrim)_parent; + parent.ChildDelink(this); + } + } + else + { + disableBody(); + } + } + if (d.SpaceQuery(m_targetSpace, prim_geom)) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + d.SpaceRemove(m_targetSpace, prim_geom); + } + d.GeomDestroy(prim_geom); + prim_geom = IntPtr.Zero; + // we don't need to do space calculation because the client sends a position update also. + + // Construction of new prim + if (_parent_scene.needsMeshing(_pbs)) + { + float meshlod = _parent_scene.meshSculptLOD; + + if (IsPhysical) + meshlod = _parent_scene.MeshSculptphysicalLOD; + // Don't need to re-enable body.. it's done in SetMesh + + IMesh mesh = null; + + if (_parent_scene.needsMeshing(_pbs)) + mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); + + //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); +//Console.WriteLine("changesize 1"); + CreateGeom(m_targetSpace, mesh); + + + } + else + { + _mesh = null; +//Console.WriteLine("changesize 2"); + CreateGeom(m_targetSpace, _mesh); + } + + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.X = _orientation.X; + myrot.Y = _orientation.Y; + myrot.Z = _orientation.Z; + myrot.W = _orientation.W; + d.GeomSetQuaternion(prim_geom, ref myrot); + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == IntPtr.Zero && !childPrim) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } + + _parent_scene.geom_name_map[prim_geom] = oldname; + + changeSelectedStatus(timestamp); + if (childPrim) + { + if (_parent is OdePrim) + { + OdePrim parent = (OdePrim)_parent; + parent.ChildSetGeom(this); + } + } + resetCollisionAccounting(); + m_taintsize = _size; + } + + + + public void changefloatonwater(float timestep) + { + m_collidesWater = m_taintCollidesWater; + + if (prim_geom != IntPtr.Zero) + { + if (m_collidesWater) + { + m_collisionFlags |= CollisionCategories.Water; + } + else + { + m_collisionFlags &= ~CollisionCategories.Water; + } + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + } + + public void changeshape(float timestamp) + { + string oldname = _parent_scene.geom_name_map[prim_geom]; + + // Cleanup of old prim geometry and Bodies + if (IsPhysical && Body != IntPtr.Zero) + { + if (childPrim) + { + if (_parent != null) + { + OdePrim parent = (OdePrim)_parent; + parent.ChildDelink(this); + } + } + else + { + disableBody(); + } + } + try + { + d.GeomDestroy(prim_geom); + } + catch (System.AccessViolationException) + { + prim_geom = IntPtr.Zero; + m_log.Error("[PHYSICS]: PrimGeom dead"); + } + prim_geom = IntPtr.Zero; + // we don't need to do space calculation because the client sends a position update also. + if (_size.X <= 0) _size.X = 0.01f; + if (_size.Y <= 0) _size.Y = 0.01f; + if (_size.Z <= 0) _size.Z = 0.01f; + // Construction of new prim + + if (_parent_scene.needsMeshing(_pbs)) + { + // Don't need to re-enable body.. it's done in SetMesh + float meshlod = _parent_scene.meshSculptLOD; + + if (IsPhysical) + meshlod = _parent_scene.MeshSculptphysicalLOD; + + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); + // createmesh returns null when it doesn't mesh. + CreateGeom(m_targetSpace, mesh); + } + else + { + _mesh = null; +//Console.WriteLine("changeshape"); + CreateGeom(m_targetSpace, null); + } + + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + //myrot.W = _orientation.w; + myrot.W = _orientation.W; + myrot.X = _orientation.X; + myrot.Y = _orientation.Y; + myrot.Z = _orientation.Z; + d.GeomSetQuaternion(prim_geom, ref myrot); + + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == IntPtr.Zero) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + if (Body != IntPtr.Zero) + { + d.BodyEnable(Body); + } + } + _parent_scene.geom_name_map[prim_geom] = oldname; + + changeSelectedStatus(timestamp); + if (childPrim) + { + if (_parent is OdePrim) + { + OdePrim parent = (OdePrim)_parent; + parent.ChildSetGeom(this); + } + } + resetCollisionAccounting(); + m_taintshape = false; + } + + public void changeAddForce(float timestamp) + { + if (!m_isSelected) + { + lock (m_forcelist) + { + //m_log.Info("[PHYSICS]: dequeing forcelist"); + if (IsPhysical) + { + Vector3 iforce = Vector3.Zero; + int i = 0; + try + { + for (i = 0; i < m_forcelist.Count; i++) + { + + iforce = iforce + (m_forcelist[i] * 100); + } + } + catch (IndexOutOfRangeException) + { + m_forcelist = new List(); + m_collisionscore = 0; + m_interpenetrationcount = 0; + m_taintforce = false; + return; + } + catch (ArgumentOutOfRangeException) + { + m_forcelist = new List(); + m_collisionscore = 0; + m_interpenetrationcount = 0; + m_taintforce = false; + return; + } + d.BodyEnable(Body); + d.BodyAddForce(Body, iforce.X, iforce.Y, iforce.Z); + } + m_forcelist.Clear(); + } + + m_collisionscore = 0; + m_interpenetrationcount = 0; + } + + m_taintforce = false; + + } + + + + public void changeSetTorque(float timestamp) + { + if (!m_isSelected) + { + if (IsPhysical && Body != IntPtr.Zero) + { + d.BodySetTorque(Body, m_taintTorque.X, m_taintTorque.Y, m_taintTorque.Z); + } + } + + m_taintTorque = Vector3.Zero; + } + + public void changeAddAngularForce(float timestamp) + { + if (!m_isSelected) + { + lock (m_angularforcelist) + { + //m_log.Info("[PHYSICS]: dequeing forcelist"); + if (IsPhysical) + { + Vector3 iforce = Vector3.Zero; + for (int i = 0; i < m_angularforcelist.Count; i++) + { + iforce = iforce + (m_angularforcelist[i] * 100); + } + d.BodyEnable(Body); + d.BodyAddTorque(Body, iforce.X, iforce.Y, iforce.Z); + + } + m_angularforcelist.Clear(); + } + + m_collisionscore = 0; + m_interpenetrationcount = 0; + } + + m_taintaddangularforce = false; + } + + private void changevelocity(float timestep) + { + if (!m_isSelected) + { + Thread.Sleep(20); + if (IsPhysical) + { + if (Body != IntPtr.Zero) + { + d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); + } + } + + //resetCollisionAccounting(); + } + m_taintVelocity = Vector3.Zero; + } + + public override bool IsPhysical + { + get { return m_isphysical; } + set { + m_isphysical = value; + if (!m_isphysical) // Zero the remembered last velocity + m_lastVelocity = Vector3.Zero; + } + } + + public void setPrimForRemoval() + { + m_taintremove = true; + } + + public override bool Flying + { + // no flying prims for you + get { return false; } + set { } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return m_throttleUpdates; } + set { m_throttleUpdates = value; } + } + + public override bool Stopped + { + get { return _zeroFlag; } + } + + public override Vector3 Position + { + get { return _position; } + + set { _position = value; + //m_log.Info("[PHYSICS]: " + _position.ToString()); + } + } + + public override Vector3 Size + { + get { return _size; } + set + { + if (value.IsFinite()) + { + _size = value; + } + else + { + m_log.Warn("[PHYSICS]: Got NaN Size on object"); + } + } + } + + public override float Mass + { + get { return CalculateMass(); } + } + + public override Vector3 Force + { + //get { return Vector3.Zero; } + get { return m_force; } + set + { + if (value.IsFinite()) + { + m_force = value; + } + else + { + m_log.Warn("[PHYSICS]: NaN in Force Applied to an Object"); + } + } + } + + public override int VehicleType + { + get { return (int)m_vehicle.Type; } + set { m_vehicle.ProcessTypeChange((Vehicle)value); } + } + + public override void VehicleFloatParam(int param, float value) + { + m_vehicle.ProcessFloatVehicleParam((Vehicle) param, value); + } + + public override void VehicleVectorParam(int param, Vector3 value) + { + m_vehicle.ProcessVectorVehicleParam((Vehicle) param, value); + } + + public override void VehicleRotationParam(int param, Quaternion rotation) + { + m_vehicle.ProcessRotationVehicleParam((Vehicle) param, rotation); + } + + public override void SetVolumeDetect(int param) + { + lock (_parent_scene.OdeLock) + { + m_isVolumeDetect = (param!=0); + } + } + + public override Vector3 CenterOfMass + { + get { return Vector3.Zero; } + } + + public override Vector3 GeometricCenter + { + get { return Vector3.Zero; } + } + + public override PrimitiveBaseShape Shape + { + set + { + _pbs = value; + m_taintshape = true; + } + } + + public override Vector3 Velocity + { + get + { + // Averate previous velocity with the new one so + // client object interpolation works a 'little' better + if (_zeroFlag) + return Vector3.Zero; + + Vector3 returnVelocity = Vector3.Zero; + returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2; + returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2; + returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2; + return returnVelocity; + } + set + { + if (value.IsFinite()) + { + _velocity = value; + + m_taintVelocity = value; + _parent_scene.AddPhysicsActorTaint(this); + } + else + { + m_log.Warn("[PHYSICS]: Got NaN Velocity in Object"); + } + + } + } + + public override Vector3 Torque + { + get + { + if (!m_isphysical || Body == IntPtr.Zero) + return Vector3.Zero; + + return _torque; + } + + set + { + if (value.IsFinite()) + { + m_taintTorque = value; + _parent_scene.AddPhysicsActorTaint(this); + } + else + { + m_log.Warn("[PHYSICS]: Got NaN Torque in Object"); + } + } + } + + public override float CollisionScore + { + get { return m_collisionscore; } + set { m_collisionscore = value; } + } + + public override bool Kinematic + { + get { return false; } + set { } + } + + public override Quaternion Orientation + { + get { return _orientation; } + set + { + if (QuaternionIsFinite(value)) + { + _orientation = value; + } + else + m_log.Warn("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object"); + + } + } + + internal static bool QuaternionIsFinite(Quaternion q) + { + if (Single.IsNaN(q.X) || Single.IsInfinity(q.X)) + return false; + if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y)) + return false; + if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z)) + return false; + if (Single.IsNaN(q.W) || Single.IsInfinity(q.W)) + return false; + return true; + } + + public override Vector3 Acceleration + { + get { return _acceleration; } + } + + + public void SetAcceleration(Vector3 accel) + { + _acceleration = accel; + } + + public override void AddForce(Vector3 force, bool pushforce) + { + if (force.IsFinite()) + { + lock (m_forcelist) + m_forcelist.Add(force); + + m_taintforce = true; + } + else + { + m_log.Warn("[PHYSICS]: Got Invalid linear force vector from Scene in Object"); + } + //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString()); + } + + public override void AddAngularForce(Vector3 force, bool pushforce) + { + if (force.IsFinite()) + { + m_angularforcelist.Add(force); + m_taintaddangularforce = true; + } + else + { + m_log.Warn("[PHYSICS]: Got Invalid Angular force vector from Scene in Object"); + } + } + + public override Vector3 RotationalVelocity + { + get + { + Vector3 pv = Vector3.Zero; + if (_zeroFlag) + return pv; + m_lastUpdateSent = false; + + if (m_rotationalVelocity.ApproxEquals(pv, 0.2f)) + return pv; + + return m_rotationalVelocity; + } + set + { + if (value.IsFinite()) + { + m_rotationalVelocity = value; + } + else + { + m_log.Warn("[PHYSICS]: Got NaN RotationalVelocity in Object"); + } + } + } + + public override void CrossingFailure() + { + m_crossingfailures++; + if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds) + { + base.RaiseOutOfBounds(_position); + return; + } + else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds) + { + m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName); + } + } + + public override float Buoyancy + { + get { return m_buoyancy; } + set { m_buoyancy = value; } + } + + public override void link(PhysicsActor obj) + { + m_taintparent = obj; + } + + public override void delink() + { + m_taintparent = null; + } + + public override void LockAngularMotion(Vector3 axis) + { + // reverse the zero/non zero values for ODE. + if (axis.IsFinite()) + { + axis.X = (axis.X > 0) ? 1f : 0f; + axis.Y = (axis.Y > 0) ? 1f : 0f; + axis.Z = (axis.Z > 0) ? 1f : 0f; + m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); + m_taintAngularLock = axis; + } + else + { + m_log.Warn("[PHYSICS]: Got NaN locking axis from Scene on Object"); + } + } + + public void UpdatePositionAndVelocity() + { + // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! + if (_parent == null) + { + Vector3 pv = Vector3.Zero; + bool lastZeroFlag = _zeroFlag; + if (Body != (IntPtr)0) // FIXME -> or if it is a joint + { + d.Vector3 vec = d.BodyGetPosition(Body); + d.Quaternion ori = d.BodyGetQuaternion(Body); + d.Vector3 vel = d.BodyGetLinearVel(Body); + d.Vector3 rotvel = d.BodyGetAngularVel(Body); + d.Vector3 torque = d.BodyGetTorque(Body); + _torque = new Vector3(torque.X, torque.Y, torque.Z); + Vector3 l_position = Vector3.Zero; + Quaternion l_orientation = Quaternion.Identity; + + // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) + //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + + m_lastposition = _position; + m_lastorientation = _orientation; + + l_position.X = vec.X; + l_position.Y = vec.Y; + l_position.Z = vec.Z; + l_orientation.X = ori.X; + l_orientation.Y = ori.Y; + l_orientation.Z = ori.Z; + l_orientation.W = ori.W; + +// if(l_position.Y != m_lastposition.Y){ +// Console.WriteLine("UP&V {0} {1}", m_primName, l_position); +// } + + if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f) + { + //base.RaiseOutOfBounds(l_position); + + if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds) + { + _position = l_position; + //_parent_scene.remActivePrim(this); + if (_parent == null) + base.RequestPhysicsterseUpdate(); + return; + } + else + { + if (_parent == null) + base.RaiseOutOfBounds(l_position); + return; + } + } + + if (l_position.Z < 0) + { + // This is so prim that get lost underground don't fall forever and suck up + // + // Sim resources and memory. + // Disables the prim's movement physics.... + // It's a hack and will generate a console message if it fails. + + //IsPhysical = false; + if (_parent == null) + base.RaiseOutOfBounds(_position); + + _acceleration.X = 0; + _acceleration.Y = 0; + _acceleration.Z = 0; + + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + + if (_parent == null) + base.RequestPhysicsterseUpdate(); + + m_throttleUpdates = false; + throttleCounter = 0; + _zeroFlag = true; + //outofBounds = true; + } + + //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)); +//Console.WriteLine("Adiff " + m_primName + " = " + Adiff); + if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) + && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) + && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) +// && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01)) + && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large + { + _zeroFlag = true; +//Console.WriteLine("ZFT 2"); + m_throttleUpdates = false; + } + else + { + //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString()); + _zeroFlag = false; + m_lastUpdateSent = false; + //m_throttleUpdates = false; + } + + if (_zeroFlag) + { + _velocity.X = 0.0f; + _velocity.Y = 0.0f; + _velocity.Z = 0.0f; + + _acceleration.X = 0; + _acceleration.Y = 0; + _acceleration.Z = 0; + + //_orientation.w = 0f; + //_orientation.X = 0f; + //_orientation.Y = 0f; + //_orientation.Z = 0f; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + if (!m_lastUpdateSent) + { + m_throttleUpdates = false; + throttleCounter = 0; + m_rotationalVelocity = pv; + + if (_parent == null) + { + base.RequestPhysicsterseUpdate(); + } + + m_lastUpdateSent = true; + } + } + else + { + if (lastZeroFlag != _zeroFlag) + { + if (_parent == null) + { + base.RequestPhysicsterseUpdate(); + } + } + + m_lastVelocity = _velocity; + + _position = l_position; + + _velocity.X = vel.X; + _velocity.Y = vel.Y; + _velocity.Z = vel.Z; + + _acceleration = ((_velocity - m_lastVelocity) / 0.1f); + _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); + //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); + + if (_velocity.ApproxEquals(pv, 0.5f)) + { + m_rotationalVelocity = pv; + } + else + { + m_rotationalVelocity = new Vector3(rotvel.X, rotvel.Y, rotvel.Z); + } + + //m_log.Debug("ODE: " + m_rotationalVelocity.ToString()); + _orientation.X = ori.X; + _orientation.Y = ori.Y; + _orientation.Z = ori.Z; + _orientation.W = ori.W; + m_lastUpdateSent = false; + if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) + { + if (_parent == null) + { + base.RequestPhysicsterseUpdate(); + } + } + else + { + throttleCounter++; + } + } + m_lastposition = l_position; + } + else + { + // Not a body.. so Make sure the client isn't interpolating + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + + _acceleration.X = 0; + _acceleration.Y = 0; + _acceleration.Z = 0; + + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + _zeroFlag = true; + } + } + } + + public override bool FloatOnWater + { + set { + m_taintCollidesWater = value; + _parent_scene.AddPhysicsActorTaint(this); + } + } + + public override void SetMomentum(Vector3 momentum) + { + } + + public override Vector3 PIDTarget + { + set + { + if (value.IsFinite()) + { + m_PIDTarget = value; + } + else + m_log.Warn("[PHYSICS]: Got NaN PIDTarget from Scene on Object"); + } + } + public override bool PIDActive { set { m_usePID = value; } } + public override float PIDTau { set { m_PIDTau = value; } } + + // For RotLookAt + public override Quaternion APIDTarget { set { m_APIDTarget = value; } } + public override bool APIDActive { set { m_useAPID = value; } } + public override float APIDStrength { set { m_APIDStrength = value; } } + public override float APIDDamping { set { m_APIDDamping = value; } } + + public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } + public override bool PIDHoverActive { set { m_useHoverPID = value; } } + public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } + public override float PIDHoverTau { set { m_PIDHoverTau = value; } } + + private void createAMotor(Vector3 axis) + { + if (Body == IntPtr.Zero) + return; + + if (Amotor != IntPtr.Zero) + { + d.JointDestroy(Amotor); + Amotor = IntPtr.Zero; + } + + float axisnum = 3; + + axisnum = (axisnum - (axis.X + axis.Y + axis.Z)); + + // PhysicsVector totalSize = new PhysicsVector(_size.X, _size.Y, _size.Z); + + + // Inverse Inertia Matrix, set the X, Y, and/r Z inertia to 0 then invert it again. + d.Mass objMass; + d.MassSetZero(out objMass); + DMassCopy(ref pMass, ref objMass); + + //m_log.DebugFormat("1-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); + + Matrix4 dMassMat = FromDMass(objMass); + + Matrix4 mathmat = Inverse(dMassMat); + + /* + //m_log.DebugFormat("2-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", mathmat[0, 0], mathmat[0, 1], mathmat[0, 2], mathmat[1, 0], mathmat[1, 1], mathmat[1, 2], mathmat[2, 0], mathmat[2, 1], mathmat[2, 2]); + + mathmat = Inverse(mathmat); + + + objMass = FromMatrix4(mathmat, ref objMass); + //m_log.DebugFormat("3-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); + + mathmat = Inverse(mathmat); + */ + if (axis.X == 0) + { + mathmat.M33 = 50.0000001f; + //objMass.I.M22 = 0; + } + if (axis.Y == 0) + { + mathmat.M22 = 50.0000001f; + //objMass.I.M11 = 0; + } + if (axis.Z == 0) + { + mathmat.M11 = 50.0000001f; + //objMass.I.M00 = 0; + } + + + + mathmat = Inverse(mathmat); + objMass = FromMatrix4(mathmat, ref objMass); + //m_log.DebugFormat("4-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); + + //return; + if (d.MassCheck(ref objMass)) + { + d.BodySetMass(Body, ref objMass); + } + else + { + //m_log.Debug("[PHYSICS]: Mass invalid, ignoring"); + } + + if (axisnum <= 0) + return; + // int dAMotorEuler = 1; + + Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); + d.JointAttach(Amotor, Body, IntPtr.Zero); + d.JointSetAMotorMode(Amotor, 0); + + d.JointSetAMotorNumAxes(Amotor,(int)axisnum); + int i = 0; + + if (axis.X == 0) + { + d.JointSetAMotorAxis(Amotor, i, 0, 1, 0, 0); + i++; + } + + if (axis.Y == 0) + { + d.JointSetAMotorAxis(Amotor, i, 0, 0, 1, 0); + i++; + } + + if (axis.Z == 0) + { + d.JointSetAMotorAxis(Amotor, i, 0, 0, 0, 1); + i++; + } + + for (int j = 0; j < (int)axisnum; j++) + { + //d.JointSetAMotorAngle(Amotor, j, 0); + } + + //d.JointSetAMotorAngle(Amotor, 1, 0); + //d.JointSetAMotorAngle(Amotor, 2, 0); + + // These lowstops and high stops are effectively (no wiggle room) + d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0f); + //d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 9000f); + d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.FMax, Mass * 50f);// + + } + + public Matrix4 FromDMass(d.Mass pMass) + { + Matrix4 obj; + obj.M11 = pMass.I.M00; + obj.M12 = pMass.I.M01; + obj.M13 = pMass.I.M02; + obj.M14 = 0; + obj.M21 = pMass.I.M10; + obj.M22 = pMass.I.M11; + obj.M23 = pMass.I.M12; + obj.M24 = 0; + obj.M31 = pMass.I.M20; + obj.M32 = pMass.I.M21; + obj.M33 = pMass.I.M22; + obj.M34 = 0; + obj.M41 = 0; + obj.M42 = 0; + obj.M43 = 0; + obj.M44 = 1; + return obj; + } + + public d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj) + { + obj.I.M00 = pMat[0, 0]; + obj.I.M01 = pMat[0, 1]; + obj.I.M02 = pMat[0, 2]; + obj.I.M10 = pMat[1, 0]; + obj.I.M11 = pMat[1, 1]; + obj.I.M12 = pMat[1, 2]; + obj.I.M20 = pMat[2, 0]; + obj.I.M21 = pMat[2, 1]; + obj.I.M22 = pMat[2, 2]; + return obj; + } + + public override void SubscribeEvents(int ms) + { + m_eventsubscription = ms; + _parent_scene.addCollisionEventReporting(this); + } + + public override void UnSubscribeEvents() + { + _parent_scene.remCollisionEventReporting(this); + m_eventsubscription = 0; + } + + public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) + { + if (CollisionEventsThisFrame == null) + CollisionEventsThisFrame = new CollisionEventUpdate(); + CollisionEventsThisFrame.addCollider(CollidedWith, contact); + } + + public void SendCollisions() + { + if (CollisionEventsThisFrame == null) + return; + + base.SendCollisionUpdate(CollisionEventsThisFrame); + + if (CollisionEventsThisFrame.m_objCollisionList.Count == 0) + CollisionEventsThisFrame = null; + else + CollisionEventsThisFrame = new CollisionEventUpdate(); + } + + public override bool SubscribedEvents() + { + if (m_eventsubscription > 0) + return true; + return false; + } + + public static Matrix4 Inverse(Matrix4 pMat) + { + if (determinant3x3(pMat) == 0) + { + return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible + } + + + + return (Adjoint(pMat) / determinant3x3(pMat)); + } + + public static Matrix4 Adjoint(Matrix4 pMat) + { + Matrix4 adjointMatrix = new Matrix4(); + for (int i=0; i<4; i++) + { + for (int j=0; j<4; j++) + { + Matrix4SetValue(ref adjointMatrix, i, j, (float)(Math.Pow(-1, i + j) * (determinant3x3(Minor(pMat, i, j))))); + } + } + + adjointMatrix = Transpose(adjointMatrix); + return adjointMatrix; + } + + public static Matrix4 Minor(Matrix4 matrix, int iRow, int iCol) + { + Matrix4 minor = new Matrix4(); + int m = 0, n = 0; + for (int i = 0; i < 4; i++) + { + if (i == iRow) + continue; + n = 0; + for (int j = 0; j < 4; j++) + { + if (j == iCol) + continue; + Matrix4SetValue(ref minor, m,n, matrix[i, j]); + n++; + } + m++; + } + return minor; + } + + public static Matrix4 Transpose(Matrix4 pMat) + { + Matrix4 transposeMatrix = new Matrix4(); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + Matrix4SetValue(ref transposeMatrix, i, j, pMat[j, i]); + return transposeMatrix; + } + + public static void Matrix4SetValue(ref Matrix4 pMat, int r, int c, float val) + { + switch (r) + { + case 0: + switch (c) + { + case 0: + pMat.M11 = val; + break; + case 1: + pMat.M12 = val; + break; + case 2: + pMat.M13 = val; + break; + case 3: + pMat.M14 = val; + break; + } + + break; + case 1: + switch (c) + { + case 0: + pMat.M21 = val; + break; + case 1: + pMat.M22 = val; + break; + case 2: + pMat.M23 = val; + break; + case 3: + pMat.M24 = val; + break; + } + + break; + case 2: + switch (c) + { + case 0: + pMat.M31 = val; + break; + case 1: + pMat.M32 = val; + break; + case 2: + pMat.M33 = val; + break; + case 3: + pMat.M34 = val; + break; + } + + break; + case 3: + switch (c) + { + case 0: + pMat.M41 = val; + break; + case 1: + pMat.M42 = val; + break; + case 2: + pMat.M43 = val; + break; + case 3: + pMat.M44 = val; + break; + } + + break; + } + } + private static float determinant3x3(Matrix4 pMat) + { + float det = 0; + float diag1 = pMat[0, 0]*pMat[1, 1]*pMat[2, 2]; + float diag2 = pMat[0, 1]*pMat[2, 1]*pMat[2, 0]; + float diag3 = pMat[0, 2]*pMat[1, 0]*pMat[2, 1]; + float diag4 = pMat[2, 0]*pMat[1, 1]*pMat[0, 2]; + float diag5 = pMat[2, 1]*pMat[1, 2]*pMat[0, 0]; + float diag6 = pMat[2, 2]*pMat[1, 0]*pMat[0, 1]; + + det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6); + return det; + + } + + private static void DMassCopy(ref d.Mass src, ref d.Mass dst) + { + dst.c.W = src.c.W; + dst.c.X = src.c.X; + dst.c.Y = src.c.Y; + dst.c.Z = src.c.Z; + dst.mass = src.mass; + dst.I.M00 = src.I.M00; + dst.I.M01 = src.I.M01; + dst.I.M02 = src.I.M02; + dst.I.M10 = src.I.M10; + dst.I.M11 = src.I.M11; + dst.I.M12 = src.I.M12; + dst.I.M20 = src.I.M20; + dst.I.M21 = src.I.M21; + dst.I.M22 = src.I.M22; + } + + public override void SetMaterial(int pMaterial) + { + m_material = pMaterial; + } + + } +} diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs b/OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs new file mode 100644 index 0000000..7314107 --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/ODERayCastRequestManager.cs @@ -0,0 +1,375 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using OpenMetaverse; +using OpenSim.Region.Physics.Manager; +using Ode.NET; +using log4net; + +namespace OpenSim.Region.Physics.OdePlugin +{ + /// + /// Processes raycast requests as ODE is in a state to be able to do them. + /// This ensures that it's thread safe and there will be no conflicts. + /// Requests get returned by a different thread then they were requested by. + /// + public class ODERayCastRequestManager + { + /// + /// Pending Raycast Requests + /// + protected List m_PendingRequests = new List(); + + /// + /// Scene that created this object. + /// + private OdeScene m_scene; + + /// + /// ODE contact array to be filled by the collision testing + /// + d.ContactGeom[] contacts = new d.ContactGeom[5]; + + /// + /// ODE near callback delegate + /// + private d.NearCallback nearCallback; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private List m_contactResults = new List(); + + + public ODERayCastRequestManager(OdeScene pScene) + { + m_scene = pScene; + nearCallback = near; + + } + + /// + /// Queues a raycast + /// + /// Origin of Ray + /// Ray normal + /// Ray length + /// Return method to send the results + public void QueueRequest(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) + { + lock (m_PendingRequests) + { + ODERayCastRequest req = new ODERayCastRequest(); + req.callbackMethod = retMethod; + req.length = length; + req.Normal = direction; + req.Origin = position; + + m_PendingRequests.Add(req); + } + } + + /// + /// Process all queued raycast requests + /// + /// Time in MS the raycasts took to process. + public int ProcessQueuedRequests() + { + int time = System.Environment.TickCount; + lock (m_PendingRequests) + { + if (m_PendingRequests.Count > 0) + { + ODERayCastRequest[] reqs = m_PendingRequests.ToArray(); + for (int i = 0; i < reqs.Length; i++) + { + if (reqs[i].callbackMethod != null) // quick optimization here, don't raycast + RayCast(reqs[i]); // if there isn't anyone to send results + } + /* + foreach (ODERayCastRequest req in m_PendingRequests) + { + if (req.callbackMethod != null) // quick optimization here, don't raycast + RayCast(req); // if there isn't anyone to send results to + + } + */ + m_PendingRequests.Clear(); + } + } + + lock (m_contactResults) + m_contactResults.Clear(); + + return System.Environment.TickCount - time; + } + + /// + /// Method that actually initiates the raycast + /// + /// + private void RayCast(ODERayCastRequest req) + { + // Create the ray + IntPtr ray = d.CreateRay(m_scene.space, req.length); + d.GeomRaySet(ray, req.Origin.X, req.Origin.Y, req.Origin.Z, req.Normal.X, req.Normal.Y, req.Normal.Z); + + // Collide test + d.SpaceCollide2(m_scene.space, ray, IntPtr.Zero, nearCallback); + + // Remove Ray + d.GeomDestroy(ray); + + + // Define default results + bool hitYN = false; + uint hitConsumerID = 0; + float distance = 999999999999f; + Vector3 closestcontact = new Vector3(99999f, 99999f, 99999f); + Vector3 snormal = Vector3.Zero; + + // Find closest contact and object. + lock (m_contactResults) + { + foreach (ContactResult cResult in m_contactResults) + { + if (Vector3.Distance(req.Origin, cResult.Pos) < Vector3.Distance(req.Origin, closestcontact)) + { + closestcontact = cResult.Pos; + hitConsumerID = cResult.ConsumerID; + distance = cResult.Depth; + hitYN = true; + snormal = cResult.Normal; + } + } + + m_contactResults.Clear(); + } + + // Return results + if (req.callbackMethod != null) + req.callbackMethod(hitYN, closestcontact, hitConsumerID, distance, snormal); + } + + // This is the standard Near. Uses space AABBs to speed up detection. + private void near(IntPtr space, IntPtr g1, IntPtr g2) + { + + //Don't test against heightfield Geom, or you'll be sorry! + + /* + terminate called after throwing an instance of 'std::bad_alloc' + what(): std::bad_alloc + Stacktrace: + + at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0x00004> + at (wrapper managed-to-native) Ode.NET.d.Collide (intptr,intptr,int,Ode.NET.d/ContactGeom[],int) <0xffffffff> + at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0x00280> + at (wrapper native-to-managed) OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.near (intptr,intptr,intptr) <0xfff + fffff> + at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0x00004> + at (wrapper managed-to-native) Ode.NET.d.SpaceCollide2 (intptr,intptr,intptr,Ode.NET.d/NearCallback) <0xffffffff> + at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.RayCast (OpenSim.Region.Physics.OdePlugin.ODERayCastRequest) < + 0x00114> + at OpenSim.Region.Physics.OdePlugin.ODERayCastRequestManager.ProcessQueuedRequests () <0x000eb> + at OpenSim.Region.Physics.OdePlugin.OdeScene.Simulate (single) <0x017e6> + at OpenSim.Region.Framework.Scenes.SceneGraph.UpdatePhysics (double) <0x00042> + at OpenSim.Region.Framework.Scenes.Scene.Update () <0x0039e> + at OpenSim.Region.Framework.Scenes.Scene.Heartbeat (object) <0x00019> + at (wrapper runtime-invoke) object.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <0xffffffff> + + Native stacktrace: + + mono [0x80d2a42] + [0xb7f5840c] + /lib/i686/cmov/libc.so.6(abort+0x188) [0xb7d1a018] + /usr/lib/libstdc++.so.6(_ZN9__gnu_cxx27__verbose_terminate_handlerEv+0x158) [0xb45fc988] + /usr/lib/libstdc++.so.6 [0xb45fa865] + /usr/lib/libstdc++.so.6 [0xb45fa8a2] + /usr/lib/libstdc++.so.6 [0xb45fa9da] + /usr/lib/libstdc++.so.6(_Znwj+0x83) [0xb45fb033] + /usr/lib/libstdc++.so.6(_Znaj+0x1d) [0xb45fb11d] + libode.so(_ZN13dxHeightfield23dCollideHeightfieldZoneEiiiiP6dxGeomiiP12dContactGeomi+0xd04) [0xb46678e4] + libode.so(_Z19dCollideHeightfieldP6dxGeomS0_iP12dContactGeomi+0x54b) [0xb466832b] + libode.so(dCollide+0x102) [0xb46571b2] + [0x95cfdec9] + [0x8ea07fe1] + [0xab260146] + libode.so [0xb465a5c4] + libode.so(_ZN11dxHashSpace8collide2EPvP6dxGeomPFvS0_S2_S2_E+0x75) [0xb465bcf5] + libode.so(dSpaceCollide2+0x177) [0xb465ac67] + [0x95cf978e] + [0x8ea07945] + [0x95cf2bbc] + [0xab2787e7] + [0xab419fb3] + [0xab416657] + [0xab415bda] + [0xb609b08e] + mono(mono_runtime_delegate_invoke+0x34) [0x8192534] + mono [0x81a2f0f] + mono [0x81d28b6] + mono [0x81ea2c6] + /lib/i686/cmov/libpthread.so.0 [0xb7e744c0] + /lib/i686/cmov/libc.so.6(clone+0x5e) [0xb7dcd6de] + */ + + // Exclude heightfield geom + + if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) + return; + if (d.GeomGetClass(g1) == d.GeomClassID.HeightfieldClass || d.GeomGetClass(g2) == d.GeomClassID.HeightfieldClass) + return; + + // Raytest against AABBs of spaces first, then dig into the spaces it hits for actual geoms. + if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) + { + if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) + return; + + // Separating static prim geometry spaces. + // We'll be calling near recursivly if one + // of them is a space to find all of the + // contact points in the space + try + { + d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to collide test a space"); + return; + } + //Colliding a space or a geom with a space or a geom. so drill down + + //Collide all geoms in each space.. + //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); + //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); + return; + } + + if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) + return; + + int count = 0; + try + { + + if (g1 == g2) + return; // Can't collide with yourself + + lock (contacts) + { + count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); + } + } + catch (SEHException) + { + m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); + } + catch (Exception e) + { + m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message); + return; + } + + PhysicsActor p1 = null; + PhysicsActor p2 = null; + + if (g1 != IntPtr.Zero) + m_scene.actor_name_map.TryGetValue(g1, out p1); + + if (g2 != IntPtr.Zero) + m_scene.actor_name_map.TryGetValue(g1, out p2); + + // Loop over contacts, build results. + for (int i = 0; i < count; i++) + { + if (p1 != null) { + if (p1 is OdePrim) + { + ContactResult collisionresult = new ContactResult(); + + collisionresult.ConsumerID = ((OdePrim)p1).m_localID; + collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z); + collisionresult.Depth = contacts[i].depth; + collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y, + contacts[i].normal.Z); + lock (m_contactResults) + m_contactResults.Add(collisionresult); + } + } + + if (p2 != null) + { + if (p2 is OdePrim) + { + ContactResult collisionresult = new ContactResult(); + + collisionresult.ConsumerID = ((OdePrim)p2).m_localID; + collisionresult.Pos = new Vector3(contacts[i].pos.X, contacts[i].pos.Y, contacts[i].pos.Z); + collisionresult.Depth = contacts[i].depth; + collisionresult.Normal = new Vector3(contacts[i].normal.X, contacts[i].normal.Y, + contacts[i].normal.Z); + + lock (m_contactResults) + m_contactResults.Add(collisionresult); + } + } + + + } + + } + + /// + /// Dereference the creator scene so that it can be garbage collected if needed. + /// + internal void Dispose() + { + m_scene = null; + } + } + + public struct ODERayCastRequest + { + public Vector3 Origin; + public Vector3 Normal; + public float length; + public RaycastCallback callbackMethod; + } + + public struct ContactResult + { + public Vector3 Pos; + public float Depth; + public uint ConsumerID; + public Vector3 Normal; + } +} diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs new file mode 100644 index 0000000..b4a3c48 --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/OdePhysicsJoint.cs @@ -0,0 +1,48 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using OpenMetaverse; +using Ode.NET; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; +using OpenSim.Region.Physics.OdePlugin; + +namespace OpenSim.Region.Physics.OdePlugin +{ + class OdePhysicsJoint : PhysicsJoint + { + public override bool IsInPhysicsEngine + { + get + { + return (jointID != IntPtr.Zero); + } + } + public IntPtr jointID; + } +} diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs new file mode 100644 index 0000000..f48649e --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs @@ -0,0 +1,3865 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +//#define USE_DRAWSTUFF + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using System.IO; +using System.Diagnostics; +using log4net; +using Nini.Config; +using Ode.NET; +#if USE_DRAWSTUFF +using Drawstuff.NET; +#endif +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; +using OpenMetaverse; + +//using OpenSim.Region.Physics.OdePlugin.Meshing; + +namespace OpenSim.Region.Physics.OdePlugin +{ + /// + /// ODE plugin + /// + public class OdePlugin : IPhysicsPlugin + { + //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + private CollisionLocker ode; + private OdeScene _mScene; + + public OdePlugin() + { + ode = new CollisionLocker(); + } + + public bool Init() + { + return true; + } + + public PhysicsScene GetScene(String sceneIdentifier) + { + if (_mScene == null) + { + // Initializing ODE only when a scene is created allows alternative ODE plugins to co-habit (according to + // http://opensimulator.org/mantis/view.php?id=2750). + d.InitODE(); + + _mScene = new OdeScene(ode, sceneIdentifier); + } + return (_mScene); + } + + public string GetName() + { + return ("ChODE"); + } + + public void Dispose() + { + } + } + + public enum StatusIndicators : int + { + Generic = 0, + Start = 1, + End = 2 + } + + public struct sCollisionData + { + public uint ColliderLocalId; + public uint CollidedWithLocalId; + public int NumberOfCollisions; + public int CollisionType; + public int StatusIndicator; + public int lastframe; + } + + [Flags] + public enum CollisionCategories : int + { + Disabled = 0, + Geom = 0x00000001, + Body = 0x00000002, + Space = 0x00000004, + Character = 0x00000008, + Land = 0x00000010, + Water = 0x00000020, + Wind = 0x00000040, + Sensor = 0x00000080, + Selected = 0x00000100 + } + + /// + /// Material type for a primitive + /// + public enum Material : int + { + /// + Stone = 0, + /// + Metal = 1, + /// + Glass = 2, + /// + Wood = 3, + /// + Flesh = 4, + /// + Plastic = 5, + /// + Rubber = 6 + + } + + public sealed class OdeScene : PhysicsScene + { + private readonly ILog m_log; + // private Dictionary m_storedCollisions = new Dictionary(); + + CollisionLocker ode; + + private Random fluidRandomizer = new Random(Environment.TickCount); + + private const uint m_regionWidth = Constants.RegionSize; + private const uint m_regionHeight = Constants.RegionSize; + + private float ODE_STEPSIZE = 0.020f; + private float metersInSpace = 29.9f; + private float m_timeDilation = 1.0f; + + public float gravityx = 0f; + public float gravityy = 0f; + public float gravityz = -9.8f; + + private float contactsurfacelayer = 0.001f; + + private int worldHashspaceLow = -4; + private int worldHashspaceHigh = 128; + + private int smallHashspaceLow = -4; + private int smallHashspaceHigh = 66; + + private float waterlevel = 0f; + private int framecount = 0; + //private int m_returncollisions = 10; + + private readonly IntPtr contactgroup; + + internal IntPtr LandGeom; + internal IntPtr WaterGeom; + + private float nmTerrainContactFriction = 255.0f; + private float nmTerrainContactBounce = 0.1f; + private float nmTerrainContactERP = 0.1025f; + + private float mTerrainContactFriction = 75f; + private float mTerrainContactBounce = 0.1f; + private float mTerrainContactERP = 0.05025f; + + private float nmAvatarObjectContactFriction = 250f; + private float nmAvatarObjectContactBounce = 0.1f; + + private float mAvatarObjectContactFriction = 75f; + private float mAvatarObjectContactBounce = 0.1f; + + private float avPIDD = 3200f; + private float avPIDP = 1400f; + private float avCapRadius = 0.37f; + private float avStandupTensor = 2000000f; + private bool avCapsuleTilted = true; // true = old compatibility mode with leaning capsule; false = new corrected mode + public bool IsAvCapsuleTilted { get { return avCapsuleTilted; } set { avCapsuleTilted = value; } } + private float avDensity = 80f; + private float avHeightFudgeFactor = 0.52f; + private float avMovementDivisorWalk = 1.3f; + private float avMovementDivisorRun = 0.8f; + private float minimumGroundFlightOffset = 3f; + public float maximumMassObject = 10000.01f; + + public bool meshSculptedPrim = true; + public bool forceSimplePrimMeshing = false; + + public float meshSculptLOD = 32; + public float MeshSculptphysicalLOD = 16; + + public float geomDefaultDensity = 10.000006836f; + + public int geomContactPointsStartthrottle = 3; + public int geomUpdatesPerThrottledUpdate = 15; + + public float bodyPIDD = 35f; + public float bodyPIDG = 25; + + public int geomCrossingFailuresBeforeOutofbounds = 5; + + public float bodyMotorJointMaxforceTensor = 2; + + public int bodyFramesAutoDisable = 20; + + + + private float[] _watermap; + private bool m_filterCollisions = true; + + private d.NearCallback nearCallback; + public d.TriCallback triCallback; + public d.TriArrayCallback triArrayCallback; + private readonly HashSet _characters = new HashSet(); + private readonly HashSet _prims = new HashSet(); + private readonly HashSet _activeprims = new HashSet(); + private readonly HashSet _taintedPrimH = new HashSet(); + private readonly Object _taintedPrimLock = new Object(); + private readonly List _taintedPrimL = new List(); + private readonly HashSet _taintedActors = new HashSet(); + private readonly List _perloopContact = new List(); + private readonly List _collisionEventPrim = new List(); + private readonly HashSet _badCharacter = new HashSet(); + public Dictionary geom_name_map = new Dictionary(); + public Dictionary actor_name_map = new Dictionary(); + private bool m_NINJA_physics_joints_enabled = false; + //private Dictionary jointpart_name_map = new Dictionary(); + private readonly Dictionary> joints_connecting_actor = new Dictionary>(); + private d.ContactGeom[] contacts; + private readonly List requestedJointsToBeCreated = new List(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active + private readonly List pendingJoints = new List(); // can lock for longer. accessed only by OdeScene. + private readonly List activeJoints = new List(); // can lock for longer. accessed only by OdeScene. + private readonly List requestedJointsToBeDeleted = new List(); // lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active + private Object externalJointRequestsLock = new Object(); + private readonly Dictionary SOPName_to_activeJoint = new Dictionary(); + private readonly Dictionary SOPName_to_pendingJoint = new Dictionary(); + private readonly DoubleDictionary RegionTerrain = new DoubleDictionary(); + private readonly Dictionary TerrainHeightFieldHeights = new Dictionary(); + + private d.Contact contact; + private d.Contact TerrainContact; + private d.Contact AvatarMovementprimContact; + private d.Contact AvatarMovementTerrainContact; + private d.Contact WaterContact; + private d.Contact[,] m_materialContacts; + +//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it +//Ckrinke private int m_randomizeWater = 200; + private int m_physicsiterations = 10; + private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag + private readonly PhysicsActor PANull = new NullPhysicsActor(); + private float step_time = 0.0f; +//Ckrinke: Comment out until used. We declare it, initialize it, but do not use it +//Ckrinke private int ms = 0; + public IntPtr world; + //private bool returncollisions = false; + // private uint obj1LocalID = 0; + private uint obj2LocalID = 0; + //private int ctype = 0; + private OdeCharacter cc1; + private OdePrim cp1; + private OdeCharacter cc2; + private OdePrim cp2; + //private int cStartStop = 0; + //private string cDictKey = ""; + + public IntPtr space; + + //private IntPtr tmpSpace; + // split static geometry collision handling into spaces of 30 meters + public IntPtr[,] staticPrimspace; + + public Object OdeLock; + + public IMesher mesher; + + private IConfigSource m_config; + + public bool physics_logging = false; + public int physics_logging_interval = 0; + public bool physics_logging_append_existing_logfile = false; + + public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); + public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); + + // TODO: unused: private uint heightmapWidth = m_regionWidth + 1; + // TODO: unused: private uint heightmapHeight = m_regionHeight + 1; + // TODO: unused: private uint heightmapWidthSamples; + // TODO: unused: private uint heightmapHeightSamples; + + private volatile int m_global_contactcount = 0; + + private Vector3 m_worldOffset = Vector3.Zero; + public Vector2 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); + private PhysicsScene m_parentScene = null; + + private ODERayCastRequestManager m_rayCastManager; + + /// + /// Initiailizes the scene + /// Sets many properties that ODE requires to be stable + /// These settings need to be tweaked 'exactly' right or weird stuff happens. + /// + public OdeScene(CollisionLocker dode, string sceneIdentifier) + { + m_log + = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + sceneIdentifier); + + OdeLock = new Object(); + ode = dode; + nearCallback = near; + triCallback = TriCallback; + triArrayCallback = TriArrayCallback; + m_rayCastManager = new ODERayCastRequestManager(this); + lock (OdeLock) + { + // Create the world and the first space + world = d.WorldCreate(); + space = d.HashSpaceCreate(IntPtr.Zero); + + + contactgroup = d.JointGroupCreate(0); + //contactgroup + + d.WorldSetAutoDisableFlag(world, false); + #if USE_DRAWSTUFF + + Thread viewthread = new Thread(new ParameterizedThreadStart(startvisualization)); + viewthread.Start(); + #endif + } + + + _watermap = new float[258 * 258]; + + // Zero out the prim spaces array (we split our space into smaller spaces so + // we can hit test less. + } + +#if USE_DRAWSTUFF + public void startvisualization(object o) + { + ds.Functions fn; + fn.version = ds.VERSION; + fn.start = new ds.CallbackFunction(start); + fn.step = new ds.CallbackFunction(step); + fn.command = new ds.CallbackFunction(command); + fn.stop = null; + fn.path_to_textures = "./textures"; + string[] args = new string[0]; + ds.SimulationLoop(args.Length, args, 352, 288, ref fn); + } +#endif + + // Initialize the mesh plugin + public override void Initialise(IMesher meshmerizer, IConfigSource config) + { + mesher = meshmerizer; + m_config = config; + // Defaults + + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + avPIDD = 3200.0f; + avPIDP = 1400.0f; + avStandupTensor = 2000000f; + } + else + { + avPIDD = 2200.0f; + avPIDP = 900.0f; + avStandupTensor = 550000f; + } + + int contactsPerCollision = 80; + + if (m_config != null) + { + IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; + if (physicsconfig != null) + { + gravityx = physicsconfig.GetFloat("world_gravityx", 0f); + gravityy = physicsconfig.GetFloat("world_gravityy", 0f); + gravityz = physicsconfig.GetFloat("world_gravityz", -9.8f); + + worldHashspaceLow = physicsconfig.GetInt("world_hashspace_size_low", -4); + worldHashspaceHigh = physicsconfig.GetInt("world_hashspace_size_high", 128); + + metersInSpace = physicsconfig.GetFloat("meters_in_small_space", 29.9f); + smallHashspaceLow = physicsconfig.GetInt("small_hashspace_size_low", -4); + smallHashspaceHigh = physicsconfig.GetInt("small_hashspace_size_high", 66); + + contactsurfacelayer = physicsconfig.GetFloat("world_contact_surface_layer", 0.001f); + + nmTerrainContactFriction = physicsconfig.GetFloat("nm_terraincontact_friction", 255.0f); + nmTerrainContactBounce = physicsconfig.GetFloat("nm_terraincontact_bounce", 0.1f); + nmTerrainContactERP = physicsconfig.GetFloat("nm_terraincontact_erp", 0.1025f); + + mTerrainContactFriction = physicsconfig.GetFloat("m_terraincontact_friction", 75f); + mTerrainContactBounce = physicsconfig.GetFloat("m_terraincontact_bounce", 0.05f); + mTerrainContactERP = physicsconfig.GetFloat("m_terraincontact_erp", 0.05025f); + + nmAvatarObjectContactFriction = physicsconfig.GetFloat("objectcontact_friction", 250f); + nmAvatarObjectContactBounce = physicsconfig.GetFloat("objectcontact_bounce", 0.2f); + + mAvatarObjectContactFriction = physicsconfig.GetFloat("m_avatarobjectcontact_friction", 75f); + mAvatarObjectContactBounce = physicsconfig.GetFloat("m_avatarobjectcontact_bounce", 0.1f); + + ODE_STEPSIZE = physicsconfig.GetFloat("world_stepsize", 0.020f); + m_physicsiterations = physicsconfig.GetInt("world_internal_steps_without_collisions", 10); + + avDensity = physicsconfig.GetFloat("av_density", 80f); + avHeightFudgeFactor = physicsconfig.GetFloat("av_height_fudge_factor", 0.52f); + avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); + avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); + avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); + avCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); + + contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); + + geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3); + geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); + geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); + + geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f); + bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20); + + bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", 35f); + bodyPIDG = physicsconfig.GetFloat("body_pid_gain", 25f); + + forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing); + meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", true); + meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); + MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); + m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); + + if (Environment.OSVersion.Platform == PlatformID.Unix) + { + avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", 2200.0f); + avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", 900.0f); + avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_linux", 550000f); + bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_linux", 5f); + } + else + { + avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", 2200.0f); + avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", 900.0f); + avStandupTensor = physicsconfig.GetFloat("av_capsule_standup_tensor_win", 550000f); + bodyMotorJointMaxforceTensor = physicsconfig.GetFloat("body_motor_joint_maxforce_tensor_win", 5f); + } + + physics_logging = physicsconfig.GetBoolean("physics_logging", false); + physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); + physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false); + + m_NINJA_physics_joints_enabled = physicsconfig.GetBoolean("use_NINJA_physics_joints", false); + minimumGroundFlightOffset = physicsconfig.GetFloat("minimum_ground_flight_offset", 3f); + maximumMassObject = physicsconfig.GetFloat("maximum_mass_object", 10000.01f); + } + } + + contacts = new d.ContactGeom[contactsPerCollision]; + + staticPrimspace = new IntPtr[(int)(300 / metersInSpace), (int)(300 / metersInSpace)]; + + // Centeral contact friction and bounce + // ckrinke 11/10/08 Enabling soft_erp but not soft_cfm until I figure out why + // an avatar falls through in Z but not in X or Y when walking on a prim. + contact.surface.mode |= d.ContactFlags.SoftERP; + contact.surface.mu = nmAvatarObjectContactFriction; + contact.surface.bounce = nmAvatarObjectContactBounce; + contact.surface.soft_cfm = 0.010f; + contact.surface.soft_erp = 0.010f; + + // Terrain contact friction and Bounce + // This is the *non* moving version. Use this when an avatar + // isn't moving to keep it in place better + TerrainContact.surface.mode |= d.ContactFlags.SoftERP; + TerrainContact.surface.mu = nmTerrainContactFriction; + TerrainContact.surface.bounce = nmTerrainContactBounce; + TerrainContact.surface.soft_erp = nmTerrainContactERP; + + WaterContact.surface.mode |= (d.ContactFlags.SoftERP | d.ContactFlags.SoftCFM); + WaterContact.surface.mu = 0f; // No friction + WaterContact.surface.bounce = 0.0f; // No bounce + WaterContact.surface.soft_cfm = 0.010f; + WaterContact.surface.soft_erp = 0.010f; + + // Prim contact friction and bounce + // THis is the *non* moving version of friction and bounce + // Use this when an avatar comes in contact with a prim + // and is moving + AvatarMovementprimContact.surface.mu = mAvatarObjectContactFriction; + AvatarMovementprimContact.surface.bounce = mAvatarObjectContactBounce; + + // Terrain contact friction bounce and various error correcting calculations + // Use this when an avatar is in contact with the terrain and moving. + AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; + AvatarMovementTerrainContact.surface.mu = mTerrainContactFriction; + AvatarMovementTerrainContact.surface.bounce = mTerrainContactBounce; + AvatarMovementTerrainContact.surface.soft_erp = mTerrainContactERP; + + + /* + + Stone = 0, + /// + Metal = 1, + /// + Glass = 2, + /// + Wood = 3, + /// + Flesh = 4, + /// + Plastic = 5, + /// + Rubber = 6 + */ + + m_materialContacts = new d.Contact[7,2]; + + m_materialContacts[(int)Material.Stone, 0] = new d.Contact(); + m_materialContacts[(int)Material.Stone, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Stone, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Stone, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Stone, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Stone, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Stone, 1] = new d.Contact(); + m_materialContacts[(int)Material.Stone, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Stone, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Stone, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Stone, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Stone, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Metal, 0] = new d.Contact(); + m_materialContacts[(int)Material.Metal, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Metal, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Metal, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Metal, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Metal, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Metal, 1] = new d.Contact(); + m_materialContacts[(int)Material.Metal, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Metal, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Metal, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Metal, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Metal, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Glass, 0] = new d.Contact(); + m_materialContacts[(int)Material.Glass, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Glass, 0].surface.mu = 1f; + m_materialContacts[(int)Material.Glass, 0].surface.bounce = 0.5f; + m_materialContacts[(int)Material.Glass, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Glass, 0].surface.soft_erp = 0.010f; + + /* + private float nmAvatarObjectContactFriction = 250f; + private float nmAvatarObjectContactBounce = 0.1f; + + private float mAvatarObjectContactFriction = 75f; + private float mAvatarObjectContactBounce = 0.1f; + */ + m_materialContacts[(int)Material.Glass, 1] = new d.Contact(); + m_materialContacts[(int)Material.Glass, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Glass, 1].surface.mu = 1f; + m_materialContacts[(int)Material.Glass, 1].surface.bounce = 0.5f; + m_materialContacts[(int)Material.Glass, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Glass, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Wood, 0] = new d.Contact(); + m_materialContacts[(int)Material.Wood, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Wood, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Wood, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Wood, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Wood, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Wood, 1] = new d.Contact(); + m_materialContacts[(int)Material.Wood, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Wood, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Wood, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Wood, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Wood, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Flesh, 0] = new d.Contact(); + m_materialContacts[(int)Material.Flesh, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Flesh, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Flesh, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Flesh, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Flesh, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Flesh, 1] = new d.Contact(); + m_materialContacts[(int)Material.Flesh, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Flesh, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Flesh, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Flesh, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Flesh, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Plastic, 0] = new d.Contact(); + m_materialContacts[(int)Material.Plastic, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Plastic, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Plastic, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Plastic, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Plastic, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Plastic, 1] = new d.Contact(); + m_materialContacts[(int)Material.Plastic, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Plastic, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Plastic, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Plastic, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Plastic, 1].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Rubber, 0] = new d.Contact(); + m_materialContacts[(int)Material.Rubber, 0].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Rubber, 0].surface.mu = nmAvatarObjectContactFriction; + m_materialContacts[(int)Material.Rubber, 0].surface.bounce = nmAvatarObjectContactBounce; + m_materialContacts[(int)Material.Rubber, 0].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Rubber, 0].surface.soft_erp = 0.010f; + + m_materialContacts[(int)Material.Rubber, 1] = new d.Contact(); + m_materialContacts[(int)Material.Rubber, 1].surface.mode |= d.ContactFlags.SoftERP; + m_materialContacts[(int)Material.Rubber, 1].surface.mu = mAvatarObjectContactFriction; + m_materialContacts[(int)Material.Rubber, 1].surface.bounce = mAvatarObjectContactBounce; + m_materialContacts[(int)Material.Rubber, 1].surface.soft_cfm = 0.010f; + m_materialContacts[(int)Material.Rubber, 1].surface.soft_erp = 0.010f; + + d.HashSpaceSetLevels(space, worldHashspaceLow, worldHashspaceHigh); + + // Set the gravity,, don't disable things automatically (we set it explicitly on some things) + + d.WorldSetGravity(world, gravityx, gravityy, gravityz); + d.WorldSetContactSurfaceLayer(world, contactsurfacelayer); + + d.WorldSetLinearDamping(world, 256f); + d.WorldSetAngularDamping(world, 256f); + d.WorldSetAngularDampingThreshold(world, 256f); + d.WorldSetLinearDampingThreshold(world, 256f); + d.WorldSetMaxAngularSpeed(world, 256f); + + // Set how many steps we go without running collision testing + // This is in addition to the step size. + // Essentially Steps * m_physicsiterations + d.WorldSetQuickStepNumIterations(world, m_physicsiterations); + //d.WorldSetContactMaxCorrectingVel(world, 1000.0f); + + + + for (int i = 0; i < staticPrimspace.GetLength(0); i++) + { + for (int j = 0; j < staticPrimspace.GetLength(1); j++) + { + staticPrimspace[i, j] = IntPtr.Zero; + } + } + } + + internal void waitForSpaceUnlock(IntPtr space) + { + //if (space != IntPtr.Zero) + //while (d.SpaceLockQuery(space)) { } // Wait and do nothing + } + + /// + /// Debug space message for printing the space that a prim/avatar is in. + /// + /// + /// Returns which split up space the given position is in. + public string whichspaceamIin(Vector3 pos) + { + return calculateSpaceForGeom(pos).ToString(); + } + + #region Collision Detection + + /// + /// This is our near callback. A geometry is near a body + /// + /// The space that contains the geoms. Remember, spaces are also geoms + /// a geometry or space + /// another geometry or space + private void near(IntPtr space, IntPtr g1, IntPtr g2) + { + // no lock here! It's invoked from within Simulate(), which is thread-locked + + // Test if we're colliding a geom with a space. + // If so we have to drill down into the space recursively + + if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) + { + if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) + return; + + // Separating static prim geometry spaces. + // We'll be calling near recursivly if one + // of them is a space to find all of the + // contact points in the space + try + { + d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to collide test a space"); + return; + } + //Colliding a space or a geom with a space or a geom. so drill down + + //Collide all geoms in each space.. + //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); + //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); + return; + } + + if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) + return; + + IntPtr b1 = d.GeomGetBody(g1); + IntPtr b2 = d.GeomGetBody(g2); + + // d.GeomClassID id = d.GeomGetClass(g1); + + String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(g1, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(g2, out name2)) + { + name2 = "null"; + } + + //if (id == d.GeomClassId.TriMeshClass) + //{ + // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2); + //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2); + //} + + // Figure out how many contact points we have + int count = 0; + try + { + // Colliding Geom To Geom + // This portion of the function 'was' blatantly ripped off from BoxStack.cs + + if (g1 == g2) + return; // Can't collide with yourself + + if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) + return; + + lock (contacts) + { + count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); + if (count > contacts.Length) + m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); + } + } + catch (SEHException) + { + m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); + ode.drelease(world); + base.TriggerPhysicsBasedRestart(); + } + catch (Exception e) + { + m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message); + return; + } + + PhysicsActor p1; + PhysicsActor p2; + + if (!actor_name_map.TryGetValue(g1, out p1)) + { + p1 = PANull; + } + + if (!actor_name_map.TryGetValue(g2, out p2)) + { + p2 = PANull; + } + + ContactPoint maxDepthContact = new ContactPoint(); + if (p1.CollisionScore + count >= float.MaxValue) + p1.CollisionScore = 0; + p1.CollisionScore += count; + + if (p2.CollisionScore + count >= float.MaxValue) + p2.CollisionScore = 0; + p2.CollisionScore += count; + + for (int i = 0; i < count; i++) + { + d.ContactGeom curContact = contacts[i]; + + if (curContact.depth > maxDepthContact.PenetrationDepth) + { + maxDepthContact = new ContactPoint( + new Vector3(curContact.pos.X, curContact.pos.Y, curContact.pos.Z), + new Vector3(curContact.normal.X, curContact.normal.Y, curContact.normal.Z), + curContact.depth + ); + } + + //m_log.Warn("[CCOUNT]: " + count); + IntPtr joint; + // If we're colliding with terrain, use 'TerrainContact' instead of contact. + // allows us to have different settings + + // We only need to test p2 for 'jump crouch purposes' + if (p2 is OdeCharacter && p1.PhysicsActorType == (int)ActorTypes.Prim) + { + // Testing if the collision is at the feet of the avatar + + //m_log.DebugFormat("[PHYSICS]: {0} - {1} - {2} - {3}", curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f)); + if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f)) + p2.IsColliding = true; + } + else + { + p2.IsColliding = true; + } + + //if ((framecount % m_returncollisions) == 0) + + switch (p1.PhysicsActorType) + { + case (int)ActorTypes.Agent: + p2.CollidingObj = true; + break; + case (int)ActorTypes.Prim: + if (p2.Velocity.LengthSquared() > 0.0f) + p2.CollidingObj = true; + break; + case (int)ActorTypes.Unknown: + p2.CollidingGround = true; + break; + default: + p2.CollidingGround = true; + break; + } + + // we don't want prim or avatar to explode + + #region InterPenetration Handling - Unintended physics explosions +# region disabled code1 + + if (curContact.depth >= 0.08f) + { + //This is disabled at the moment only because it needs more tweaking + //It will eventually be uncommented + /* + if (contact.depth >= 1.00f) + { + //m_log.Debug("[PHYSICS]: " + contact.depth.ToString()); + } + + //If you interpenetrate a prim with an agent + if ((p2.PhysicsActorType == (int) ActorTypes.Agent && + p1.PhysicsActorType == (int) ActorTypes.Prim) || + (p1.PhysicsActorType == (int) ActorTypes.Agent && + p2.PhysicsActorType == (int) ActorTypes.Prim)) + { + + //contact.depth = contact.depth * 4.15f; + /* + if (p2.PhysicsActorType == (int) ActorTypes.Agent) + { + p2.CollidingObj = true; + contact.depth = 0.003f; + p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); + OdeCharacter character = (OdeCharacter) p2; + character.SetPidStatus(true); + contact.pos = new d.Vector3(contact.pos.X + (p1.Size.X / 2), contact.pos.Y + (p1.Size.Y / 2), contact.pos.Z + (p1.Size.Z / 2)); + + } + else + { + + //contact.depth = 0.0000000f; + } + if (p1.PhysicsActorType == (int) ActorTypes.Agent) + { + + p1.CollidingObj = true; + contact.depth = 0.003f; + p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); + contact.pos = new d.Vector3(contact.pos.X + (p2.Size.X / 2), contact.pos.Y + (p2.Size.Y / 2), contact.pos.Z + (p2.Size.Z / 2)); + OdeCharacter character = (OdeCharacter)p1; + character.SetPidStatus(true); + } + else + { + + //contact.depth = 0.0000000f; + } + + + + } +*/ + // If you interpenetrate a prim with another prim + /* + if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) + { + #region disabledcode2 + //OdePrim op1 = (OdePrim)p1; + //OdePrim op2 = (OdePrim)p2; + //op1.m_collisionscore++; + //op2.m_collisionscore++; + + //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} + + //if (contact.depth >= 0.25f) + //{ + // Don't collide, one or both prim will expld. + + //op1.m_interpenetrationcount++; + //op2.m_interpenetrationcount++; + //interpenetrations_before_disable = 200; + //if (op1.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + //op1.m_taintdisable = true; + //AddPhysicsActorTaint(p1); + //} + //if (op2.m_interpenetrationcount >= interpenetrations_before_disable) + //{ + // op2.m_taintdisable = true; + //AddPhysicsActorTaint(p2); + //} + + //contact.depth = contact.depth / 8f; + //contact.normal = new d.Vector3(0, 0, 1); + //} + //if (op1.m_disabled || op2.m_disabled) + //{ + //Manually disabled objects stay disabled + //contact.depth = 0f; + //} + #endregion + } + */ +#endregion + if (curContact.depth >= 1.00f) + { + //m_log.Info("[P]: " + contact.depth.ToString()); + if ((p2.PhysicsActorType == (int) ActorTypes.Agent && + p1.PhysicsActorType == (int) ActorTypes.Unknown) || + (p1.PhysicsActorType == (int) ActorTypes.Agent && + p2.PhysicsActorType == (int) ActorTypes.Unknown)) + { + if (p2.PhysicsActorType == (int) ActorTypes.Agent) + { + if (p2 is OdeCharacter) + { + OdeCharacter character = (OdeCharacter) p2; + + //p2.CollidingObj = true; + curContact.depth = 0.00000003f; + p2.Velocity = p2.Velocity + new Vector3(0f, 0f, 0.5f); + curContact.pos = + new d.Vector3(curContact.pos.X + (p1.Size.X/2), + curContact.pos.Y + (p1.Size.Y/2), + curContact.pos.Z + (p1.Size.Z/2)); + character.SetPidStatus(true); + } + } + + + if (p1.PhysicsActorType == (int) ActorTypes.Agent) + { + if (p1 is OdeCharacter) + { + OdeCharacter character = (OdeCharacter) p1; + + //p2.CollidingObj = true; + curContact.depth = 0.00000003f; + p1.Velocity = p1.Velocity + new Vector3(0f, 0f, 0.5f); + curContact.pos = + new d.Vector3(curContact.pos.X + (p1.Size.X/2), + curContact.pos.Y + (p1.Size.Y/2), + curContact.pos.Z + (p1.Size.Z/2)); + character.SetPidStatus(true); + } + } + } + } + } + + #endregion + + // Logic for collision handling + // Note, that if *all* contacts are skipped (VolumeDetect) + // The prim still detects (and forwards) collision events but + // appears to be phantom for the world + Boolean skipThisContact = false; + + if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) + skipThisContact = true; // No collision on volume detect prims + + if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) + skipThisContact = true; // No collision on volume detect prims + + if (!skipThisContact && curContact.depth < 0f) + skipThisContact = true; + + if (!skipThisContact && checkDupe(curContact, p2.PhysicsActorType)) + skipThisContact = true; + + const int maxContactsbeforedeath = 4000; + joint = IntPtr.Zero; + + if (!skipThisContact) + { + // If we're colliding against terrain + if (name1 == "Terrain" || name2 == "Terrain") + { + // If we're moving + if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && + (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) + { + // Use the movement terrain contact + AvatarMovementTerrainContact.geom = curContact; + _perloopContact.Add(curContact); + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); + m_global_contactcount++; + } + } + else + { + if (p2.PhysicsActorType == (int)ActorTypes.Agent) + { + // Use the non moving terrain contact + TerrainContact.geom = curContact; + _perloopContact.Add(curContact); + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); + m_global_contactcount++; + } + } + else + { + if (p2.PhysicsActorType == (int)ActorTypes.Prim && p1.PhysicsActorType == (int)ActorTypes.Prim) + { + // prim prim contact + // int pj294950 = 0; + int movintYN = 0; + int material = (int) Material.Wood; + // prim terrain contact + if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) + { + movintYN = 1; + } + + if (p2 is OdePrim) + material = ((OdePrim)p2).m_material; + + //m_log.DebugFormat("Material: {0}", material); + m_materialContacts[material, movintYN].geom = curContact; + _perloopContact.Add(curContact); + + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); + m_global_contactcount++; + + } + + } + else + { + + int movintYN = 0; + // prim terrain contact + if (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f) + { + movintYN = 1; + } + + int material = (int)Material.Wood; + + if (p2 is OdePrim) + material = ((OdePrim)p2).m_material; + //m_log.DebugFormat("Material: {0}", material); + m_materialContacts[material, movintYN].geom = curContact; + _perloopContact.Add(curContact); + + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); + m_global_contactcount++; + + } + } + } + } + //if (p2.PhysicsActorType == (int)ActorTypes.Prim) + //{ + //m_log.Debug("[PHYSICS]: prim contacting with ground"); + //} + } + else if (name1 == "Water" || name2 == "Water") + { + /* + if ((p2.PhysicsActorType == (int) ActorTypes.Prim)) + { + } + else + { + } + */ + //WaterContact.surface.soft_cfm = 0.0000f; + //WaterContact.surface.soft_erp = 0.00000f; + if (curContact.depth > 0.1f) + { + curContact.depth *= 52; + //contact.normal = new d.Vector3(0, 0, 1); + //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f); + } + WaterContact.geom = curContact; + _perloopContact.Add(curContact); + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref WaterContact); + m_global_contactcount++; + } + //m_log.Info("[PHYSICS]: Prim Water Contact" + contact.depth); + } + else + { + // we're colliding with prim or avatar + // check if we're moving + if ((p2.PhysicsActorType == (int)ActorTypes.Agent)) + { + if ((Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) + { + // Use the Movement prim contact + AvatarMovementprimContact.geom = curContact; + _perloopContact.Add(curContact); + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); + m_global_contactcount++; + } + } + else + { + // Use the non movement contact + contact.geom = curContact; + _perloopContact.Add(curContact); + + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref contact); + m_global_contactcount++; + } + } + } + else if (p2.PhysicsActorType == (int)ActorTypes.Prim) + { + //p1.PhysicsActorType + int material = (int)Material.Wood; + + if (p2 is OdePrim) + material = ((OdePrim)p2).m_material; + + //m_log.DebugFormat("Material: {0}", material); + m_materialContacts[material, 0].geom = curContact; + _perloopContact.Add(curContact); + + if (m_global_contactcount < maxContactsbeforedeath) + { + joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]); + m_global_contactcount++; + + } + } + } + + if (m_global_contactcount < maxContactsbeforedeath && joint != IntPtr.Zero) // stack collide! + { + d.JointAttach(joint, b1, b2); + m_global_contactcount++; + } + + } + collision_accounting_events(p1, p2, maxDepthContact); + if (count > geomContactPointsStartthrottle) + { + // If there are more then 3 contact points, it's likely + // that we've got a pile of objects, so ... + // We don't want to send out hundreds of terse updates over and over again + // so lets throttle them and send them again after it's somewhat sorted out. + p2.ThrottleUpdates = true; + } + //m_log.Debug(count.ToString()); + //m_log.Debug("near: A collision was detected between {1} and {2}", 0, name1, name2); + } + } + + private bool checkDupe(d.ContactGeom contactGeom, int atype) + { + bool result = false; + //return result; + if (!m_filterCollisions) + return false; + + ActorTypes at = (ActorTypes)atype; + lock (_perloopContact) + { + foreach (d.ContactGeom contact in _perloopContact) + { + //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2)) + //{ + // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2) + if (at == ActorTypes.Agent) + { + if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) + { + + if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) + { + //contactGeom.depth *= .00005f; + //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); + // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); + result = true; + break; + } + else + { + //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); + } + } + else + { + //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); + //int i = 0; + } + } + else if (at == ActorTypes.Prim) + { + //d.AABB aabb1 = new d.AABB(); + //d.AABB aabb2 = new d.AABB(); + + //d.GeomGetAABB(contactGeom.g2, out aabb2); + //d.GeomGetAABB(contactGeom.g1, out aabb1); + //aabb1. + if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) + { + if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) + { + if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f) + { + result = true; + break; + } + } + //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); + //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); + } + + } + + //} + + } + } + return result; + } + + private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact) + { + // obj1LocalID = 0; + //returncollisions = false; + obj2LocalID = 0; + //ctype = 0; + //cStartStop = 0; + if (!p2.SubscribedEvents() && !p1.SubscribedEvents()) + return; + + switch ((ActorTypes)p2.PhysicsActorType) + { + case ActorTypes.Agent: + cc2 = (OdeCharacter)p2; + + // obj1LocalID = cc2.m_localID; + switch ((ActorTypes)p1.PhysicsActorType) + { + case ActorTypes.Agent: + cc1 = (OdeCharacter)p1; + obj2LocalID = cc1.m_localID; + cc1.AddCollisionEvent(cc2.m_localID, contact); + //ctype = (int)CollisionCategories.Character; + + //if (cc1.CollidingObj) + //cStartStop = (int)StatusIndicators.Generic; + //else + //cStartStop = (int)StatusIndicators.Start; + + //returncollisions = true; + break; + case ActorTypes.Prim: + if (p1 is OdePrim) + { + cp1 = (OdePrim) p1; + obj2LocalID = cp1.m_localID; + cp1.AddCollisionEvent(cc2.m_localID, contact); + } + //ctype = (int)CollisionCategories.Geom; + + //if (cp1.CollidingObj) + //cStartStop = (int)StatusIndicators.Generic; + //else + //cStartStop = (int)StatusIndicators.Start; + + //returncollisions = true; + break; + + case ActorTypes.Ground: + case ActorTypes.Unknown: + obj2LocalID = 0; + //ctype = (int)CollisionCategories.Land; + //returncollisions = true; + break; + } + + cc2.AddCollisionEvent(obj2LocalID, contact); + break; + case ActorTypes.Prim: + + if (p2 is OdePrim) + { + cp2 = (OdePrim) p2; + + // obj1LocalID = cp2.m_localID; + switch ((ActorTypes) p1.PhysicsActorType) + { + case ActorTypes.Agent: + if (p1 is OdeCharacter) + { + cc1 = (OdeCharacter) p1; + obj2LocalID = cc1.m_localID; + cc1.AddCollisionEvent(cp2.m_localID, contact); + //ctype = (int)CollisionCategories.Character; + + //if (cc1.CollidingObj) + //cStartStop = (int)StatusIndicators.Generic; + //else + //cStartStop = (int)StatusIndicators.Start; + //returncollisions = true; + } + break; + case ActorTypes.Prim: + + if (p1 is OdePrim) + { + cp1 = (OdePrim) p1; + obj2LocalID = cp1.m_localID; + cp1.AddCollisionEvent(cp2.m_localID, contact); + //ctype = (int)CollisionCategories.Geom; + + //if (cp1.CollidingObj) + //cStartStop = (int)StatusIndicators.Generic; + //else + //cStartStop = (int)StatusIndicators.Start; + + //returncollisions = true; + } + break; + + case ActorTypes.Ground: + case ActorTypes.Unknown: + obj2LocalID = 0; + //ctype = (int)CollisionCategories.Land; + + //returncollisions = true; + break; + } + + cp2.AddCollisionEvent(obj2LocalID, contact); + } + break; + } + //if (returncollisions) + //{ + + //lock (m_storedCollisions) + //{ + //cDictKey = obj1LocalID.ToString() + obj2LocalID.ToString() + cStartStop.ToString() + ctype.ToString(); + //if (m_storedCollisions.ContainsKey(cDictKey)) + //{ + //sCollisionData objd = m_storedCollisions[cDictKey]; + //objd.NumberOfCollisions += 1; + //objd.lastframe = framecount; + //m_storedCollisions[cDictKey] = objd; + //} + //else + //{ + //sCollisionData objd = new sCollisionData(); + //objd.ColliderLocalId = obj1LocalID; + //objd.CollidedWithLocalId = obj2LocalID; + //objd.CollisionType = ctype; + //objd.NumberOfCollisions = 1; + //objd.lastframe = framecount; + //objd.StatusIndicator = cStartStop; + //m_storedCollisions.Add(cDictKey, objd); + //} + //} + // } + } + + public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) + { + /* String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + + m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2); + */ + return 1; + } + + public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) + { + String name1 = null; + String name2 = null; + + if (!geom_name_map.TryGetValue(trimesh, out name1)) + { + name1 = "null"; + } + + if (!geom_name_map.TryGetValue(refObject, out name2)) + { + name2 = "null"; + } + + // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); + + d.Vector3 v0 = new d.Vector3(); + d.Vector3 v1 = new d.Vector3(); + d.Vector3 v2 = new d.Vector3(); + + d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); + // m_log.DebugFormat("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); + + return 1; + } + + /// + /// This is our collision testing routine in ODE + /// + /// + private void collision_optimized(float timeStep) + { + _perloopContact.Clear(); + + lock (_characters) + { + foreach (OdeCharacter chr in _characters) + { + // Reset the collision values to false + // since we don't know if we're colliding yet + + // For some reason this can happen. Don't ask... + // + if (chr == null) + continue; + + if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero) + continue; + + chr.IsColliding = false; + chr.CollidingGround = false; + chr.CollidingObj = false; + + // test the avatar's geometry for collision with the space + // This will return near and the space that they are the closest to + // And we'll run this again against the avatar and the space segment + // This will return with a bunch of possible objects in the space segment + // and we'll run it again on all of them. + try + { + d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y); + //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10) + //{ + //chr.Position.Z = terrainheight + 10.0f; + //forcedZ = true; + //} + } + } + + lock (_activeprims) + { + List removeprims = null; + foreach (OdePrim chr in _activeprims) + { + if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled)) + { + try + { + lock (chr) + { + if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) + { + d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); + } + else + { + if (removeprims == null) + { + removeprims = new List(); + } + removeprims.Add(chr); + m_log.Debug("[PHYSICS]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!"); + } + } + } + catch (AccessViolationException) + { + m_log.Warn("[PHYSICS]: Unable to space collide"); + } + } + } + if (removeprims != null) + { + foreach (OdePrim chr in removeprims) + { + _activeprims.Remove(chr); + } + } + } + + _perloopContact.Clear(); + } + + #endregion + + public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) + { + m_worldOffset = offset; + WorldExtents = new Vector2(extents.X, extents.Y); + m_parentScene = pScene; + + } + + // Recovered for use by fly height. Kitto Flora + public float GetTerrainHeightAtXY(float x, float y) + { + + int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize; + int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize; + + IntPtr heightFieldGeom = IntPtr.Zero; + + if (RegionTerrain.TryGetValue(new Vector3(offsetX,offsetY,0), out heightFieldGeom)) + { + if (heightFieldGeom != IntPtr.Zero) + { + if (TerrainHeightFieldHeights.ContainsKey(heightFieldGeom)) + { + + int index; + + + if ((int)x > WorldExtents.X || (int)y > WorldExtents.Y || + (int)x < 0.001f || (int)y < 0.001f) + return 0; + + x = x - offsetX; + y = y - offsetY; + + index = (int)((int)x * ((int)Constants.RegionSize + 2) + (int)y); + + if (index < TerrainHeightFieldHeights[heightFieldGeom].Length) + { + //m_log.DebugFormat("x{0} y{1} = {2}", x, y, (float)TerrainHeightFieldHeights[heightFieldGeom][index]); + return (float)TerrainHeightFieldHeights[heightFieldGeom][index]; + } + + else + return 0f; + } + else + { + return 0f; + } + + } + else + { + return 0f; + } + + } + else + { + return 0f; + } + + + } +// End recovered. Kitto Flora + + public void addCollisionEventReporting(PhysicsActor obj) + { + lock (_collisionEventPrim) + { + if (!_collisionEventPrim.Contains(obj)) + _collisionEventPrim.Add(obj); + } + } + + public void remCollisionEventReporting(PhysicsActor obj) + { + lock (_collisionEventPrim) + { + if (!_collisionEventPrim.Contains(obj)) + _collisionEventPrim.Remove(obj); + } + } + + #region Add/Remove Entities + + public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) + { + Vector3 pos; + pos.X = position.X; + pos.Y = position.Y; + pos.Z = position.Z; + OdeCharacter newAv = new OdeCharacter(avName, this, pos, ode, size, avPIDD, avPIDP, avCapRadius, avStandupTensor, avDensity, avHeightFudgeFactor, avMovementDivisorWalk, avMovementDivisorRun); + newAv.Flying = isFlying; + newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; + + return newAv; + } + + public void AddCharacter(OdeCharacter chr) + { + lock (_characters) + { + if (!_characters.Contains(chr)) + { + _characters.Add(chr); + if (chr.bad) + m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid); + } + } + } + + public void RemoveCharacter(OdeCharacter chr) + { + lock (_characters) + { + if (_characters.Contains(chr)) + { + _characters.Remove(chr); + } + } + } + public void BadCharacter(OdeCharacter chr) + { + lock (_badCharacter) + { + if (!_badCharacter.Contains(chr)) + _badCharacter.Add(chr); + } + } + + public override void RemoveAvatar(PhysicsActor actor) + { + //m_log.Debug("[PHYSICS]:ODELOCK"); + ((OdeCharacter) actor).Destroy(); + + } + + private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, + IMesh mesh, PrimitiveBaseShape pbs, bool isphysical) + { + + Vector3 pos = position; + Vector3 siz = size; + Quaternion rot = rotation; + + OdePrim newPrim; + lock (OdeLock) + { + newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode); + + lock (_prims) + _prims.Add(newPrim); + } + + return newPrim; + } + + public void addActivePrim(OdePrim activatePrim) + { + // adds active prim.. (ones that should be iterated over in collisions_optimized + lock (_activeprims) + { + if (!_activeprims.Contains(activatePrim)) + _activeprims.Add(activatePrim); + //else + // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent"); + } + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, + Vector3 size, Quaternion rotation) //To be removed + { + return AddPrimShape(primName, pbs, position, size, rotation, false); + } + + public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, + Vector3 size, Quaternion rotation, bool isPhysical) + { + PhysicsActor result; + IMesh mesh = null; + + if (needsMeshing(pbs)) + mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical); + + result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); + + return result; + } + + public override float TimeDilation + { + get { return m_timeDilation; } + } + + public override bool SupportsNINJAJoints + { + get { return m_NINJA_physics_joints_enabled; } + } + + // internal utility function: must be called within a lock (OdeLock) + private void InternalAddActiveJoint(PhysicsJoint joint) + { + activeJoints.Add(joint); + SOPName_to_activeJoint.Add(joint.ObjectNameInScene, joint); + } + + // internal utility function: must be called within a lock (OdeLock) + private void InternalAddPendingJoint(OdePhysicsJoint joint) + { + pendingJoints.Add(joint); + SOPName_to_pendingJoint.Add(joint.ObjectNameInScene, joint); + } + + // internal utility function: must be called within a lock (OdeLock) + private void InternalRemovePendingJoint(PhysicsJoint joint) + { + pendingJoints.Remove(joint); + SOPName_to_pendingJoint.Remove(joint.ObjectNameInScene); + } + + // internal utility function: must be called within a lock (OdeLock) + private void InternalRemoveActiveJoint(PhysicsJoint joint) + { + activeJoints.Remove(joint); + SOPName_to_activeJoint.Remove(joint.ObjectNameInScene); + } + + public override void DumpJointInfo() + { + string hdr = "[NINJA] JOINTINFO: "; + foreach (PhysicsJoint j in pendingJoints) + { + m_log.Debug(hdr + " pending joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); + } + m_log.Debug(hdr + pendingJoints.Count + " total pending joints"); + foreach (string jointName in SOPName_to_pendingJoint.Keys) + { + m_log.Debug(hdr + " pending joints dict contains Name: " + jointName); + } + m_log.Debug(hdr + SOPName_to_pendingJoint.Keys.Count + " total pending joints dict entries"); + foreach (PhysicsJoint j in activeJoints) + { + m_log.Debug(hdr + " active joint, Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); + } + m_log.Debug(hdr + activeJoints.Count + " total active joints"); + foreach (string jointName in SOPName_to_activeJoint.Keys) + { + m_log.Debug(hdr + " active joints dict contains Name: " + jointName); + } + m_log.Debug(hdr + SOPName_to_activeJoint.Keys.Count + " total active joints dict entries"); + + m_log.Debug(hdr + " Per-body joint connectivity information follows."); + m_log.Debug(hdr + joints_connecting_actor.Keys.Count + " bodies are connected by joints."); + foreach (string actorName in joints_connecting_actor.Keys) + { + m_log.Debug(hdr + " Actor " + actorName + " has the following joints connecting it"); + foreach (PhysicsJoint j in joints_connecting_actor[actorName]) + { + m_log.Debug(hdr + " * joint Name: " + j.ObjectNameInScene + " raw parms:" + j.RawParams); + } + m_log.Debug(hdr + joints_connecting_actor[actorName].Count + " connecting joints total for this actor"); + } + } + + public override void RequestJointDeletion(string ObjectNameInScene) + { + lock (externalJointRequestsLock) + { + if (!requestedJointsToBeDeleted.Contains(ObjectNameInScene)) // forbid same deletion request from entering twice to prevent spurious deletions processed asynchronously + { + requestedJointsToBeDeleted.Add(ObjectNameInScene); + } + } + } + + private void DeleteRequestedJoints() + { + List myRequestedJointsToBeDeleted; + lock (externalJointRequestsLock) + { + // make a local copy of the shared list for processing (threading issues) + myRequestedJointsToBeDeleted = new List(requestedJointsToBeDeleted); + } + + foreach (string jointName in myRequestedJointsToBeDeleted) + { + lock (OdeLock) + { + //m_log.Debug("[NINJA] trying to deleting requested joint " + jointName); + if (SOPName_to_activeJoint.ContainsKey(jointName) || SOPName_to_pendingJoint.ContainsKey(jointName)) + { + OdePhysicsJoint joint = null; + if (SOPName_to_activeJoint.ContainsKey(jointName)) + { + joint = SOPName_to_activeJoint[jointName] as OdePhysicsJoint; + InternalRemoveActiveJoint(joint); + } + else if (SOPName_to_pendingJoint.ContainsKey(jointName)) + { + joint = SOPName_to_pendingJoint[jointName] as OdePhysicsJoint; + InternalRemovePendingJoint(joint); + } + + if (joint != null) + { + //m_log.Debug("joint.BodyNames.Count is " + joint.BodyNames.Count + " and contents " + joint.BodyNames); + for (int iBodyName = 0; iBodyName < 2; iBodyName++) + { + string bodyName = joint.BodyNames[iBodyName]; + if (bodyName != "NULL") + { + joints_connecting_actor[bodyName].Remove(joint); + if (joints_connecting_actor[bodyName].Count == 0) + { + joints_connecting_actor.Remove(bodyName); + } + } + } + + DoJointDeactivated(joint); + if (joint.jointID != IntPtr.Zero) + { + d.JointDestroy(joint.jointID); + joint.jointID = IntPtr.Zero; + //DoJointErrorMessage(joint, "successfully destroyed joint " + jointName); + } + else + { + //m_log.Warn("[NINJA] Ignoring re-request to destroy joint " + jointName); + } + } + else + { + // DoJointErrorMessage(joint, "coult not find joint to destroy based on name " + jointName); + } + } + else + { + // DoJointErrorMessage(joint, "WARNING - joint removal failed, joint " + jointName); + } + } + } + + // remove processed joints from the shared list + lock (externalJointRequestsLock) + { + foreach (string jointName in myRequestedJointsToBeDeleted) + { + requestedJointsToBeDeleted.Remove(jointName); + } + } + } + + // for pending joints we don't know if their associated bodies exist yet or not. + // the joint is actually created during processing of the taints + private void CreateRequestedJoints() + { + List myRequestedJointsToBeCreated; + lock (externalJointRequestsLock) + { + // make a local copy of the shared list for processing (threading issues) + myRequestedJointsToBeCreated = new List(requestedJointsToBeCreated); + } + + foreach (PhysicsJoint joint in myRequestedJointsToBeCreated) + { + lock (OdeLock) + { + if (SOPName_to_pendingJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_pendingJoint[joint.ObjectNameInScene] != null) + { + DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already pending joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation); + continue; + } + if (SOPName_to_activeJoint.ContainsKey(joint.ObjectNameInScene) && SOPName_to_activeJoint[joint.ObjectNameInScene] != null) + { + DoJointErrorMessage(joint, "WARNING: ignoring request to re-add already active joint Name:" + joint.ObjectNameInScene + " type:" + joint.Type + " parms: " + joint.RawParams + " pos: " + joint.Position + " rot:" + joint.Rotation); + continue; + } + + InternalAddPendingJoint(joint as OdePhysicsJoint); + + if (joint.BodyNames.Count >= 2) + { + for (int iBodyName = 0; iBodyName < 2; iBodyName++) + { + string bodyName = joint.BodyNames[iBodyName]; + if (bodyName != "NULL") + { + if (!joints_connecting_actor.ContainsKey(bodyName)) + { + joints_connecting_actor.Add(bodyName, new List()); + } + joints_connecting_actor[bodyName].Add(joint); + } + } + } + } + } + + // remove processed joints from shared list + lock (externalJointRequestsLock) + { + foreach (PhysicsJoint joint in myRequestedJointsToBeCreated) + { + requestedJointsToBeCreated.Remove(joint); + } + } + + } + + // public function to add an request for joint creation + // this joint will just be added to a waiting list that is NOT processed during the main + // Simulate() loop (to avoid deadlocks). After Simulate() is finished, we handle unprocessed joint requests. + + public override PhysicsJoint RequestJointCreation(string objectNameInScene, PhysicsJointType jointType, Vector3 position, + Quaternion rotation, string parms, List bodyNames, string trackedBodyName, Quaternion localRotation) + + { + + OdePhysicsJoint joint = new OdePhysicsJoint(); + joint.ObjectNameInScene = objectNameInScene; + joint.Type = jointType; + joint.Position = position; + joint.Rotation = rotation; + joint.RawParams = parms; + joint.BodyNames = new List(bodyNames); + joint.TrackedBodyName = trackedBodyName; + joint.LocalRotation = localRotation; + joint.jointID = IntPtr.Zero; + joint.ErrorMessageCount = 0; + + lock (externalJointRequestsLock) + { + if (!requestedJointsToBeCreated.Contains(joint)) // forbid same creation request from entering twice + { + requestedJointsToBeCreated.Add(joint); + } + } + return joint; + } + + private void RemoveAllJointsConnectedToActor(PhysicsActor actor) + { + //m_log.Debug("RemoveAllJointsConnectedToActor: start"); + if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null) + { + + List jointsToRemove = new List(); + //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism) + foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName]) + { + jointsToRemove.Add(j); + } + foreach (PhysicsJoint j in jointsToRemove) + { + //m_log.Debug("RemoveAllJointsConnectedToActor: about to request deletion of " + j.ObjectNameInScene); + RequestJointDeletion(j.ObjectNameInScene); + //m_log.Debug("RemoveAllJointsConnectedToActor: done request deletion of " + j.ObjectNameInScene); + j.TrackedBodyName = null; // *IMMEDIATELY* prevent any further movement of this joint (else a deleted actor might cause spurious tracking motion of the joint for a few frames, leading to the joint proxy object disappearing) + } + } + } + + public override void RemoveAllJointsConnectedToActorThreadLocked(PhysicsActor actor) + { + //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: start"); + lock (OdeLock) + { + //m_log.Debug("RemoveAllJointsConnectedToActorThreadLocked: got lock"); + RemoveAllJointsConnectedToActor(actor); + } + } + + // normally called from within OnJointMoved, which is called from within a lock (OdeLock) + public override Vector3 GetJointAnchor(PhysicsJoint joint) + { + Debug.Assert(joint.IsInPhysicsEngine); + d.Vector3 pos = new d.Vector3(); + + if (!(joint is OdePhysicsJoint)) + { + DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene); + } + else + { + OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint; + switch (odeJoint.Type) + { + case PhysicsJointType.Ball: + d.JointGetBallAnchor(odeJoint.jointID, out pos); + break; + case PhysicsJointType.Hinge: + d.JointGetHingeAnchor(odeJoint.jointID, out pos); + break; + } + } + return new Vector3(pos.X, pos.Y, pos.Z); + } + + // normally called from within OnJointMoved, which is called from within a lock (OdeLock) + // WARNING: ODE sometimes returns <0,0,0> as the joint axis! Therefore this function + // appears to be unreliable. Fortunately we can compute the joint axis ourselves by + // keeping track of the joint's original orientation relative to one of the involved bodies. + public override Vector3 GetJointAxis(PhysicsJoint joint) + { + Debug.Assert(joint.IsInPhysicsEngine); + d.Vector3 axis = new d.Vector3(); + + if (!(joint is OdePhysicsJoint)) + { + DoJointErrorMessage(joint, "warning: non-ODE joint requesting anchor: " + joint.ObjectNameInScene); + } + else + { + OdePhysicsJoint odeJoint = (OdePhysicsJoint)joint; + switch (odeJoint.Type) + { + case PhysicsJointType.Ball: + DoJointErrorMessage(joint, "warning - axis requested for ball joint: " + joint.ObjectNameInScene); + break; + case PhysicsJointType.Hinge: + d.JointGetHingeAxis(odeJoint.jointID, out axis); + break; + } + } + return new Vector3(axis.X, axis.Y, axis.Z); + } + + + public void remActivePrim(OdePrim deactivatePrim) + { + lock (_activeprims) + { + _activeprims.Remove(deactivatePrim); + } + } + + public override void RemovePrim(PhysicsActor prim) + { + if (prim is OdePrim) + { + lock (OdeLock) + { + OdePrim p = (OdePrim) prim; + + p.setPrimForRemoval(); + AddPhysicsActorTaint(prim); + //RemovePrimThreadLocked(p); + } + } + } + + /// + /// This is called from within simulate but outside the locked portion + /// We need to do our own locking here + /// Essentially, we need to remove the prim from our space segment, whatever segment it's in. + /// + /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory + /// that the space was using. + /// + /// + public void RemovePrimThreadLocked(OdePrim prim) + { +//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName); + lock (prim) + { + remCollisionEventReporting(prim); + lock (ode) + { + if (prim.prim_geom != IntPtr.Zero) + { + prim.ResetTaints(); + + if (prim.IsPhysical) + { + prim.disableBody(); + if (prim.childPrim) + { + prim.childPrim = false; + prim.Body = IntPtr.Zero; + prim.m_disabled = true; + prim.IsPhysical = false; + } + + + } + // we don't want to remove the main space + + // If the geometry is in the targetspace, remove it from the target space + //m_log.Warn(prim.m_targetSpace); + + //if (prim.m_targetSpace != IntPtr.Zero) + //{ + //if (d.SpaceQuery(prim.m_targetSpace, prim.prim_geom)) + //{ + + //if (d.GeomIsSpace(prim.m_targetSpace)) + //{ + //waitForSpaceUnlock(prim.m_targetSpace); + //d.SpaceRemove(prim.m_targetSpace, prim.prim_geom); + prim.m_targetSpace = IntPtr.Zero; + //} + //else + //{ + // m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + + //((OdePrim)prim).m_targetSpace.ToString()); + //} + + //} + //} + //m_log.Warn(prim.prim_geom); + try + { + if (prim.prim_geom != IntPtr.Zero) + { + d.GeomDestroy(prim.prim_geom); + prim.prim_geom = IntPtr.Zero; + } + else + { + m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene"); + } + } + catch (AccessViolationException) + { + m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed."); + } + lock (_prims) + _prims.Remove(prim); + + //If there are no more geometries in the sub-space, we don't need it in the main space anymore + //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0) + //{ + //if (prim.m_targetSpace != null) + //{ + //if (d.GeomIsSpace(prim.m_targetSpace)) + //{ + //waitForSpaceUnlock(prim.m_targetSpace); + //d.SpaceRemove(space, prim.m_targetSpace); + // free up memory used by the space. + //d.SpaceDestroy(prim.m_targetSpace); + //int[] xyspace = calculateSpaceArrayItemFromPos(prim.Position); + //resetSpaceArrayItemToZero(xyspace[0], xyspace[1]); + //} + //else + //{ + //m_log.Info("[Physics]: Invalid Scene passed to 'removeprim from scene':" + + //((OdePrim) prim).m_targetSpace.ToString()); + //} + //} + //} + + if (SupportsNINJAJoints) + { + RemoveAllJointsConnectedToActorThreadLocked(prim); + } + } + } + } + } + + #endregion + + #region Space Separation Calculation + + /// + /// Takes a space pointer and zeros out the array we're using to hold the spaces + /// + /// + public void resetSpaceArrayItemToZero(IntPtr pSpace) + { + for (int x = 0; x < staticPrimspace.GetLength(0); x++) + { + for (int y = 0; y < staticPrimspace.GetLength(1); y++) + { + if (staticPrimspace[x, y] == pSpace) + staticPrimspace[x, y] = IntPtr.Zero; + } + } + } + + public void resetSpaceArrayItemToZero(int arrayitemX, int arrayitemY) + { + staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; + } + + /// + /// Called when a static prim moves. Allocates a space for the prim based on its position + /// + /// the pointer to the geom that moved + /// the position that the geom moved to + /// a pointer to the space it was in before it was moved. + /// a pointer to the new space it's in + public IntPtr recalculateSpaceForGeom(IntPtr geom, Vector3 pos, IntPtr currentspace) + { + // Called from setting the Position and Size of an ODEPrim so + // it's already in locked space. + + // we don't want to remove the main space + // we don't need to test physical here because this function should + // never be called if the prim is physical(active) + + // All physical prim end up in the root space + //Thread.Sleep(20); + if (currentspace != space) + { + //m_log.Info("[SPACE]: C:" + currentspace.ToString() + " g:" + geom.ToString()); + //if (currentspace == IntPtr.Zero) + //{ + //int adfadf = 0; + //} + if (d.SpaceQuery(currentspace, geom) && currentspace != IntPtr.Zero) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + d.SpaceRemove(currentspace, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace + + " Geom:" + geom); + } + } + else + { + IntPtr sGeomIsIn = d.GeomGetSpace(geom); + if (sGeomIsIn != IntPtr.Zero) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(sGeomIsIn); + d.SpaceRemove(sGeomIsIn, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + sGeomIsIn + " Geom:" + geom); + } + } + } + + //If there are no more geometries in the sub-space, we don't need it in the main space anymore + if (d.SpaceGetNumGeoms(currentspace) == 0) + { + if (currentspace != IntPtr.Zero) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + waitForSpaceUnlock(space); + d.SpaceRemove(space, currentspace); + // free up memory used by the space. + + //d.SpaceDestroy(currentspace); + resetSpaceArrayItemToZero(currentspace); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + currentspace + " Geom:" + geom); + } + } + } + } + else + { + // this is a physical object that got disabled. ;.; + if (currentspace != IntPtr.Zero && geom != IntPtr.Zero) + { + if (d.SpaceQuery(currentspace, geom)) + { + if (d.GeomIsSpace(currentspace)) + { + waitForSpaceUnlock(currentspace); + d.SpaceRemove(currentspace, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + currentspace + " Geom:" + geom); + } + } + else + { + IntPtr sGeomIsIn = d.GeomGetSpace(geom); + if (sGeomIsIn != IntPtr.Zero) + { + if (d.GeomIsSpace(sGeomIsIn)) + { + waitForSpaceUnlock(sGeomIsIn); + d.SpaceRemove(sGeomIsIn, geom); + } + else + { + m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + + sGeomIsIn + " Geom:" + geom); + } + } + } + } + } + + // The routines in the Position and Size sections do the 'inserting' into the space, + // so all we have to do is make sure that the space that we're putting the prim into + // is in the 'main' space. + int[] iprimspaceArrItem = calculateSpaceArrayItemFromPos(pos); + IntPtr newspace = calculateSpaceForGeom(pos); + + if (newspace == IntPtr.Zero) + { + newspace = createprimspace(iprimspaceArrItem[0], iprimspaceArrItem[1]); + d.HashSpaceSetLevels(newspace, smallHashspaceLow, smallHashspaceHigh); + } + + return newspace; + } + + /// + /// Creates a new space at X Y + /// + /// + /// + /// A pointer to the created space + public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) + { + // creating a new space for prim and inserting it into main space. + staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); + d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space); + waitForSpaceUnlock(space); + d.SpaceSetSublevel(space, 1); + d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); + return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; + } + + /// + /// Calculates the space the prim should be in by its position + /// + /// + /// a pointer to the space. This could be a new space or reused space. + public IntPtr calculateSpaceForGeom(Vector3 pos) + { + int[] xyspace = calculateSpaceArrayItemFromPos(pos); + //m_log.Info("[Physics]: Attempting to use arrayItem: " + xyspace[0].ToString() + "," + xyspace[1].ToString()); + return staticPrimspace[xyspace[0], xyspace[1]]; + } + + /// + /// Holds the space allocation logic + /// + /// + /// an array item based on the position + public int[] calculateSpaceArrayItemFromPos(Vector3 pos) + { + int[] returnint = new int[2]; + + returnint[0] = (int) (pos.X/metersInSpace); + + if (returnint[0] > ((int) (259f/metersInSpace))) + returnint[0] = ((int) (259f/metersInSpace)); + if (returnint[0] < 0) + returnint[0] = 0; + + returnint[1] = (int) (pos.Y/metersInSpace); + if (returnint[1] > ((int) (259f/metersInSpace))) + returnint[1] = ((int) (259f/metersInSpace)); + if (returnint[1] < 0) + returnint[1] = 0; + + return returnint; + } + + #endregion + + /// + /// Routine to figure out if we need to mesh this prim with our mesher + /// + /// + /// + public bool needsMeshing(PrimitiveBaseShape pbs) + { + // most of this is redundant now as the mesher will return null if it cant mesh a prim + // but we still need to check for sculptie meshing being enabled so this is the most + // convenient place to do it for now... + + // //if (pbs.PathCurve == (byte)Primitive.PathCurve.Circle && pbs.ProfileCurve == (byte)Primitive.ProfileCurve.Circle && pbs.PathScaleY <= 0.75f) + // //m_log.Debug("needsMeshing: " + " pathCurve: " + pbs.PathCurve.ToString() + " profileCurve: " + pbs.ProfileCurve.ToString() + " pathScaleY: " + Primitive.UnpackPathScale(pbs.PathScaleY).ToString()); + int iPropertiesNotSupportedDefault = 0; + + if (pbs.SculptEntry && !meshSculptedPrim) + { +#if SPAM + m_log.Warn("NonMesh"); +#endif + return false; + } + + // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim + if (!forceSimplePrimMeshing) + { + if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) + || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 + && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) + { + + if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 + && pbs.ProfileHollow == 0 + && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 + && pbs.PathBegin == 0 && pbs.PathEnd == 0 + && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 + && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 + && pbs.PathShearX == 0 && pbs.PathShearY == 0) + { +#if SPAM + m_log.Warn("NonMesh"); +#endif + return false; + } + } + } + + if (pbs.ProfileHollow != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) + iPropertiesNotSupportedDefault++; + + if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1) + iPropertiesNotSupportedDefault++; + + // test for torus + if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) + { + if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; + } + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) + { + if (pbs.PathCurve == (byte)Extrusion.Straight) + { + iPropertiesNotSupportedDefault++; + } + + // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits + else if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; + } + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) + { + if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) + { + iPropertiesNotSupportedDefault++; + } + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) + { + if (pbs.PathCurve == (byte)Extrusion.Straight) + { + iPropertiesNotSupportedDefault++; + } + else if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; + } + } + + + if (iPropertiesNotSupportedDefault == 0) + { +#if SPAM + m_log.Warn("NonMesh"); +#endif + return false; + } +#if SPAM + m_log.Debug("Mesh"); +#endif + return true; + } + + /// + /// Called after our prim properties are set Scale, position etc. + /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex + /// This assures us that we have no race conditions + /// + /// + public override void AddPhysicsActorTaint(PhysicsActor prim) + { + + if (prim is OdePrim) + { + OdePrim taintedprim = ((OdePrim) prim); + lock (_taintedPrimLock) + { + if (!(_taintedPrimH.Contains(taintedprim))) + { +//Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.m_primName); + _taintedPrimH.Add(taintedprim); // HashSet for searching + _taintedPrimL.Add(taintedprim); // List for ordered readout + } + } + return; + } + else if (prim is OdeCharacter) + { + OdeCharacter taintedchar = ((OdeCharacter)prim); + lock (_taintedActors) + { + if (!(_taintedActors.Contains(taintedchar))) + { + _taintedActors.Add(taintedchar); + if (taintedchar.bad) + m_log.DebugFormat("[PHYSICS]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid); + } + } + } + } + + /// + /// This is our main simulate loop + /// It's thread locked by a Mutex in the scene. + /// It holds Collisions, it instructs ODE to step through the physical reactions + /// It moves the objects around in memory + /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup) + /// + /// + /// + public override float Simulate(float timeStep) + { + if (framecount >= int.MaxValue) + framecount = 0; + + //if (m_worldOffset != Vector3.Zero) + // return 0; + + framecount++; + + float fps = 0; + //m_log.Info(timeStep.ToString()); + step_time += timeStep; + + // If We're loaded down by something else, + // or debugging with the Visual Studio project on pause + // skip a few frames to catch up gracefully. + // without shooting the physicsactors all over the place + + if (step_time >= m_SkipFramesAtms) + { + // Instead of trying to catch up, it'll do 5 physics frames only + step_time = ODE_STEPSIZE; + m_physicsiterations = 5; + } + else + { + m_physicsiterations = 10; + } + + if (SupportsNINJAJoints) + { + DeleteRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks + CreateRequestedJoints(); // this must be outside of the lock (OdeLock) to avoid deadlocks + } + + lock (OdeLock) + { + // Process 10 frames if the sim is running normal.. + // process 5 frames if the sim is running slow + //try + //{ + //d.WorldSetQuickStepNumIterations(world, m_physicsiterations); + //} + //catch (StackOverflowException) + //{ + // m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim."); + // ode.drelease(world); + //base.TriggerPhysicsBasedRestart(); + //} + + int i = 0; + + // Figure out the Frames Per Second we're going at. + //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size + + fps = (step_time / ODE_STEPSIZE) * 1000; + // HACK: Using a time dilation of 1.0 to debug rubberbanding issues + //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f); + + step_time = 0.09375f; + + while (step_time > 0.0f) + { + //lock (ode) + //{ + //if (!ode.lockquery()) + //{ + // ode.dlock(world); + try + { + // Insert, remove Characters + bool processedtaints = false; + + lock (_taintedActors) + { + if (_taintedActors.Count > 0) + { + foreach (OdeCharacter character in _taintedActors) + { + + character.ProcessTaints(timeStep); + + processedtaints = true; + //character.m_collisionscore = 0; + } + + if (processedtaints) + _taintedActors.Clear(); + } + } + + // Modify other objects in the scene. + processedtaints = false; + + lock (_taintedPrimLock) + { + foreach (OdePrim prim in _taintedPrimL) + { + if (prim.m_taintremove) + { + //Console.WriteLine("Simulate calls RemovePrimThreadLocked"); + RemovePrimThreadLocked(prim); + } + else + { + //Console.WriteLine("Simulate calls ProcessTaints"); + prim.ProcessTaints(timeStep); + } + processedtaints = true; + prim.m_collisionscore = 0; + + // This loop can block up the Heartbeat for a very long time on large regions. + // We need to let the Watchdog know that the Heartbeat is not dead + // NOTE: This is currently commented out, but if things like OAR loading are + // timing the heartbeat out we will need to uncomment it + //Watchdog.UpdateThread(); + } + + if (SupportsNINJAJoints) + { + // Create pending joints, if possible + + // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating + // a joint requires specifying the body id of both involved bodies + if (pendingJoints.Count > 0) + { + List successfullyProcessedPendingJoints = new List(); + //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints"); + foreach (PhysicsJoint joint in pendingJoints) + { + //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams); + string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries); + List jointBodies = new List(); + bool allJointBodiesAreReady = true; + foreach (string jointParam in jointParams) + { + if (jointParam == "NULL") + { + //DoJointErrorMessage(joint, "attaching NULL joint to world"); + jointBodies.Add(IntPtr.Zero); + } + else + { + //DoJointErrorMessage(joint, "looking for prim name: " + jointParam); + bool foundPrim = false; + lock (_prims) + { + foreach (OdePrim prim in _prims) // FIXME: inefficient + { + if (prim.SOPName == jointParam) + { + //DoJointErrorMessage(joint, "found for prim name: " + jointParam); + if (prim.IsPhysical && prim.Body != IntPtr.Zero) + { + jointBodies.Add(prim.Body); + foundPrim = true; + break; + } + else + { + DoJointErrorMessage(joint, "prim name " + jointParam + + " exists but is not (yet) physical; deferring joint creation. " + + "IsPhysical property is " + prim.IsPhysical + + " and body is " + prim.Body); + foundPrim = false; + break; + } + } + } + } + if (foundPrim) + { + // all is fine + } + else + { + allJointBodiesAreReady = false; + break; + } + } + } + if (allJointBodiesAreReady) + { + //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams); + if (jointBodies[0] == jointBodies[1]) + { + DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams); + } + else + { + switch (joint.Type) + { + case PhysicsJointType.Ball: + { + IntPtr odeJoint; + //DoJointErrorMessage(joint, "ODE creating ball joint "); + odeJoint = d.JointCreateBall(world, IntPtr.Zero); + //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]); + d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]); + //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position); + d.JointSetBallAnchor(odeJoint, + joint.Position.X, + joint.Position.Y, + joint.Position.Z); + //DoJointErrorMessage(joint, "ODE joint setting OK"); + //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: "); + //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment")); + //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: "); + //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment")); + + if (joint is OdePhysicsJoint) + { + ((OdePhysicsJoint)joint).jointID = odeJoint; + } + else + { + DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!"); + } + } + break; + case PhysicsJointType.Hinge: + { + IntPtr odeJoint; + //DoJointErrorMessage(joint, "ODE creating hinge joint "); + odeJoint = d.JointCreateHinge(world, IntPtr.Zero); + //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]); + d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]); + //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position); + d.JointSetHingeAnchor(odeJoint, + joint.Position.X, + joint.Position.Y, + joint.Position.Z); + // We use the orientation of the x-axis of the joint's coordinate frame + // as the axis for the hinge. + + // Therefore, we must get the joint's coordinate frame based on the + // joint.Rotation field, which originates from the orientation of the + // joint's proxy object in the scene. + + // The joint's coordinate frame is defined as the transformation matrix + // that converts a vector from joint-local coordinates into world coordinates. + // World coordinates are defined as the XYZ coordinate system of the sim, + // as shown in the top status-bar of the viewer. + + // Once we have the joint's coordinate frame, we extract its X axis (AtAxis) + // and use that as the hinge axis. + + //joint.Rotation.Normalize(); + Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation); + + // Now extract the X axis of the joint's coordinate frame. + + // Do not try to use proxyFrame.AtAxis or you will become mired in the + // tar pit of transposed, inverted, and generally messed-up orientations. + // (In other words, Matrix4.AtAxis() is borked.) + // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness + + // Instead, compute the X axis of the coordinate frame by transforming + // the (1,0,0) vector. At least that works. + + //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame); + Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame); + //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis); + //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis); + d.JointSetHingeAxis(odeJoint, + jointAxis.X, + jointAxis.Y, + jointAxis.Z); + //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f); + if (joint is OdePhysicsJoint) + { + ((OdePhysicsJoint)joint).jointID = odeJoint; + } + else + { + DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!"); + } + } + break; + } + successfullyProcessedPendingJoints.Add(joint); + } + } + else + { + DoJointErrorMessage(joint, "joint could not yet be created; still pending"); + } + } + foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints) + { + //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams); + //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending"); + InternalRemovePendingJoint(successfullyProcessedJoint); + //DoJointErrorMessage(successfullyProcessedJoint, "adding to active"); + InternalAddActiveJoint(successfullyProcessedJoint); + //DoJointErrorMessage(successfullyProcessedJoint, "done"); + } + } + } + + if (processedtaints) +//Console.WriteLine("Simulate calls Clear of _taintedPrim list"); + _taintedPrimH.Clear(); + _taintedPrimL.Clear(); + } + + // Move characters + lock (_characters) + { + List defects = new List(); + foreach (OdeCharacter actor in _characters) + { + if (actor != null) + actor.Move(timeStep, defects); + } + if (0 != defects.Count) + { + foreach (OdeCharacter defect in defects) + { + RemoveCharacter(defect); + } + } + } + + // Move other active objects + lock (_activeprims) + { + foreach (OdePrim prim in _activeprims) + { + prim.m_collisionscore = 0; + prim.Move(timeStep); + } + } + + //if ((framecount % m_randomizeWater) == 0) + // randomizeWater(waterlevel); + + //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); + m_rayCastManager.ProcessQueuedRequests(); + + collision_optimized(timeStep); + + lock (_collisionEventPrim) + { + foreach (PhysicsActor obj in _collisionEventPrim) + { + if (obj == null) + continue; + + switch ((ActorTypes)obj.PhysicsActorType) + { + case ActorTypes.Agent: + OdeCharacter cobj = (OdeCharacter)obj; + cobj.AddCollisionFrameTime(100); + cobj.SendCollisions(); + break; + case ActorTypes.Prim: + OdePrim pobj = (OdePrim)obj; + pobj.SendCollisions(); + break; + } + } + } + + //if (m_global_contactcount > 5) + //{ + // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount); + //} + + m_global_contactcount = 0; + + d.WorldQuickStep(world, ODE_STEPSIZE); + d.JointGroupEmpty(contactgroup); + //ode.dunlock(world); + } + catch (Exception e) + { + m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e); + ode.dunlock(world); + } + + step_time -= ODE_STEPSIZE; + i++; + //} + //else + //{ + //fps = 0; + //} + //} + } + + lock (_characters) + { + foreach (OdeCharacter actor in _characters) + { + if (actor != null) + { + if (actor.bad) + m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid); + actor.UpdatePositionAndVelocity(); + } + } + } + + lock (_badCharacter) + { + if (_badCharacter.Count > 0) + { + foreach (OdeCharacter chr in _badCharacter) + { + RemoveCharacter(chr); + } + _badCharacter.Clear(); + } + } + + lock (_activeprims) + { + //if (timeStep < 0.2f) + { + foreach (OdePrim actor in _activeprims) + { + if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag)) + { + actor.UpdatePositionAndVelocity(); + + if (SupportsNINJAJoints) + { + // If an actor moved, move its joint proxy objects as well. + // There seems to be an event PhysicsActor.OnPositionUpdate that could be used + // for this purpose but it is never called! So we just do the joint + // movement code here. + + if (actor.SOPName != null && + joints_connecting_actor.ContainsKey(actor.SOPName) && + joints_connecting_actor[actor.SOPName] != null && + joints_connecting_actor[actor.SOPName].Count > 0) + { + foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName]) + { + if (affectedJoint.IsInPhysicsEngine) + { + DoJointMoved(affectedJoint); + } + else + { + DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams); + } + } + } + } + } + } + } + } + + //DumpJointInfo(); + + // Finished with all sim stepping. If requested, dump world state to file for debugging. + // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed? + // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots? + if (physics_logging && (physics_logging_interval>0) && (framecount % physics_logging_interval == 0)) + { + string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename + string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file + + if (physics_logging_append_existing_logfile) + { + string header = "-------------- START OF PHYSICS FRAME " + framecount.ToString() + " --------------"; + TextWriter fwriter = File.AppendText(fname); + fwriter.WriteLine(header); + fwriter.Close(); + } + d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); + } + } + + return fps; + } + + public override void GetResults() + { + } + + public override bool IsThreaded + { + // for now we won't be multithreaded + get { return (false); } + } + + #region ODE Specific Terrain Fixes + public float[] ResizeTerrain512NearestNeighbour(float[] heightMap) + { + float[] returnarr = new float[262144]; + float[,] resultarr = new float[(int)WorldExtents.X, (int)WorldExtents.Y]; + + // Filling out the array into its multi-dimensional components + for (int y = 0; y < WorldExtents.Y; y++) + { + for (int x = 0; x < WorldExtents.X; x++) + { + resultarr[y, x] = heightMap[y * (int)WorldExtents.Y + x]; + } + } + + // Resize using Nearest Neighbour + + // This particular way is quick but it only works on a multiple of the original + + // The idea behind this method can be described with the following diagrams + // second pass and third pass happen in the same loop really.. just separated + // them to show what this does. + + // First Pass + // ResultArr: + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + + // Second Pass + // ResultArr2: + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + + // Third pass fills in the blanks + // ResultArr2: + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + + // X,Y = . + // X+1,y = ^ + // X,Y+1 = * + // X+1,Y+1 = # + + // Filling in like this; + // .* + // ^# + // 1st . + // 2nd * + // 3rd ^ + // 4th # + // on single loop. + + float[,] resultarr2 = new float[512, 512]; + for (int y = 0; y < WorldExtents.Y; y++) + { + for (int x = 0; x < WorldExtents.X; x++) + { + resultarr2[y * 2, x * 2] = resultarr[y, x]; + + if (y < WorldExtents.Y) + { + resultarr2[(y * 2) + 1, x * 2] = resultarr[y, x]; + } + if (x < WorldExtents.X) + { + resultarr2[y * 2, (x * 2) + 1] = resultarr[y, x]; + } + if (x < WorldExtents.X && y < WorldExtents.Y) + { + resultarr2[(y * 2) + 1, (x * 2) + 1] = resultarr[y, x]; + } + } + } + + //Flatten out the array + int i = 0; + for (int y = 0; y < 512; y++) + { + for (int x = 0; x < 512; x++) + { + if (resultarr2[y, x] <= 0) + returnarr[i] = 0.0000001f; + else + returnarr[i] = resultarr2[y, x]; + + i++; + } + } + + return returnarr; + } + + public float[] ResizeTerrain512Interpolation(float[] heightMap) + { + float[] returnarr = new float[262144]; + float[,] resultarr = new float[512,512]; + + // Filling out the array into its multi-dimensional components + for (int y = 0; y < 256; y++) + { + for (int x = 0; x < 256; x++) + { + resultarr[y, x] = heightMap[y * 256 + x]; + } + } + + // Resize using interpolation + + // This particular way is quick but it only works on a multiple of the original + + // The idea behind this method can be described with the following diagrams + // second pass and third pass happen in the same loop really.. just separated + // them to show what this does. + + // First Pass + // ResultArr: + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + // 1,1,1,1,1,1 + + // Second Pass + // ResultArr2: + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + // ,,,,,,,,,, + // 1,,1,,1,,1,,1,,1, + + // Third pass fills in the blanks + // ResultArr2: + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + // 1,1,1,1,1,1,1,1,1,1,1,1 + + // X,Y = . + // X+1,y = ^ + // X,Y+1 = * + // X+1,Y+1 = # + + // Filling in like this; + // .* + // ^# + // 1st . + // 2nd * + // 3rd ^ + // 4th # + // on single loop. + + float[,] resultarr2 = new float[512,512]; + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + for (int x = 0; x < (int)Constants.RegionSize; x++) + { + resultarr2[y*2, x*2] = resultarr[y, x]; + + if (y < (int)Constants.RegionSize) + { + if (y + 1 < (int)Constants.RegionSize) + { + if (x + 1 < (int)Constants.RegionSize) + { + resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[(y*2) + 1, x*2] = ((resultarr[y, x] + resultarr[y + 1, x])/2); + } + } + else + { + resultarr2[(y*2) + 1, x*2] = resultarr[y, x]; + } + } + if (x < (int)Constants.RegionSize) + { + if (x + 1 < (int)Constants.RegionSize) + { + if (y + 1 < (int)Constants.RegionSize) + { + resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[y*2, (x*2) + 1] = ((resultarr[y, x] + resultarr[y, x + 1])/2); + } + } + else + { + resultarr2[y*2, (x*2) + 1] = resultarr[y, x]; + } + } + if (x < (int)Constants.RegionSize && y < (int)Constants.RegionSize) + { + if ((x + 1 < (int)Constants.RegionSize) && (y + 1 < (int)Constants.RegionSize)) + { + resultarr2[(y*2) + 1, (x*2) + 1] = ((resultarr[y, x] + resultarr[y + 1, x] + + resultarr[y, x + 1] + resultarr[y + 1, x + 1])/4); + } + else + { + resultarr2[(y*2) + 1, (x*2) + 1] = resultarr[y, x]; + } + } + } + } + //Flatten out the array + int i = 0; + for (int y = 0; y < 512; y++) + { + for (int x = 0; x < 512; x++) + { + if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x])) + { + m_log.Warn("[PHYSICS]: Non finite heightfield element detected. Setting it to 0"); + resultarr2[y, x] = 0; + } + returnarr[i] = resultarr2[y, x]; + i++; + } + } + + return returnarr; + } + + #endregion + + public override void SetTerrain(float[] heightMap) + { + if (m_worldOffset != Vector3.Zero && m_parentScene != null) + { + if (m_parentScene is OdeScene) + { + ((OdeScene)m_parentScene).SetTerrain(heightMap, m_worldOffset); + } + } + else + { + SetTerrain(heightMap, m_worldOffset); + } + } + + public void SetTerrain(float[] heightMap, Vector3 pOffset) + { + // this._heightmap[i] = (double)heightMap[i]; + // dbm (danx0r) -- creating a buffer zone of one extra sample all around + //_origheightmap = heightMap; + + float[] _heightmap; + + // zero out a heightmap array float array (single dimension [flattened])) + //if ((int)Constants.RegionSize == 256) + // _heightmap = new float[514 * 514]; + //else + + _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))]; + + uint heightmapWidth = Constants.RegionSize + 1; + uint heightmapHeight = Constants.RegionSize + 1; + + uint heightmapWidthSamples; + + uint heightmapHeightSamples; + + //if (((int)Constants.RegionSize) == 256) + //{ + // heightmapWidthSamples = 2 * (uint)Constants.RegionSize + 2; + // heightmapHeightSamples = 2 * (uint)Constants.RegionSize + 2; + // heightmapWidth++; + // heightmapHeight++; + //} + //else + //{ + + heightmapWidthSamples = (uint)Constants.RegionSize + 1; + heightmapHeightSamples = (uint)Constants.RegionSize + 1; + //} + + const float scale = 1.0f; + const float offset = 0.0f; + const float thickness = 0.2f; + const int wrap = 0; + + int regionsize = (int) Constants.RegionSize + 2; + //Double resolution + //if (((int)Constants.RegionSize) == 256) + // heightMap = ResizeTerrain512Interpolation(heightMap); + + + // if (((int)Constants.RegionSize) == 256 && (int)Constants.RegionSize == 256) + // regionsize = 512; + + float hfmin = 2000; + float hfmax = -2000; + + for (int x = 0; x < heightmapWidthSamples; x++) + { + for (int y = 0; y < heightmapHeightSamples; y++) + { + int xx = Util.Clip(x - 1, 0, regionsize - 1); + int yy = Util.Clip(y - 1, 0, regionsize - 1); + + + float val= heightMap[yy * (int)Constants.RegionSize + xx]; + _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val; + + hfmin = (val < hfmin) ? val : hfmin; + hfmax = (val > hfmax) ? val : hfmax; + } + } + + + + + lock (OdeLock) + { + IntPtr GroundGeom = IntPtr.Zero; + if (RegionTerrain.TryGetValue(pOffset, out GroundGeom)) + { + RegionTerrain.Remove(pOffset); + if (GroundGeom != IntPtr.Zero) + { + if (TerrainHeightFieldHeights.ContainsKey(GroundGeom)) + { + TerrainHeightFieldHeights.Remove(GroundGeom); + } + d.SpaceRemove(space, GroundGeom); + d.GeomDestroy(GroundGeom); + } + + } + IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); + d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth + 1, heightmapHeight + 1, + (int)heightmapWidthSamples + 1, (int)heightmapHeightSamples + 1, scale, + offset, thickness, wrap); + d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); + GroundGeom = d.CreateHeightfield(space, HeightmapData, 1); + if (GroundGeom != IntPtr.Zero) + { + d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); + d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); + + } + geom_name_map[GroundGeom] = "Terrain"; + + d.Matrix3 R = new d.Matrix3(); + + Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); + Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); + //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); + + q1 = q1 * q2; + //q1 = q1 * q3; + Vector3 v3; + float angle; + q1.GetAxisAngle(out v3, out angle); + + d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); + d.GeomSetRotation(GroundGeom, ref R); + d.GeomSetPosition(GroundGeom, (pOffset.X + ((int)Constants.RegionSize * 0.5f)) - 1, (pOffset.Y + ((int)Constants.RegionSize * 0.5f)) - 1, 0); + IntPtr testGround = IntPtr.Zero; + if (RegionTerrain.TryGetValue(pOffset, out testGround)) + { + RegionTerrain.Remove(pOffset); + } + RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); + TerrainHeightFieldHeights.Add(GroundGeom,_heightmap); + + } + } + + public override void DeleteTerrain() + { + } + + public float GetWaterLevel() + { + return waterlevel; + } + + public override bool SupportsCombining() + { + return true; + } + + public override void UnCombine(PhysicsScene pScene) + { + IntPtr localGround = IntPtr.Zero; +// float[] localHeightfield; + bool proceed = false; + List geomDestroyList = new List(); + + lock (OdeLock) + { + if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround)) + { + foreach (IntPtr geom in TerrainHeightFieldHeights.Keys) + { + if (geom == localGround) + { +// localHeightfield = TerrainHeightFieldHeights[geom]; + proceed = true; + } + else + { + geomDestroyList.Add(geom); + } + } + + if (proceed) + { + m_worldOffset = Vector3.Zero; + WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); + m_parentScene = null; + + foreach (IntPtr g in geomDestroyList) + { + // removingHeightField needs to be done or the garbage collector will + // collect the terrain data before we tell ODE to destroy it causing + // memory corruption + if (TerrainHeightFieldHeights.ContainsKey(g)) + { +// float[] removingHeightField = TerrainHeightFieldHeights[g]; + TerrainHeightFieldHeights.Remove(g); + + if (RegionTerrain.ContainsKey(g)) + { + RegionTerrain.Remove(g); + } + + d.GeomDestroy(g); + //removingHeightField = new float[0]; + } + } + + } + else + { + m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); + + } + } + } + } + + public override void SetWaterLevel(float baseheight) + { + waterlevel = baseheight; + randomizeWater(waterlevel); + } + + public void randomizeWater(float baseheight) + { + const uint heightmapWidth = m_regionWidth + 2; + const uint heightmapHeight = m_regionHeight + 2; + const uint heightmapWidthSamples = m_regionWidth + 2; + const uint heightmapHeightSamples = m_regionHeight + 2; + const float scale = 1.0f; + const float offset = 0.0f; + const float thickness = 2.9f; + const int wrap = 0; + + for (int i = 0; i < (258 * 258); i++) + { + _watermap[i] = (baseheight-0.1f) + ((float)fluidRandomizer.Next(1,9) / 10f); + // m_log.Info((baseheight - 0.1f) + ((float)fluidRandomizer.Next(1, 9) / 10f)); + } + + lock (OdeLock) + { + if (WaterGeom != IntPtr.Zero) + { + d.SpaceRemove(space, WaterGeom); + } + IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); + d.GeomHeightfieldDataBuildSingle(HeightmapData, _watermap, 0, heightmapWidth, heightmapHeight, + (int)heightmapWidthSamples, (int)heightmapHeightSamples, scale, + offset, thickness, wrap); + d.GeomHeightfieldDataSetBounds(HeightmapData, m_regionWidth, m_regionHeight); + WaterGeom = d.CreateHeightfield(space, HeightmapData, 1); + if (WaterGeom != IntPtr.Zero) + { + d.GeomSetCategoryBits(WaterGeom, (int)(CollisionCategories.Water)); + d.GeomSetCollideBits(WaterGeom, (int)(CollisionCategories.Space)); + + } + geom_name_map[WaterGeom] = "Water"; + + d.Matrix3 R = new d.Matrix3(); + + Quaternion q1 = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), 1.5707f); + Quaternion q2 = Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), 1.5707f); + //Axiom.Math.Quaternion q3 = Axiom.Math.Quaternion.FromAngleAxis(3.14f, new Axiom.Math.Vector3(0, 0, 1)); + + q1 = q1 * q2; + //q1 = q1 * q3; + Vector3 v3; + float angle; + q1.GetAxisAngle(out v3, out angle); + + d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); + d.GeomSetRotation(WaterGeom, ref R); + d.GeomSetPosition(WaterGeom, 128, 128, 0); + + } + + } + + public override void Dispose() + { + m_rayCastManager.Dispose(); + m_rayCastManager = null; + + lock (OdeLock) + { + lock (_prims) + { + foreach (OdePrim prm in _prims) + { + RemovePrim(prm); + } + } + + //foreach (OdeCharacter act in _characters) + //{ + //RemoveAvatar(act); + //} + d.WorldDestroy(world); + //d.CloseODE(); + } + } + public override Dictionary GetTopColliders() + { + Dictionary returncolliders = new Dictionary(); + int cnt = 0; + lock (_prims) + { + foreach (OdePrim prm in _prims) + { + if (prm.CollisionScore > 0) + { + returncolliders.Add(prm.m_localID, prm.CollisionScore); + cnt++; + prm.CollisionScore = 0f; + if (cnt > 25) + { + break; + } + } + } + } + return returncolliders; + } + + public override bool SupportsRayCast() + { + return true; + } + + public override void RaycastWorld(Vector3 position, Vector3 direction, float length, RaycastCallback retMethod) + { + if (retMethod != null) + { + m_rayCastManager.QueueRequest(position, direction, length, retMethod); + } + } + +#if USE_DRAWSTUFF + // Keyboard callback + public void command(int cmd) + { + IntPtr geom; + d.Mass mass; + d.Vector3 sides = new d.Vector3(d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f, d.RandReal() * 0.5f + 0.1f); + + + + Char ch = Char.ToLower((Char)cmd); + switch ((Char)ch) + { + case 'w': + try + { + Vector3 rotate = (new Vector3(1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD)); + + xyz.X += rotate.X; xyz.Y += rotate.Y; xyz.Z += rotate.Z; + ds.SetViewpoint(ref xyz, ref hpr); + } + catch (ArgumentException) + { hpr.X = 0; } + break; + + case 'a': + hpr.X++; + ds.SetViewpoint(ref xyz, ref hpr); + break; + + case 's': + try + { + Vector3 rotate2 = (new Vector3(-1, 0, 0) * Quaternion.CreateFromEulers(hpr.Z * Utils.DEG_TO_RAD, hpr.Y * Utils.DEG_TO_RAD, hpr.X * Utils.DEG_TO_RAD)); + + xyz.X += rotate2.X; xyz.Y += rotate2.Y; xyz.Z += rotate2.Z; + ds.SetViewpoint(ref xyz, ref hpr); + } + catch (ArgumentException) + { hpr.X = 0; } + break; + case 'd': + hpr.X--; + ds.SetViewpoint(ref xyz, ref hpr); + break; + case 'r': + xyz.Z++; + ds.SetViewpoint(ref xyz, ref hpr); + break; + case 'f': + xyz.Z--; + ds.SetViewpoint(ref xyz, ref hpr); + break; + case 'e': + xyz.Y++; + ds.SetViewpoint(ref xyz, ref hpr); + break; + case 'q': + xyz.Y--; + ds.SetViewpoint(ref xyz, ref hpr); + break; + } + } + + public void step(int pause) + { + + ds.SetColor(1.0f, 1.0f, 0.0f); + ds.SetTexture(ds.Texture.Wood); + lock (_prims) + { + foreach (OdePrim prm in _prims) + { + //IntPtr body = d.GeomGetBody(prm.prim_geom); + if (prm.prim_geom != IntPtr.Zero) + { + d.Vector3 pos; + d.GeomCopyPosition(prm.prim_geom, out pos); + //d.BodyCopyPosition(body, out pos); + + d.Matrix3 R; + d.GeomCopyRotation(prm.prim_geom, out R); + //d.BodyCopyRotation(body, out R); + + + d.Vector3 sides = new d.Vector3(); + sides.X = prm.Size.X; + sides.Y = prm.Size.Y; + sides.Z = prm.Size.Z; + + ds.DrawBox(ref pos, ref R, ref sides); + } + } + } + ds.SetColor(1.0f, 0.0f, 0.0f); + lock (_characters) + { + foreach (OdeCharacter chr in _characters) + { + if (chr.Shell != IntPtr.Zero) + { + IntPtr body = d.GeomGetBody(chr.Shell); + + d.Vector3 pos; + d.GeomCopyPosition(chr.Shell, out pos); + //d.BodyCopyPosition(body, out pos); + + d.Matrix3 R; + d.GeomCopyRotation(chr.Shell, out R); + //d.BodyCopyRotation(body, out R); + + ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f); + d.Vector3 sides = new d.Vector3(); + sides.X = 0.5f; + sides.Y = 0.5f; + sides.Z = 0.5f; + + ds.DrawBox(ref pos, ref R, ref sides); + } + } + } + } + + public void start(int unused) + { + ds.SetViewpoint(ref xyz, ref hpr); + } +#endif + } +} diff --git a/OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs new file mode 100644 index 0000000..69e2d03 --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/Tests/ODETestClass.cs @@ -0,0 +1,122 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Physics.Manager; +using log4net; +using System.Reflection; + +namespace OpenSim.Region.Physics.OdePlugin +{ + [TestFixture] + public class ODETestClass + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private OdePlugin cbt; + private PhysicsScene ps; + private IMeshingPlugin imp; + + [SetUp] + public void Initialize() + { + // Loading ODEPlugin + cbt = new OdePlugin(); + // Loading Zero Mesher + imp = new ZeroMesherPlugin(); + // Getting Physics Scene + ps = cbt.GetScene("test"); + // Initializing Physics Scene. + ps.Initialise(imp.GetMesher(),null); + float[] _heightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize]; + for (int i = 0; i < ((int)Constants.RegionSize * (int)Constants.RegionSize); i++) + { + _heightmap[i] = 21f; + } + ps.SetTerrain(_heightmap); + } + + [TearDown] + public void Terminate() + { + ps.DeleteTerrain(); + ps.Dispose(); + + } + + [Test] + public void CreateAndDropPhysicalCube() + { + PrimitiveBaseShape newcube = PrimitiveBaseShape.CreateBox(); + Vector3 position = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 128f); + Vector3 size = new Vector3(0.5f, 0.5f, 0.5f); + Quaternion rot = Quaternion.Identity; + PhysicsActor prim = ps.AddPrimShape("CoolShape", newcube, position, size, rot, true); + OdePrim oprim = (OdePrim)prim; + OdeScene pscene = (OdeScene) ps; + + Assert.That(oprim.m_taintadd); + + prim.LocalID = 5; + + for (int i = 0; i < 58; i++) + { + ps.Simulate(0.133f); + + Assert.That(oprim.prim_geom != (IntPtr)0); + + Assert.That(oprim.m_targetSpace != (IntPtr)0); + + //Assert.That(oprim.m_targetSpace == pscene.space); + m_log.Info("TargetSpace: " + oprim.m_targetSpace + " - SceneMainSpace: " + pscene.space); + + Assert.That(!oprim.m_taintadd); + m_log.Info("Prim Position (" + oprim.m_localID + "): " + prim.Position.ToString()); + + // Make sure we're above the ground + //Assert.That(prim.Position.Z > 20f); + //m_log.Info("PrimCollisionScore (" + oprim.m_localID + "): " + oprim.m_collisionscore); + + // Make sure we've got a Body + Assert.That(oprim.Body != (IntPtr)0); + //m_log.Info( + } + + // Make sure we're not somewhere above the ground + Assert.That(prim.Position.Z < 21.5f); + + ps.RemovePrim(prim); + Assert.That(oprim.m_taintremove); + ps.Simulate(0.133f); + Assert.That(oprim.Body == (IntPtr)0); + } + } +} diff --git a/OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs b/OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs new file mode 100644 index 0000000..87ca446 --- /dev/null +++ b/OpenSim/Region/Physics/ChOdePlugin/drawstuff.cs @@ -0,0 +1,98 @@ +/* + * Copyright ODE + * Ode.NET - .NET bindings for ODE + * Jason Perkins (starkos@industriousone.com) + * Licensed under the New BSD + * Part of the OpenDynamicsEngine +Open Dynamics Engine +Copyright (c) 2001-2007, Russell L. Smith. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +Neither the names of ODE's copyright owner nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * + */ + +using System; +using System.Runtime.InteropServices; +using Ode.NET; + +namespace Drawstuff.NET +{ +#if dDOUBLE + using dReal = System.Double; +#else + using dReal = System.Single; +#endif + + public static class ds + { + public const int VERSION = 2; + + public enum Texture + { + None, + Wood + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void CallbackFunction(int arg); + + [StructLayout(LayoutKind.Sequential)] + public struct Functions + { + public int version; + public CallbackFunction start; + public CallbackFunction step; + public CallbackFunction command; + public CallbackFunction stop; + public string path_to_textures; + } + + [DllImport("drawstuff", EntryPoint = "dsDrawBox")] + public static extern void DrawBox(ref d.Vector3 pos, ref d.Matrix3 R, ref d.Vector3 sides); + + [DllImport("drawstuff", EntryPoint = "dsDrawCapsule")] + public static extern void DrawCapsule(ref d.Vector3 pos, ref d.Matrix3 R, dReal length, dReal radius); + + [DllImport("drawstuff", EntryPoint = "dsDrawConvex")] + public static extern void DrawConvex(ref d.Vector3 pos, ref d.Matrix3 R, dReal[] planes, int planeCount, dReal[] points, int pointCount, int[] polygons); + + [DllImport("drawstuff", EntryPoint = "dsSetColor")] + public static extern void SetColor(float red, float green, float blue); + + [DllImport("drawstuff", EntryPoint = "dsSetTexture")] + public static extern void SetTexture(Texture texture); + + [DllImport("drawstuff", EntryPoint = "dsSetViewpoint")] + public static extern void SetViewpoint(ref d.Vector3 xyz, ref d.Vector3 hpr); + + [DllImport("drawstuff", EntryPoint = "dsSimulationLoop")] + public static extern void SimulationLoop(int argc, string[] argv, int window_width, int window_height, ref Functions fn); + } +} diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index b99baa2..06ed8fb 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -1197,26 +1197,13 @@ namespace OpenSim.Region.Physics.OdePlugin public override PIDHoverType PIDHoverType { set { return; } } public override float PIDHoverTau { set { return; } } - public override Quaternion APIDTarget - { - set { return; } - } + public override Quaternion APIDTarget{ set { return; } } - public override bool APIDActive - { - set { return; } - } + public override bool APIDActive{ set { return; } } - public override float APIDStrength - { - set { return; } - } - - public override float APIDDamping - { - set { return; } - } + public override float APIDStrength{ set { return; } } + public override float APIDDamping{ set { return; } } public override void SubscribeEvents(int ms) diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs index 78b15be..39cdc0f 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs @@ -23,19 +23,6 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. - * */ /* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces @@ -133,7 +120,7 @@ namespace OpenSim.Region.Physics.OdePlugin // private float m_VhoverEfficiency = 0f; private float m_VhoverTimescale = 0f; private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height - private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle. + private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. @@ -492,7 +479,7 @@ namespace OpenSim.Region.Physics.OdePlugin Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object m_dir *= rotq; // apply obj rotation to velocity vector - // add Gravity and Buoyancy + // add Gravity andBuoyancy // KF: So far I have found no good method to combine a script-requested // .Z velocity and gravity. Therefore only 0g will used script-requested // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. @@ -574,7 +561,6 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body */ -//if(frcount == 0) Console.WriteLine("MoveAngular "); // Get what the body is doing, this includes 'external' influences d.Vector3 angularVelocity = d.BodyGetAngularVel(Body); @@ -650,7 +636,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Deflection section tba // Sum velocities - m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // tba: + bank + deflection + m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) { diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 688be83..3eb3b28 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -21,18 +21,6 @@ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. */ /* @@ -93,12 +81,7 @@ namespace OpenSim.Region.Physics.OdePlugin private float m_PIDTau; private float PID_D = 35f; private float PID_G = 25f; - private bool m_usePID = false; - - private Quaternion m_APIDTarget = new Quaternion(); - private float m_APIDStrength = 0.5f; - private float m_APIDDamping = 0.5f; - private bool m_useAPID = false; + private bool m_usePID; // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), // and are for non-VEHICLES only. @@ -199,9 +182,6 @@ namespace OpenSim.Region.Physics.OdePlugin private ODEDynamics m_vehicle; internal int m_material = (int)Material.Wood; - - private int frcount = 0; // Used to limit dynamics debug output to - public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) @@ -1581,14 +1561,9 @@ Console.WriteLine(" JointCreateFixed"); float fy = 0; float fz = 0; - frcount++; // used to limit debug comment output - if (frcount > 100) - frcount = 0; if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. { -//if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_vehicle.Type + - // " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); if (m_vehicle.Type != Vehicle.TYPE_NONE) { // 'VEHICLES' are dealt with in ODEDynamics.cs @@ -1596,6 +1571,7 @@ Console.WriteLine(" JointCreateFixed"); } else { +//Console.WriteLine("Move " + m_primName); if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 // NON-'VEHICLES' are dealt with here if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f)) @@ -1617,18 +1593,21 @@ Console.WriteLine(" JointCreateFixed"); //m_log.Info(m_collisionFlags.ToString()); - //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle. + //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. + // would come from SceneObjectPart.cs, public void SetBuoyancy(float fvalue) , PhysActor.Buoyancy = fvalue; ?? // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up - // NB Prims in ODE are no subject to global gravity - fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass + // gravityz multiplier = 1 - m_buoyancy + fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; if (m_usePID) { -//if(frcount == 0) Console.WriteLine("PID " + m_primName); - // KF - this is for object MoveToTarget. - +//Console.WriteLine("PID " + m_primName); + // KF - this is for object move? eg. llSetPos() ? //if (!d.BodyIsEnabled(Body)) //d.BodySetForce(Body, 0f, 0f, 0f); + // If we're using the PID controller, then we have no gravity + //fz = (-1 * _parent_scene.gravityz) * m_mass; //KF: ?? Prims have no global gravity,so simply... + fz = 0f; // no lock; for now it's only called from within Simulate() @@ -1763,7 +1742,7 @@ Console.WriteLine(" JointCreateFixed"); d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); d.BodySetLinearVel(Body, vel.X, vel.Y, 0); d.BodyAddForce(Body, 0, 0, fz); - //KF this prevents furthur motions return; + return; } else { @@ -1772,46 +1751,8 @@ Console.WriteLine(" JointCreateFixed"); // We're flying and colliding with something fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); } - } // end m_useHoverPID && !m_usePID - - if (m_useAPID) - { - // RotLookAt, apparently overrides all other rotation sources. Inputs: - // Quaternion m_APIDTarget - // float m_APIDStrength // From SL experiments, this is the time to get there - // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly - // Also in SL the mass of the object has no effect on time to get there. - // Factors: -//if(frcount == 0) Console.WriteLine("APID "); - // get present body rotation - float limit = 1.0f; - float scaler = 50f; // adjusts damping time - float RLAservo = 0f; - - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); - Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget; - float diff_angle; - Vector3 diff_axis; - rot_diff.GetAxisAngle(out diff_axis, out diff_angle); - diff_axis.Normalize(); - if(diff_angle > 0.01f) // diff_angle is always +ve - { -// PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z); - Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z); - rotforce = rotforce * rotq; - if(diff_angle > limit) diff_angle = limit; // cap the rotate rate -// RLAservo = timestep / m_APIDStrength * m_mass * scaler; - // rotforce = rotforce * RLAservo * diff_angle ; - // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); - RLAservo = timestep / m_APIDStrength * scaler; - rotforce = rotforce * RLAservo * diff_angle ; - d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); -//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); - } -//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); - } // end m_useAPID - + } + fx *= m_mass; fy *= m_mass; //fz *= m_mass; @@ -2673,7 +2614,7 @@ Console.WriteLine(" JointCreateFixed"); m_lastposition = _position; m_lastorientation = _orientation; - + l_position.X = vec.X; l_position.Y = vec.Y; l_position.Z = vec.Z; @@ -2681,10 +2622,6 @@ Console.WriteLine(" JointCreateFixed"); l_orientation.Y = ori.Y; l_orientation.Z = ori.Z; l_orientation.W = ori.W; - -// if(l_position.Y != m_lastposition.Y){ -// Console.WriteLine("UP&V {0} {1}", m_primName, l_position); -// } if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f) { @@ -2885,17 +2822,20 @@ Console.WriteLine(" JointCreateFixed"); } public override bool PIDActive { set { m_usePID = value; } } public override float PIDTau { set { m_PIDTau = value; } } - - // For RotLookAt - public override Quaternion APIDTarget { set { m_APIDTarget = value; } } - public override bool APIDActive { set { m_useAPID = value; } } - public override float APIDStrength { set { m_APIDStrength = value; } } - public override float APIDDamping { set { m_APIDDamping = value; } } public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } public override bool PIDHoverActive { set { m_useHoverPID = value; } } public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } public override float PIDHoverTau { set { m_PIDHoverTau = value; } } + + public override Quaternion APIDTarget{ set { return; } } + + public override bool APIDActive{ set { return; } } + + public override float APIDStrength{ set { return; } } + + public override float APIDDamping{ set { return; } } + private void createAMotor(Vector3 axis) { diff --git a/prebuild.xml b/prebuild.xml index 9d428d1..9846164 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -543,6 +543,36 @@ + + + + ../../../../bin/Physics/ + + + + + ../../../../bin/Physics/ + + + + ../../../../bin/ + + + + + + + + + + + + + + + + + -- cgit v1.1 From b53b87166940ca0fca4ae2190649e18102c886ec Mon Sep 17 00:00:00 2001 From: root Date: Tue, 22 Dec 2009 06:25:32 +0100 Subject: Add a data path for error messages --- OpenSim/Framework/Capabilities/Caps.cs | 21 +++++++++++++-------- .../Framework/Interfaces/IEntityInventory.cs | 2 ++ .../Region/Framework/Interfaces/IScriptModule.cs | 3 +++ OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 18 ++++++++++++------ .../Framework/Scenes/SceneObjectPartInventory.cs | 22 ++++++++++++++++++++++ OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 5 +++++ 6 files changed, 57 insertions(+), 14 deletions(-) diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs index 1f1ac78..74c6ab0 100644 --- a/OpenSim/Framework/Capabilities/Caps.cs +++ b/OpenSim/Framework/Capabilities/Caps.cs @@ -46,7 +46,7 @@ namespace OpenSim.Framework.Capabilities public delegate UUID UpdateItem(UUID itemID, byte[] data); - public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data); + public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); public delegate void NewInventoryItem(UUID userID, InventoryItemBase item); @@ -54,7 +54,7 @@ namespace OpenSim.Framework.Capabilities public delegate UUID ItemUpdatedCallback(UUID userID, UUID itemID, byte[] data); - public delegate void TaskScriptUpdatedCallback(UUID userID, UUID itemID, UUID primID, + public delegate ArrayList TaskScriptUpdatedCallback(UUID userID, UUID itemID, UUID primID, bool isScriptRunning, byte[] data); public delegate InventoryCollection FetchInventoryDescendentsCAPS(UUID agentID, UUID folderID, UUID ownerID, @@ -940,11 +940,13 @@ namespace OpenSim.Framework.Capabilities /// Prim containing item to update /// Signals whether the script to update is currently running /// New asset data - public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, byte[] data) + public void TaskScriptUpdated(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors) { if (TaskScriptUpdatedCall != null) { - TaskScriptUpdatedCall(m_agentID, itemID, primID, isScriptRunning, data); + ArrayList e = TaskScriptUpdatedCall(m_agentID, itemID, primID, isScriptRunning, data); + foreach (Object item in e) + errors.Add(item); } } @@ -1174,17 +1176,20 @@ namespace OpenSim.Framework.Capabilities // data, path, param)); string res = String.Empty; - LLSDTaskInventoryUploadComplete uploadComplete = new LLSDTaskInventoryUploadComplete(); + LLSDTaskScriptUploadComplete uploadComplete = new LLSDTaskScriptUploadComplete(); + ArrayList errors = new ArrayList(); handlerUpdateTaskScript = OnUpLoad; if (handlerUpdateTaskScript != null) { - handlerUpdateTaskScript(inventoryItemID, primID, isScriptRunning, data); + handlerUpdateTaskScript(inventoryItemID, primID, isScriptRunning, data, ref errors); } - uploadComplete.item_id = inventoryItemID; - uploadComplete.task_id = primID; + uploadComplete.new_asset = inventoryItemID; + uploadComplete.compiled = errors.Count > 0 ? false : true; uploadComplete.state = "complete"; + uploadComplete.errors = new OSDArray(); + uploadComplete.errors.Array = errors; res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 89a45da..67395fa 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -26,6 +26,7 @@ */ using System.Collections.Generic; +using System.Collections; using OpenMetaverse; using OpenSim.Framework; @@ -71,6 +72,7 @@ namespace OpenSim.Region.Framework.Interfaces /// Start all the scripts contained in this entity's inventory /// void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource); + ArrayList GetScriptErrors(UUID itemID); /// /// Stop all the scripts in this entity. diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index 98efcbe..e90b300 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections; using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces @@ -39,5 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces bool PostScriptEvent(UUID itemID, string name, Object[] args); bool PostObjectEvent(UUID itemID, string name, Object[] args); + + ArrayList GetScriptErrors(UUID itemID); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 7ca779a..bce7d32 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Collections; using System.Reflection; using System.Text; using System.Timers; @@ -215,13 +216,13 @@ namespace OpenSim.Region.Framework.Scenes /// The prim which contains the item to update /// Indicates whether the script to update is currently running /// - public void CapsUpdateTaskInventoryScriptAsset(IClientAPI remoteClient, UUID itemId, + public ArrayList CapsUpdateTaskInventoryScriptAsset(IClientAPI remoteClient, UUID itemId, UUID primId, bool isScriptRunning, byte[] data) { if (!Permissions.CanEditScript(itemId, primId, remoteClient.AgentId)) { remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false); - return; + return new ArrayList(); } // Retrieve group @@ -234,7 +235,7 @@ namespace OpenSim.Region.Framework.Scenes "Prim inventory update requested for item ID {0} in prim ID {1} but this prim does not exist", itemId, primId); - return; + return new ArrayList(); } // Retrieve item @@ -247,7 +248,7 @@ namespace OpenSim.Region.Framework.Scenes + " but the item does not exist in this inventory", itemId, part.Name, part.UUID); - return; + return new ArrayList(); } AssetBase asset = CreateAsset(item.Name, item.Description, (sbyte)AssetType.LSLText, data); @@ -264,29 +265,33 @@ namespace OpenSim.Region.Framework.Scenes part.GetProperties(remoteClient); // Trigger rerunning of script (use TriggerRezScript event, see RezScript) + ArrayList errors = new ArrayList(); + if (isScriptRunning) { // Needs to determine which engine was running it and use that // part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); + errors = part.Inventory.GetScriptErrors(item.ItemID); } else { remoteClient.SendAgentAlertMessage("Script saved", false); } + return errors; } /// /// CapsUpdateTaskInventoryScriptAsset(IClientAPI, UUID, UUID, bool, byte[]) /// - public void CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId, + public ArrayList CapsUpdateTaskInventoryScriptAsset(UUID avatarId, UUID itemId, UUID primId, bool isScriptRunning, byte[] data) { ScenePresence avatar; if (TryGetAvatar(avatarId, out avatar)) { - CapsUpdateTaskInventoryScriptAsset( + return CapsUpdateTaskInventoryScriptAsset( avatar.ControllingClient, itemId, primId, isScriptRunning, data); } else @@ -295,6 +300,7 @@ namespace OpenSim.Region.Framework.Scenes "[PRIM INVENTORY]: " + "Avatar {0} cannot be found to update its prim item asset", avatarId); + return new ArrayList(); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index cdd23bd..c3c6342 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -29,6 +29,7 @@ using System; using System.Xml; using System.IO; using System.Collections.Generic; +using System.Collections; using System.Reflection; using OpenMetaverse; using log4net; @@ -210,6 +211,27 @@ namespace OpenSim.Region.Framework.Scenes } } + public ArrayList GetScriptErrors(UUID itemID) + { + ArrayList ret = new ArrayList(); + + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); + if (engines == null) // No engine at all + return ret; + + foreach (IScriptModule e in engines) + { + if (e != null) + { + ArrayList errors = e.GetScriptErrors(itemID); + foreach (Object line in errors) + ret.Add(line); + } + } + + return ret; + } + /// /// Stop all the scripts in this prim. /// diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 2a9a2db..31684ae 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1552,5 +1552,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine return true; } + + public ArrayList GetScriptErrors(UUID itemID) + { + return new ArrayList(); + } } } -- cgit v1.1 From bde26a8282cf7d3e173413a49a88f25a6bee0db1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 22 Dec 2009 06:43:03 +0100 Subject: Add missing file --- .../Capabilities/LLSDTaskScriptUploadComplete.cs | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 OpenSim/Framework/Capabilities/LLSDTaskScriptUploadComplete.cs diff --git a/OpenSim/Framework/Capabilities/LLSDTaskScriptUploadComplete.cs b/OpenSim/Framework/Capabilities/LLSDTaskScriptUploadComplete.cs new file mode 100644 index 0000000..d308831 --- /dev/null +++ b/OpenSim/Framework/Capabilities/LLSDTaskScriptUploadComplete.cs @@ -0,0 +1,54 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; +using System; +using System.Collections; + +namespace OpenSim.Framework.Capabilities +{ + [OSDMap] + public class LLSDTaskScriptUploadComplete + { + /// + /// The task inventory item that was updated + /// + public UUID new_asset; + + /// + /// Was it compiled? + /// + public bool compiled; + + /// + /// State of the upload. So far have only even seen this set to "complete" + /// + public string state; + + public OSDArray errors; + } +} -- cgit v1.1 From b575bf25245102fd43d025081b249cb730b865ac Mon Sep 17 00:00:00 2001 From: CasperW Date: Wed, 23 Dec 2009 14:14:20 +0100 Subject: Added some null reference and deleted group checks to certain functions to fix region crash scenarios. --- .../Shared/Api/Implementation/LSL_Api.cs | 114 +++++++++++++++------ 1 file changed, 85 insertions(+), 29 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 2da498a..84c2722 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -221,7 +221,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public List GetLinkParts(int linkType) { - List ret = new List(); + List ret = new List(); + if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) + return ret; ret.Add(m_host); switch (linkType) @@ -1136,7 +1138,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void llSetStatus(int status, int value) - { + { + if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) + return; m_host.AddScriptLPS(1); int statusrotationaxis = 0; @@ -1290,7 +1294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetScale(SceneObjectPart part, LSL_Vector scale) - { + { // TODO: this needs to trigger a persistance save as well if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; @@ -1349,7 +1353,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetColor(SceneObjectPart part, LSL_Vector color, int face) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + Primitive.TextureEntry tex = part.Shape.Textures; Color4 texcolor; if (face >= 0 && face < GetNumberOfSides(part)) @@ -1386,7 +1393,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void SetTexGen(SceneObjectPart part, int face,int style) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + Primitive.TextureEntry tex = part.Shape.Textures; MappingType textype; textype = MappingType.Default; @@ -1416,7 +1426,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void SetGlow(SceneObjectPart part, int face, float glow) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + Primitive.TextureEntry tex = part.Shape.Textures; if (face >= 0 && face < GetNumberOfSides(part)) { @@ -1441,7 +1454,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; Shininess sval = new Shininess(); @@ -1491,7 +1506,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void SetFullBright(SceneObjectPart part, int face, bool bright) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + Primitive.TextureEntry tex = part.Shape.Textures; if (face >= 0 && face < GetNumberOfSides(part)) { @@ -1558,7 +1576,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetAlpha(SceneObjectPart part, double alpha, int face) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + Primitive.TextureEntry tex = part.Shape.Textures; Color4 texcolor; if (face >= 0 && face < GetNumberOfSides(part)) @@ -1603,8 +1624,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, float wind, float tension, LSL_Vector Force) - { - if (part == null) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; if (flexi) @@ -1638,8 +1659,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) - { - if (part == null) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; if (light) @@ -1724,7 +1745,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetTexture(SceneObjectPart part, string texture, int face) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + UUID textureID=new UUID(); if (!UUID.TryParse(texture, out textureID)) @@ -1769,7 +1793,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + Primitive.TextureEntry tex = part.Shape.Textures; if (face >= 0 && face < GetNumberOfSides(part)) { @@ -1805,7 +1832,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + Primitive.TextureEntry tex = part.Shape.Textures; if (face >= 0 && face < GetNumberOfSides(part)) { @@ -1841,7 +1871,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void RotateTexture(SceneObjectPart part, double rotation, int face) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + Primitive.TextureEntry tex = part.Shape.Textures; if (face >= 0 && face < GetNumberOfSides(part)) { @@ -1911,7 +1944,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) LSL_Vector currentPos = llGetLocalPos(); @@ -2005,7 +2041,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetRot(SceneObjectPart part, Quaternion rot) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + part.UpdateRotation(rot); // Update rotation does not move the object in the physics scene if it's a linkset. @@ -6500,8 +6539,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist) - { - ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); + { + ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return shapeBlock; if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && @@ -6570,7 +6611,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + ObjectShapePacket.ObjectDataBlock shapeBlock; shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); @@ -6618,7 +6662,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + ObjectShapePacket.ObjectDataBlock shapeBlock; shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); @@ -6659,7 +6706,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } 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 fudge) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + ObjectShapePacket.ObjectDataBlock shapeBlock; shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); @@ -6779,7 +6829,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); UUID sculptId; @@ -6813,14 +6866,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void llSetPrimitiveParams(LSL_List rules) - { + { m_host.AddScriptLPS(1); SetPrimParams(m_host, rules); } public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) - { - m_host.AddScriptLPS(1); + { + m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); @@ -6829,7 +6882,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPrimParams(SceneObjectPart part, LSL_List rules) - { + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + return; + int idx = 0; while (idx < rules.Length) -- cgit v1.1 From a9f4d7a29c0f5b3ee10b46b9a27c5d10c7e71eb3 Mon Sep 17 00:00:00 2001 From: CasperW Date: Wed, 23 Dec 2009 17:34:08 +0100 Subject: Add a debugger tag to stop Visual Studio from breaking --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 8376846..c831c69 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1264,6 +1264,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine return UUID.Zero; } + [DebuggerNonUserCode] public void SetState(UUID itemID, string newState) { IScriptInstance instance = GetInstance(itemID); -- cgit v1.1 From 7f699fca9a34cd0f3525534bdbc04c8b8ee975fe Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 24 Dec 2009 18:18:14 +0100 Subject: Add the body to the LSL List Size property --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 38 +++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 1fc31c5..faf9c40 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -422,7 +422,8 @@ namespace OpenSim.Region.ScriptEngine.Shared public int Length { - get { + get + { if (m_data == null) m_data=new Object[0]; return m_data.Length; @@ -431,7 +432,40 @@ namespace OpenSim.Region.ScriptEngine.Shared public int Size { - get { return 0; } + get + { + if (m_data == null) + m_data=new Object[0]; + + int size = 0; + + foreach (Object o in m_data) + { + if (o is LSL_Types.LSLInteger) + size += 4; + else if (o is LSL_Types.LSLFloat) + size += 8; + else if (o is LSL_Types.LSLString) + size += ((LSL_Types.LSLString)o).m_string.Length; + else if (o is LSL_Types.key) + size += ((LSL_Types.key)o).value.Length; + else if (o is LSL_Types.Vector3) + size += 32; + else if (o is LSL_Types.Quaternion) + size += 64; + else if (o is int) + size += 4; + else if (o is string) + size += ((string)o).Length; + else if (o is float) + size += 8; + else if (o is double) + size += 16; + else + throw new Exception("Unknown type in List.Size: " + o.GetType().ToString()); + } + return size; + } } public object[] Data -- cgit v1.1 From e7439efc74a1cc0daedc51eb25ae66cd03db70b5 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 24 Dec 2009 19:19:44 -0500 Subject: Recover out-of-region objects during db load. --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 24 ++++++++++++++++++++++++ OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 4 +++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index a7d34f5..7274a06 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,7 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.6.91CM"; + private const string VERSION_NUMBER = "0.6.92Ch"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour { diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index b0fb8b3..998d598 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -222,6 +222,30 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) { + // KF: Check for out-of-region, move inside and make static. + Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, + sceneObject.RootPart.GroupPosition.Y, + sceneObject.RootPart.GroupPosition.Z); + if (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || + npos.X > Constants.RegionSize || + npos.Y > Constants.RegionSize) + { + if (npos.X < 0.0) npos.X = 1.0f; + if (npos.Y < 0.0) npos.Y = 1.0f; + if (npos.Z < 0.0) npos.Z = 0.0f; + if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; + if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; + + foreach (SceneObjectPart part in sceneObject.Children.Values) + { + part.GroupPosition = npos; + } + sceneObject.RootPart.Velocity = Vector3.Zero; + sceneObject.RootPart.AngularVelocity = Vector3.Zero; + sceneObject.RootPart.Acceleration = Vector3.Zero; + sceneObject.RootPart.Velocity = Vector3.Zero; + } + if (!alreadyPersisted) { sceneObject.ForceInventoryPersistence(); diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 983431d..0179240 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -215,6 +215,7 @@ namespace OpenSim.Region.Physics.OdePlugin parent_scene.GetTerrainHeightAtXY(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f)) + 0.5f); m_log.Warn("[PHYSICS]: Got nonFinite Object create Position"); } + _position = pos; m_taintposition = pos; PID_D = parent_scene.bodyPIDD; @@ -254,7 +255,8 @@ namespace OpenSim.Region.Physics.OdePlugin _parent_scene = parent_scene; m_targetSpace = (IntPtr)0; - if (pos.Z < 0) +// if (pos.Z < 0) + if (pos.Z < parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y)) m_isphysical = false; else { -- cgit v1.1 From b19e5643171d9a081426026c0e96c84c3e7f97b2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 25 Dec 2009 23:20:30 +0000 Subject: Restore version suffix. --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 7274a06..4844a66 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,7 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.6.92Ch"; + private const string VERSION_NUMBER = "0.6.92CM"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour { -- cgit v1.1 From 59f683066a60a99111cc032ee122dfe709c78440 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 25 Dec 2009 23:23:49 +0000 Subject: Set version back to core version (base) and suffix CM. Please DO NOT CHANGE THIS in the repo. This is the Caremninster repo and the number follows CORE. Always. --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 4844a66..f618047 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,7 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.6.92CM"; + private const string VERSION_NUMBER = "0.6.8CM"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour { -- cgit v1.1 From 43c303e27a93f07022ed0b151ca6945e34169ee9 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 26 Dec 2009 03:24:46 +0100 Subject: Make the GenericTableHandler work as intended --- OpenSim/Data/MySQL/MySQLGenericTableHandler.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index 9b8a001..4dfc324 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -37,7 +37,7 @@ using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Data.MySQL { - public class MySQLGenericTableHandler : MySqlFramework where T: struct + public class MySQLGenericTableHandler : MySqlFramework where T: class, new() { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -63,7 +63,7 @@ namespace OpenSim.Data.MySQL } Type t = typeof(T); - FieldInfo[] fields = t.GetFields(BindingFlags.NonPublic | + FieldInfo[] fields = t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly); @@ -165,7 +165,11 @@ namespace OpenSim.Data.MySQL new Dictionary(); foreach (string col in m_ColumnNames) + { data[col] = reader[col].ToString(); + if (data[col] == null) + data[col] = String.Empty; + } m_DataField.SetValue(row, data); } @@ -218,6 +222,8 @@ namespace OpenSim.Data.MySQL query = String.Format("replace into {0} (`", m_Realm) + String.Join("`,`", names.ToArray()) + "`) values ('" + String.Join("','", values.ToArray()) + "')"; + cmd.CommandText = query; + if (ExecuteNonQuery(cmd) > 0) return true; -- cgit v1.1 From 7371c7662a05d2c1dae1c110905817bb873cf934 Mon Sep 17 00:00:00 2001 From: CasperW Date: Sat, 26 Dec 2009 18:14:12 +0100 Subject: Fix for landing points. Only one scenario is not fully covered by this change, and that is people who teleport from neighbouring regions, who won't get affected by the landing point. --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 + .../Framework/Scenes/SceneCommunicationService.cs | 47 +++++++++++++++++----- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 25 ++++++++++-- 3 files changed, 59 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 265129c..37734f4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3460,6 +3460,7 @@ namespace OpenSim.Region.Framework.Scenes } } // Honor parcel landing type and position. + /* ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); if (land != null) { @@ -3468,6 +3469,7 @@ namespace OpenSim.Region.Framework.Scenes agent.startpos = land.LandData.UserLocation; } } + */// This is now handled properly in ScenePresence.MakeRootAgent } m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index e649139..0a02d39 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -706,17 +706,42 @@ namespace OpenSim.Region.Framework.Scenes { m_log.DebugFormat( "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}", - position, m_regionInfo.RegionName); - - // Teleport within the same region - if (IsOutsideRegion(avatar.Scene, position) || position.Z < 0) - { - Vector3 emergencyPos = new Vector3(128, 128, 128); - - m_log.WarnFormat( - "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", - position, avatar.Name, avatar.UUID, emergencyPos); - position = emergencyPos; + position, m_regionInfo.RegionName); + + // Teleport within the same region + if (IsOutsideRegion(avatar.Scene, position) || position.Z < 0) + { + Vector3 emergencyPos = new Vector3(128, 128, 128); + + m_log.WarnFormat( + "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", + position, avatar.Name, avatar.UUID, emergencyPos); + position = emergencyPos; + } + + Vector3 currentPos = avatar.AbsolutePosition; + ILandObject srcLand = m_scene.LandChannel.GetLandObject(currentPos.X, currentPos.Y); + ILandObject destLand = m_scene.LandChannel.GetLandObject(position.X, position.Y); + if (srcLand != null && destLand != null && (teleportFlags & (uint)TeleportFlags.ViaLure) == 0 && (teleportFlags & (uint)TeleportFlags.ViaGodlikeLure) == 0) + { + if (srcLand.LandData.LocalID == destLand.LandData.LocalID) + { + //TPing within the same parcel. If the landing point is restricted, block the TP. + //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. + if (destLand.LandData.LandingType == (byte)1 && destLand.LandData.UserLocation != Vector3.Zero && avatar.GodLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar.UUID) && destLand.LandData.OwnerID != avatar.UUID) + { + avatar.ControllingClient.SendAgentAlertMessage("Can't TP to the destination; landing point set.", false); + position = currentPos; + } + } + else + { + //Tping to a different parcel. Respect the landing point on the destination parcel. + if (destLand.LandData.LandingType == (byte)1 && destLand.LandData.UserLocation != Vector3.Zero && avatar.GodLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar.UUID) && destLand.LandData.OwnerID != avatar.UUID) + { + position = destLand.LandData.UserLocation; + } + } } // TODO: Get proper AVG Height diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index a3ad7ca..c3bc96a 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -836,9 +836,24 @@ namespace OpenSim.Region.Framework.Scenes { Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); pos.Y = crossedBorder.BorderLine.Z - 1; + } + + //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet. + //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent, + //they'll bypass the landing point. But I can't think of any decent way of fixing this. + if (KnownChildRegionHandles.Count == 0) + { + ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); + if (land != null) + { + //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. + if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godlevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) + { + pos = land.LandData.UserLocation; + } + } } - if (pos.X < 0 || pos.Y < 0 || pos.Z < 0) { Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128); @@ -973,9 +988,10 @@ namespace OpenSim.Region.Framework.Scenes public void Teleport(Vector3 pos) { bool isFlying = false; - if (m_physicsActor != null) - isFlying = m_physicsActor.Flying; + if (m_physicsActor != null) + isFlying = m_physicsActor.Flying; + RemoveFromPhysicalScene(); Velocity = Vector3.Zero; AbsolutePosition = pos; @@ -986,7 +1002,8 @@ namespace OpenSim.Region.Framework.Scenes SetHeight(m_appearance.AvatarHeight); } - SendTerseUpdateToAllClients(); + SendTerseUpdateToAllClients(); + } public void TeleportWithMomentum(Vector3 pos) -- cgit v1.1 From a6c93ce875c9e563de791002b309a3285266d597 Mon Sep 17 00:00:00 2001 From: CasperW Date: Sat, 26 Dec 2009 22:55:18 +0100 Subject: Make sure that we're not bounds checking attachments. 'Cos otherwise your hair will end up on your bum. Seen that before? --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 998d598..34a92fe 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -226,9 +226,9 @@ namespace OpenSim.Region.Framework.Scenes Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, sceneObject.RootPart.GroupPosition.Y, sceneObject.RootPart.GroupPosition.Z); - if (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || + if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || npos.X > Constants.RegionSize || - npos.Y > Constants.RegionSize) + npos.Y > Constants.RegionSize)) { if (npos.X < 0.0) npos.X = 1.0f; if (npos.Y < 0.0) npos.Y = 1.0f; -- cgit v1.1 From a18f4964cf43095a12dd6c91f606a7f28b0af4df Mon Sep 17 00:00:00 2001 From: root Date: Sun, 27 Dec 2009 01:32:23 +0100 Subject: Correct some issues with the last commit --- OpenSim/Data/MySQL/MySQLGenericTableHandler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index 58b95d7..b2bd5f6 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -205,7 +205,8 @@ namespace OpenSim.Data.MySQL foreach (FieldInfo fi in m_Fields.Values) { names.Add(fi.Name); - values.Add(fi.GetValue(row).ToString()); + values.Add("?" + fi.Name); + cmd.Parameters.AddWithValue(fi.Name, fi.GetValue(row).ToString()); } if (m_DataField != null) -- cgit v1.1 From 19a5e606b38372e882c13e27d6459ee703e07570 Mon Sep 17 00:00:00 2001 From: CasperW Date: Sun, 27 Dec 2009 07:08:16 +0100 Subject: Convert some remaining legacy lock()s for m_parts in SceneObjectGroup to ReaderWriteLockSlim, hopefully fixes a native crash --- .../Framework/Scenes/SceneObjectGroup.Inventory.cs | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 5a06bdb..65ce13a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -46,12 +46,12 @@ namespace OpenSim.Region.Framework.Scenes /// public void ForceInventoryPersistence() { - lock (m_parts) + lockPartsForRead(true); + List values = new List(m_parts.Values); + lockPartsForRead(false); + foreach (SceneObjectPart part in values) { - foreach (SceneObjectPart part in m_parts.Values) - { - part.Inventory.ForceInventoryPersistence(); - } + part.Inventory.ForceInventoryPersistence(); } } @@ -75,14 +75,16 @@ namespace OpenSim.Region.Framework.Scenes /// Stop the scripts contained in all the prims in this group /// public void RemoveScriptInstances() - { - lock (m_parts) + { + lockPartsForRead(true); + List values = new List(m_parts.Values); + lockPartsForRead(false); + + foreach (SceneObjectPart part in values) { - foreach (SceneObjectPart part in m_parts.Values) - { - part.Inventory.RemoveScriptInstances(); - } + part.Inventory.RemoveScriptInstances(); } + } /// -- cgit v1.1 From d321d23afe62e0e00f774901be3e1d1d0eda8c15 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 27 Dec 2009 16:01:36 +0000 Subject: Fix the spelling :/ --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index aeb97eb..8a5f209 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -4840,9 +4840,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP UserProfile.FirstLifeImage = Properties.FLImageID; UserProfile.Image = Properties.ImageID; UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL); - Userprofile.Flags &= ~3; - Userprofile.Flags |= Properties.AllowPublish ? 1 : 0; - Userprofile.Flags |= Properties.MaturePublish ? 2 : 0; + UserProfile.Flags &= ~3; + UserProfile.Flags |= Properties.AllowPublish ? 1 : 0; + UserProfile.Flags |= Properties.MaturePublish ? 2 : 0; handlerUpdateAvatarProperties(this, UserProfile); } -- cgit v1.1 From 045a44b1afb8a72da922eaea7b4d0ca1833bc9dd Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 27 Dec 2009 16:07:13 +0000 Subject: One should not copy/paste so much :) --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 8a5f209..ba81d05 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -4840,9 +4840,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP UserProfile.FirstLifeImage = Properties.FLImageID; UserProfile.Image = Properties.ImageID; UserProfile.ProfileUrl = Utils.BytesToString(Properties.ProfileURL); - UserProfile.Flags &= ~3; - UserProfile.Flags |= Properties.AllowPublish ? 1 : 0; - UserProfile.Flags |= Properties.MaturePublish ? 2 : 0; + UserProfile.UserFlags &= ~3; + UserProfile.UserFlags |= Properties.AllowPublish ? 1 : 0; + UserProfile.UserFlags |= Properties.MaturePublish ? 2 : 0; handlerUpdateAvatarProperties(this, UserProfile); } -- cgit v1.1 From 8ad8bd6282210c8ce0c00704edb3c55654ad2fc2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 27 Dec 2009 17:52:27 +0100 Subject: Fix up the new Sirikata cient view --- OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index e8d1889..4700bf2 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -449,7 +449,7 @@ namespace OpenSim.Client.Sirikata.ClientStack throw new System.NotImplementedException(); } - public void SendGenericMessage(string method, List message) + public void SendGenericMessage(string method, List message) { throw new System.NotImplementedException(); } -- cgit v1.1 From 06f639b8f345e075259d8b2ebfa96b9ed2174766 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 30 Dec 2009 00:27:01 +0100 Subject: Fix a timer list locking issue causing XMREngine deadlocks --- .../Shared/Api/Implementation/Plugins/Timer.cs | 32 ++++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs index eeb59d9..2fd33fe 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/Timer.cs @@ -109,25 +109,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins if (Timers.Count == 0) return; + Dictionary.ValueCollection tvals; lock (TimerListLock) { // Go through all timers - Dictionary.ValueCollection tvals = Timers.Values; - foreach (TimerClass ts in tvals) + tvals = Timers.Values; + } + + foreach (TimerClass ts in tvals) + { + // Time has passed? + if (ts.next < DateTime.Now.Ticks) { - // Time has passed? - if (ts.next < DateTime.Now.Ticks) - { - //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); - // Add it to queue - m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, - new EventParams("timer", new Object[0], - new DetectParams[0])); - // set next interval - - //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); - ts.next = DateTime.Now.Ticks + ts.interval; - } + //m_log.Debug("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next); + // Add it to queue + m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, + new EventParams("timer", new Object[0], + new DetectParams[0])); + // set next interval + + //ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + ts.next = DateTime.Now.Ticks + ts.interval; } } } -- cgit v1.1 From 8f0d6d6b5c2a66681cc80f33d10b0635a1257b25 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 30 Dec 2009 00:36:16 +0000 Subject: Fix an omission in LSL that causes a viewer crash --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index c9d6742..3a229c2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6363,6 +6363,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSLError("First parameter to llDialog needs to be a key"); return; } + if (buttons.Length < 1) + { + LSLError("No less than 1 button can be shown"); + return; + } if (buttons.Length > 12) { LSLError("No more than 12 buttons can be shown"); -- cgit v1.1 From cbe0841bc96d9ec834b06a0a012a50323698f719 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 30 Dec 2009 20:13:18 +0000 Subject: Revert "Merge branch 'master' into careminster" This reverts commit 596af3f600462fb1e467714e5b898c10aa3d838b. --- .../Scenes/Animation/ScenePresenceAnimator.cs | 8 --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 57 ++------------- .../RegionCombinerModule/RegionCombinerModule.cs | 82 ---------------------- 3 files changed, 4 insertions(+), 143 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 8f62855..e98f0e7 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -161,18 +161,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); // Check control flags -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS); bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG); -======= - bool heldForward = - (((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) || ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)); - bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; - bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; - bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG; ->>>>>>> master:OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index f05fe59..c3bc96a 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -173,12 +173,8 @@ namespace OpenSim.Region.Framework.Scenes protected RegionInfo m_regionInfo; protected ulong crossingFromRegion; -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/ScenePresence.cs private readonly Vector3[] Dir_Vectors = new Vector3[11]; private bool m_isNudging = false; -======= - private readonly Vector3[] Dir_Vectors = new Vector3[9]; ->>>>>>> master:OpenSim/Region/Framework/Scenes/ScenePresence.cs // Position of agent's camera in world (region cordinates) protected Vector3 m_CameraCenter; @@ -247,13 +243,9 @@ namespace OpenSim.Region.Framework.Scenes DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/ScenePresence.cs DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, -======= - DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, ->>>>>>> master:OpenSim/Region/Framework/Scenes/ScenePresence.cs DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG } @@ -735,43 +727,27 @@ namespace OpenSim.Region.Framework.Scenes Dir_Vectors[3] = -Vector3.UnitY; //RIGHT Dir_Vectors[4] = Vector3.UnitZ; //UP Dir_Vectors[5] = -Vector3.UnitZ; //DOWN -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/ScenePresence.cs Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge -======= - Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge - Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD - Dir_Vectors[7] = -Vector3.UnitX; //BACK ->>>>>>> master:OpenSim/Region/Framework/Scenes/ScenePresence.cs } private Vector3[] GetWalkDirectionVectors() { -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/ScenePresence.cs Vector3[] vector = new Vector3[11]; -======= - Vector3[] vector = new Vector3[9]; ->>>>>>> master:OpenSim/Region/Framework/Scenes/ScenePresence.cs vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK vector[2] = Vector3.UnitY; //LEFT vector[3] = -Vector3.UnitY; //RIGHT vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/ScenePresence.cs vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE vector[8] = Vector3.UnitY; //LEFT_NUDGE vector[9] = -Vector3.UnitY; //RIGHT_NUDGE vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE -======= - vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge - vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge - vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge ->>>>>>> master:OpenSim/Region/Framework/Scenes/ScenePresence.cs return vector; } @@ -1387,18 +1363,12 @@ namespace OpenSim.Region.Framework.Scenes else dirVectors = Dir_Vectors; -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/ScenePresence.cs bool[] isNudge = GetDirectionIsNudge(); -======= - // The fact that m_movementflag is a byte needs to be fixed - // it really should be a uint - uint nudgehack = 250; ->>>>>>> master:OpenSim/Region/Framework/Scenes/ScenePresence.cs foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) { if (((uint)flags & (uint)DCF) != 0) @@ -1408,47 +1378,28 @@ namespace OpenSim.Region.Framework.Scenes try { agent_control_v3 += dirVectors[i]; -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/ScenePresence.cs if (isNudge[i] == false) { Nudging = false; } -======= - //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); ->>>>>>> master:OpenSim/Region/Framework/Scenes/ScenePresence.cs } catch (IndexOutOfRangeException) { // Why did I get this? } - if ((m_movementflag & (byte)(uint)DCF) == 0) + if ((m_movementflag & (uint)DCF) == 0) { - if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) - { - m_movementflag |= (byte)nudgehack; - } m_movementflag += (byte)(uint)DCF; update_movementflag = true; } } else { - if ((m_movementflag & (byte)(uint)DCF) != 0 || - ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) - && ((m_movementflag & (byte)nudgehack) == nudgehack)) - ) // This or is for Nudge forward + if ((m_movementflag & (uint)DCF) != 0) { - m_movementflag -= ((byte)(uint)DCF); - + m_movementflag -= (byte)(uint)DCF; update_movementflag = true; - /* - if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) - && ((m_movementflag & (byte)nudgehack) == nudgehack)) - { - m_log.Debug("Removed Hack flag"); - } - */ } else { @@ -1589,7 +1540,7 @@ namespace OpenSim.Region.Framework.Scenes } } - if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0)) + if (update_movementflag) Animator.UpdateMovementAnimations(); m_scene.EventManager.TriggerOnClientMovement(this); diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 1a99c83..92f060b 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -88,89 +88,7 @@ namespace OpenSim.Region.RegionCombinerModule public void RegionLoaded(Scene scene) { if (enabledYN) - { RegionLoadedDoWork(scene); - - scene.EventManager.OnNewPresence += NewPresence; - } - } - - private void NewPresence(ScenePresence presence) - { - if (presence.IsChildAgent) - { - byte[] throttleData; - - try - { - throttleData = presence.ControllingClient.GetThrottlesPacked(1); - } - catch (NotImplementedException) - { - return; - } - - if (throttleData == null) - return; - - if (throttleData.Length == 0) - return; - - if (throttleData.Length != 28) - return; - - byte[] adjData; - int pos = 0; - - if (!BitConverter.IsLittleEndian) - { - byte[] newData = new byte[7 * 4]; - Buffer.BlockCopy(throttleData, 0, newData, 0, 7 * 4); - - for (int i = 0; i < 7; i++) - Array.Reverse(newData, i * 4, 4); - - adjData = newData; - } - else - { - adjData = throttleData; - } - - // 0.125f converts from bits to bytes - int resend = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - int land = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - int wind = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - int cloud = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - int task = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - int texture = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); pos += 4; - int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f); - // State is a subcategory of task that we allocate a percentage to - - - //int total = resend + land + wind + cloud + task + texture + asset; - - byte[] data = new byte[7 * 4]; - int ii = 0; - - Buffer.BlockCopy(Utils.FloatToBytes(resend), 0, data, ii, 4); ii += 4; - Buffer.BlockCopy(Utils.FloatToBytes(land * 50), 0, data, ii, 4); ii += 4; - Buffer.BlockCopy(Utils.FloatToBytes(wind), 0, data, ii, 4); ii += 4; - Buffer.BlockCopy(Utils.FloatToBytes(cloud), 0, data, ii, 4); ii += 4; - Buffer.BlockCopy(Utils.FloatToBytes(task), 0, data, ii, 4); ii += 4; - Buffer.BlockCopy(Utils.FloatToBytes(texture), 0, data, ii, 4); ii += 4; - Buffer.BlockCopy(Utils.FloatToBytes(asset), 0, data, ii, 4); - - try - { - presence.ControllingClient.SetChildAgentThrottle(data); - } - catch (NotImplementedException) - { - return; - } - - } } private void RegionLoadedDoWork(Scene scene) -- cgit v1.1 From 5e103f2b2eb51c35b435f6850fc088f1f905d9dd Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 30 Dec 2009 20:26:22 +0000 Subject: Revert "Merge branch 'master' into careminster" This reverts commit d49d44923d1be38f6fff12706b156562c6060566. --- .../Scenes/Animation/ScenePresenceAnimator.cs | 5 +---- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 18 ------------------ 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 6c64484..e98f0e7 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -151,10 +151,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation const float PREJUMP_DELAY = 0.25f; #region Inputs - if (m_scenePresence.SitGround) - { - return "SIT_GROUND_CONSTRAINED"; - } + AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; PhysicsActor actor = m_scenePresence.PhysicsActor; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index ee76cb6..c3bc96a 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -129,7 +129,6 @@ namespace OpenSim.Region.Framework.Scenes private Vector3? m_forceToApply; private uint m_requestedSitTargetID; private UUID m_requestedSitTargetUUID; - public bool SitGround = false; private SendCourseLocationsMethod m_sendCourseLocationsMethod; @@ -1300,17 +1299,8 @@ namespace OpenSim.Region.Framework.Scenes if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) { -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/ScenePresence.cs m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); -======= - // TODO: This doesn't prevent the user from walking yet. - // Setting parent ID would fix this, if we knew what value - // to use. Or we could add a m_isSitting variable. - //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); - SitGround = true; - ->>>>>>> master:OpenSim/Region/Framework/Scenes/ScenePresence.cs } // In the future, these values might need to go global. @@ -1550,11 +1540,7 @@ namespace OpenSim.Region.Framework.Scenes } } -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/ScenePresence.cs if (update_movementflag) -======= - if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) ->>>>>>> master:OpenSim/Region/Framework/Scenes/ScenePresence.cs Animator.UpdateMovementAnimations(); m_scene.EventManager.TriggerOnClientMovement(this); @@ -1665,12 +1651,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void StandUp() { - if (SitGround) - SitGround = false; - if (m_parentID != 0) { - m_log.Debug("StandupCode Executed"); SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); if (part != null) { -- cgit v1.1 From 9602227eb6d26cf76d8c88ac86558218ca11e918 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 31 Dec 2009 06:19:22 +0100 Subject: Add a small delay in NewAgentConnection to fix an issue with Hippo (and possibly other cleints) getting their data mixed up. --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2091bf0..2e34d1c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3414,6 +3414,9 @@ namespace OpenSim.Region.Framework.Scenes CapsModule.AddCapsHandler(agent.AgentID); + if ((teleportFlags & ((uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.ViaLocation | (uint)TeleportFlags.ViaLandmark | (uint)TeleportFlags.Default)) != 0) + System.Threading.Thread.Sleep(2000); + if (!agent.child) { if (TestBorderCross(agent.startpos,Cardinals.E)) -- cgit v1.1 From 3f901d313bfd11070d5260f867c8a73c14f2d109 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 31 Dec 2009 16:07:36 -0500 Subject: Vehicle Linear parameter adjustments --- OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs | 40 ++++++++++++--- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 12 +++-- OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs | 61 +++++++++++++---------- 3 files changed, 75 insertions(+), 38 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs index 78b15be..ef2dccc 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs @@ -83,6 +83,12 @@ namespace OpenSim.Region.Physics.OdePlugin // private IntPtr m_jointGroup = IntPtr.Zero; // private IntPtr m_aMotor = IntPtr.Zero; + // Correction factors, to match Sl + private static float m_linearVelocityFactor = 0.9f; + private static float m_linearAttackFactor = 0.4f; + private static float m_linearDecayFactor = 0.5f; + private static float m_linearFrictionFactor = 1.2f; + // Vehicle properties private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind @@ -98,7 +104,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Linear properties private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time - private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL + private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL, for max limiting private Vector3 m_dir = Vector3.Zero; // velocity applied to body private Vector3 m_linearFrictionTimescale = Vector3.Zero; private float m_linearMotorDecayTimescale = 0; @@ -267,8 +273,9 @@ namespace OpenSim.Region.Physics.OdePlugin m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); + pValue *= m_linearVelocityFactor; + m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, decayed by time + m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, for max limiting break; case Vehicle.LINEAR_MOTOR_OFFSET: // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -453,6 +460,17 @@ namespace OpenSim.Region.Physics.OdePlugin MoveAngular(pTimestep); }// end Step + internal void Halt() + { // Kill all motions, when non-physical + m_linearMotorDirection = Vector3.Zero; + m_linearMotorDirectionLASTSET = Vector3.Zero; + m_dir = Vector3.Zero; + m_lastLinearVelocityVector = Vector3.Zero; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorVelocity = Vector3.Zero; + m_lastAngularVelocity = Vector3.Zero; + } + private void MoveLinear(float pTimestep, OdeScene _pParentScene) { if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant @@ -460,9 +478,15 @@ namespace OpenSim.Region.Physics.OdePlugin if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // add drive to body - Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); - m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? - + float linfactor = m_linearMotorTimescale/pTimestep; + // Linear accel + Vector3 addAmount1 = (m_linearMotorDirection/linfactor) * 0.8f; + // Differential accel + Vector3 addAmount2 = ((m_linearMotorDirection - m_lastLinearVelocityVector)/linfactor) * 1.6f; + // SL correction + Vector3 addAmount = (addAmount1 + addAmount2) * m_linearAttackFactor; + m_lastLinearVelocityVector += addAmount; // lastLinearVelocityVector is the current body velocity vector +//if(frcount == 0) Console.WriteLine("AL {0} + AD {1} AS{2} V {3}", addAmount1, addAmount2, addAmount, m_lastLinearVelocityVector); // This will work temporarily, but we really need to compare speed on an axis // KF: Limit body velocity to applied velocity? if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) @@ -475,7 +499,7 @@ namespace OpenSim.Region.Physics.OdePlugin // decay applied velocity Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); //Console.WriteLine("decay: " + decayfraction); - m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; + m_linearMotorDirection -= m_linearMotorDirection * decayfraction * m_linearDecayFactor; //Console.WriteLine("actual: " + m_linearMotorDirection); } else @@ -560,7 +584,7 @@ namespace OpenSim.Region.Physics.OdePlugin // apply friction Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); - m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; + m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount * m_linearFrictionFactor; } // end MoveLinear() private void MoveAngular(float pTimestep) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 0179240..6e6b44f 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -2296,11 +2296,15 @@ Console.WriteLine(" JointCreateFixed"); public override bool IsPhysical { get { return m_isphysical; } - set { + set + { m_isphysical = value; - if (!m_isphysical) // Zero the remembered last velocity - m_lastVelocity = Vector3.Zero; - } + if (!m_isphysical) + { // Zero the remembered last velocity + m_lastVelocity = Vector3.Zero; + if (m_vehicle.Type != Vehicle.TYPE_NONE) m_vehicle.Halt(); + } + } } public void setPrimForRemoval() diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs index f48649e..60786d4 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs @@ -229,7 +229,7 @@ namespace OpenSim.Region.Physics.OdePlugin public int bodyFramesAutoDisable = 20; - + protected DateTime m_lastframe = DateTime.UtcNow; private float[] _watermap; private bool m_filterCollisions = true; @@ -2639,13 +2639,20 @@ namespace OpenSim.Region.Physics.OdePlugin { if (framecount >= int.MaxValue) framecount = 0; - //if (m_worldOffset != Vector3.Zero) // return 0; framecount++; - - float fps = 0; + + DateTime now = DateTime.UtcNow; + TimeSpan SinceLastFrame = now - m_lastframe; + m_lastframe = now; + float realtime = (float)SinceLastFrame.TotalSeconds; +// Console.WriteLine("ts={0} rt={1}", timeStep, realtime); + timeStep = realtime; + + // float fps = 1.0f / realtime; + float fps = 0.0f; // number of ODE steps in this Simulate step //m_log.Info(timeStep.ToString()); step_time += timeStep; @@ -2691,11 +2698,11 @@ namespace OpenSim.Region.Physics.OdePlugin // Figure out the Frames Per Second we're going at. //(step_time == 0.004f, there's 250 of those per second. Times the step time/step size - fps = (step_time / ODE_STEPSIZE) * 1000; + // fps = (step_time / ODE_STEPSIZE) * 1000; // HACK: Using a time dilation of 1.0 to debug rubberbanding issues //m_timeDilation = Math.Min((step_time / ODE_STEPSIZE) / (0.09375f / ODE_STEPSIZE), 1.0f); - step_time = 0.09375f; + // step_time = 0.09375f; while (step_time > 0.0f) { @@ -2716,7 +2723,7 @@ namespace OpenSim.Region.Physics.OdePlugin foreach (OdeCharacter character in _taintedActors) { - character.ProcessTaints(timeStep); + character.ProcessTaints(ODE_STEPSIZE); processedtaints = true; //character.m_collisionscore = 0; @@ -2725,7 +2732,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (processedtaints) _taintedActors.Clear(); } - } + } // end lock _taintedActors // Modify other objects in the scene. processedtaints = false; @@ -2742,7 +2749,7 @@ namespace OpenSim.Region.Physics.OdePlugin else { //Console.WriteLine("Simulate calls ProcessTaints"); - prim.ProcessTaints(timeStep); + prim.ProcessTaints(ODE_STEPSIZE); } processedtaints = true; prim.m_collisionscore = 0; @@ -2767,7 +2774,8 @@ namespace OpenSim.Region.Physics.OdePlugin foreach (PhysicsJoint joint in pendingJoints) { //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams); - string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries); + string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), + System.StringSplitOptions.RemoveEmptyEntries); List jointBodies = new List(); bool allJointBodiesAreReady = true; foreach (string jointParam in jointParams) @@ -2934,13 +2942,13 @@ namespace OpenSim.Region.Physics.OdePlugin //DoJointErrorMessage(successfullyProcessedJoint, "done"); } } - } + } // end SupportsNINJAJoints if (processedtaints) //Console.WriteLine("Simulate calls Clear of _taintedPrim list"); - _taintedPrimH.Clear(); + _taintedPrimH.Clear(); // ??? if this only ??? _taintedPrimL.Clear(); - } + } // end lock _taintedPrimLock // Move characters lock (_characters) @@ -2949,7 +2957,7 @@ namespace OpenSim.Region.Physics.OdePlugin foreach (OdeCharacter actor in _characters) { if (actor != null) - actor.Move(timeStep, defects); + actor.Move(ODE_STEPSIZE, defects); } if (0 != defects.Count) { @@ -2958,7 +2966,7 @@ namespace OpenSim.Region.Physics.OdePlugin RemoveCharacter(defect); } } - } + } // end lock _characters // Move other active objects lock (_activeprims) @@ -2966,9 +2974,9 @@ namespace OpenSim.Region.Physics.OdePlugin foreach (OdePrim prim in _activeprims) { prim.m_collisionscore = 0; - prim.Move(timeStep); + prim.Move(ODE_STEPSIZE); } - } + } // end lock _activeprims //if ((framecount % m_randomizeWater) == 0) // randomizeWater(waterlevel); @@ -2976,7 +2984,7 @@ namespace OpenSim.Region.Physics.OdePlugin //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); m_rayCastManager.ProcessQueuedRequests(); - collision_optimized(timeStep); + collision_optimized(ODE_STEPSIZE); lock (_collisionEventPrim) { @@ -2998,7 +3006,7 @@ namespace OpenSim.Region.Physics.OdePlugin break; } } - } + } // end lock _collisionEventPrim //if (m_global_contactcount > 5) //{ @@ -3009,8 +3017,9 @@ namespace OpenSim.Region.Physics.OdePlugin d.WorldQuickStep(world, ODE_STEPSIZE); d.JointGroupEmpty(contactgroup); + fps++; //ode.dunlock(world); - } + } // end try catch (Exception e) { m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e); @@ -3025,7 +3034,7 @@ namespace OpenSim.Region.Physics.OdePlugin //fps = 0; //} //} - } + } // end while (step_time > 0.0f) lock (_characters) { @@ -3090,7 +3099,7 @@ namespace OpenSim.Region.Physics.OdePlugin } } } - } + } // end lock _activeprims //DumpJointInfo(); @@ -3111,10 +3120,10 @@ namespace OpenSim.Region.Physics.OdePlugin } d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); } - } - - return fps; - } + } // end lock OdeLock + + return fps * 1000.0f; //NB This is a FRAME COUNT, not a time! AND is divide by 1000 in SimStatusReporter! + } // end Simulate public override void GetResults() { -- cgit v1.1 From 71fdc24f5c3d5805e185aac949e38f3c8058e03e Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 2 Jan 2010 21:21:31 +0100 Subject: Add virtual method StateChange to ScriptBaseClass --- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs index a44abb0..b138da3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/ScriptBase.cs @@ -128,6 +128,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_InitialValues = GetVars(); } + public virtual void StateChange(string newState) + { + } + public void Close() { // m_sponser.Close(); -- cgit v1.1 From 1121919b57e1495d0357d59e010a865b91757bfb Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 3 Jan 2010 22:02:36 +0000 Subject: Solve conflict --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index eda3d60..a14e3ad 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2910,13 +2910,6 @@ namespace OpenSim.Region.Framework.Scenes SetText(text); } - public void StopLookAt() - { - m_parentGroup.stopLookAt(); - - m_parentGroup.ScheduleGroupForTerseUpdate(); - } - public void StopMoveToTarget() { m_parentGroup.stopMoveToTarget(); -- cgit v1.1 From 53d3f46add698dd862c018e614778c1c19b0eda4 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 4 Jan 2010 18:47:47 +0000 Subject: First stage port of the XInventoryService --- OpenSim/Data/IXInventoryData.cs | 82 ++++ OpenSim/Data/MySQL/MySQLGenericTableHandler.cs | 5 + OpenSim/Data/MySQL/MySQLXInventoryData.cs | 113 +++++ .../Services/InventoryService/XInventoryService.cs | 474 +++++++++++++++++++++ 4 files changed, 674 insertions(+) create mode 100644 OpenSim/Data/IXInventoryData.cs create mode 100644 OpenSim/Data/MySQL/MySQLXInventoryData.cs create mode 100644 OpenSim/Services/InventoryService/XInventoryService.cs diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs new file mode 100644 index 0000000..88174d9 --- /dev/null +++ b/OpenSim/Data/IXInventoryData.cs @@ -0,0 +1,82 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data +{ + public class XInventoryFolder + { + public string folderName; + public int type; + public int version; + public UUID folderID; + public UUID agentID; + public UUID parentFolderID; + } + + public class XInventoryItem + { + public UUID assetID; + public int assetType; + public string inventoryName; + public string inventoryDescription; + public int inventoryNextPermissions; + public int inventoryCurrentPermissions; + public int invType; + public UUID creatorID; + public int inventoryBasePermissions; + public int inventoryEveryOnePermissions; + public int salePrice; + public int saleType; + public int creationDate; + public UUID groupID; + public bool groupOwned; + public int flags; + public UUID inventoryID; + public UUID avatarID; + public UUID parentFolderID; + public int inventoryGroupPermissions; + } + + public interface IXInventoryData + { + XInventoryFolder[] GetFolders(string[] fields, string[] vals); + XInventoryItem[] GetItems(string[] fields, string[] vals); + + bool StoreFolder(XInventoryFolder folder); + bool StoreItem(XInventoryItem item); + + bool DeleteFolders(string field, string val); + bool DeleteItems(string field, string val); + + bool MoveItem(string principalID, string id, string newParent); + } +} diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index b2bd5f6..fdb98eb 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -153,6 +153,11 @@ namespace OpenSim.Data.MySQL UUID.TryParse(reader[name].ToString(), out uuid); m_Fields[name].SetValue(row, uuid); } + else if (m_Fields[name].GetValue(row) is int) + { + int v = Convert.ToInt32(reader[name]); + m_Fields[name].SetValue(row, v); + } else { m_Fields[name].SetValue(row, reader[name]); diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs new file mode 100644 index 0000000..dd3e6ea --- /dev/null +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -0,0 +1,113 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Data; +using System.Reflection; +using System.Collections.Generic; +using log4net; +using MySql.Data.MySqlClient; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.MySQL +{ + /// + /// A MySQL Interface for the Asset Server + /// + public class MySQLXInventoryData : IXInventoryData + { + private static readonly ILog m_log = LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private MySQLGenericTableHandler m_Folders; + private MySqlItemHandler m_Items; + + public MySQLXInventoryData(string conn, string realm) + { + m_Folders = new MySQLGenericTableHandler( + conn, "inventoryfolders", "InventoryStore"); + m_Items = new MySqlItemHandler( + conn, "inventoryitems", String.Empty); + } + + public XInventoryFolder[] GetFolders(string[] fields, string[] vals) + { + return m_Folders.Get(fields, vals); + } + + public XInventoryItem[] GetItems(string[] fields, string[] vals) + { + return m_Items.Get(fields, vals); + } + + public bool StoreFolder(XInventoryFolder folder) + { + return m_Folders.Store(folder); + } + + public bool StoreItem(XInventoryItem item) + { + return m_Items.Store(item); + } + + public bool DeleteFolders(string field, string val) + { + return m_Folders.Delete(field, val); + } + + public bool DeleteItems(string field, string val) + { + return m_Items.Delete(field, val); + } + + public bool MoveItem(string principalID, string id, string newParent) + { + return m_Items.MoveItem(principalID, id, newParent); + } + } + + public class MySqlItemHandler : MySQLGenericTableHandler + { + public MySqlItemHandler(string c, string t, string m) : + base(c, t, m) + { + } + + public bool MoveItem(string principalID, string id, string newParent) + { + MySqlCommand cmd = new MySqlCommand(); + + cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where agentID = ?AgentID and folderID = ?FolderID"); + cmd.Parameters.AddWithValue("?ParentFolderID", newParent); + cmd.Parameters.AddWithValue("?FolderID", id); + cmd.Parameters.AddWithValue("?AgentID", principalID); + + return ExecuteNonQuery(cmd) == 0 ? false : true; + } + } +} diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs new file mode 100644 index 0000000..1e7f206 --- /dev/null +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -0,0 +1,474 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using log4net; +using Nini.Config; +using System.Reflection; +using OpenSim.Services.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Data; +using OpenSim.Framework; + +namespace OpenSim.Services.InventoryService +{ + public class XInventoryService : ServiceBase, IInventoryService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + protected IXInventoryData m_Database; + + public XInventoryService(IConfigSource config) : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + //string realm = "Inventory"; // OSG version doesn't use this + + // + // Try reading the [InventoryService] section first, if it exists + // + IConfig authConfig = config.Configs["InventoryService"]; + if (authConfig != null) + { + dllName = authConfig.GetString("StorageProvider", dllName); + connString = authConfig.GetString("ConnectionString", connString); + // realm = authConfig.GetString("Realm", realm); + } + + // + // Try reading the [DatabaseService] section, if it exists + // + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (connString == String.Empty) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + + // + // We tried, but this doesn't exist. We can't proceed. + // + if (dllName == String.Empty) + throw new Exception("No StorageProvider configured"); + + m_Database = LoadPlugin(dllName, + new Object[] {connString, String.Empty}); + if (m_Database == null) + throw new Exception("Could not find a storage interface in the given module"); + } + + public bool CreateUserInventory(UUID principalID) + { + // This is braindeaad. We can't ever communicate that we fixed + // an existing inventory. Well, just return root folder status, + // but check sanity anyway. + // + bool result = false; + + InventoryFolderBase rootFolder = GetRootFolder(principalID); + + if (rootFolder == null) + { + rootFolder = ConvertToOpenSim(CreateFolder(principalID, UUID.Zero, (int)AssetType.Folder, "My Inventory")); + result = true; + } + + XInventoryFolder[] sysFolders = GetSystemFolders(principalID); + + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Animation) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.Animation, "Animations"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Bodypart) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.Bodypart, "Body Parts"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.CallingCard) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.CallingCard, "Calling Cards"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Clothing) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.Clothing, "Clothing"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Gesture) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.Gesture, "Gestures"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Landmark) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.Landmark, "Landmarks"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.LostAndFoundFolder) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.LostAndFoundFolder, "Lost And Found"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Notecard) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.Notecard, "Notecards"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Object) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.Object, "Objects"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.SnapshotFolder) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.SnapshotFolder, "Photo Album"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.LSLText) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.LSLText, "Scripts"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Sound) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.Sound, "Sounds"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.Texture) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.Texture, "Textures"); + if (!Array.Exists(sysFolders, delegate (XInventoryFolder f) { if (f.type == (int)AssetType.TrashFolder) return true; return false; })) + CreateFolder(principalID, rootFolder.ID, (int)AssetType.TrashFolder, "Trash"); + + return result; + } + + private XInventoryFolder CreateFolder(UUID principalID, UUID parentID, int type, string name) + { + XInventoryFolder newFolder = new XInventoryFolder(); + + newFolder.folderName = name; + newFolder.type = type; + newFolder.version = 1; + newFolder.folderID = UUID.Random(); + newFolder.agentID = principalID; + newFolder.parentFolderID = parentID; + + m_Database.StoreFolder(newFolder); + + return newFolder; + } + + private XInventoryFolder[] GetSystemFolders(UUID principalID) + { + XInventoryFolder[] allFolders = m_Database.GetFolders( + new string[] { "agentID" }, + new string[] { principalID.ToString() }); + + XInventoryFolder[] sysFolders = Array.FindAll( + allFolders, + delegate (XInventoryFolder f) + { + if (f.type > 0) + return true; + return false; + }); + + return sysFolders; + } + + public List GetInventorySkeleton(UUID principalID) + { + XInventoryFolder[] allFolders = m_Database.GetFolders( + new string[] { "agentID" }, + new string[] { principalID.ToString() }); + + if (allFolders.Length == 0) + return null; + + List folders = new List(); + + foreach (XInventoryFolder x in allFolders) + folders.Add(ConvertToOpenSim(x)); + + return folders; + } + + public InventoryFolderBase GetRootFolder(UUID principalID) + { + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "parentFolderID"}, + new string[] { principalID.ToString(), UUID.Zero.ToString() }); + + if (folders.Length == 0) + return null; + + return ConvertToOpenSim(folders[0]); + } + + public InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) + { + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "type"}, + new string[] { principalID.ToString(), ((int)type).ToString() }); + + if (folders.Length == 0) + return null; + + return ConvertToOpenSim(folders[0]); + } + + public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) + { + InventoryCollection inventory = new InventoryCollection(); + inventory.UserID = principalID; + inventory.Folders = new List(); + inventory.Items = new List(); + + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "parentFolderID"}, + new string[] { principalID.ToString(), UUID.Zero.ToString() }); + + foreach (XInventoryFolder x in folders) + inventory.Folders.Add(ConvertToOpenSim(x)); + + XInventoryItem[] items = m_Database.GetItems( + new string[] { "avatarID", "parentFolderID"}, + new string[] { principalID.ToString(), UUID.Zero.ToString() }); + + foreach (XInventoryItem i in items) + inventory.Items.Add(ConvertToOpenSim(i)); + + return inventory; + } + + public List GetFolderItems(UUID principalID, UUID folderID) + { + List invItems = new List(); + + XInventoryItem[] items = m_Database.GetItems( + new string[] { "avatarID", "parentFolderID"}, + new string[] { principalID.ToString(), UUID.Zero.ToString() }); + + foreach (XInventoryItem i in items) + invItems.Add(ConvertToOpenSim(i)); + + return invItems; + } + + public bool AddFolder(InventoryFolderBase folder) + { + XInventoryFolder xFolder = ConvertFromOpenSim(folder); + return m_Database.StoreFolder(xFolder); + } + + public bool UpdateFolder(InventoryFolderBase folder) + { + return AddFolder(folder); + } + + public bool MoveFolder(InventoryFolderBase folder) + { + XInventoryFolder[] x = m_Database.GetFolders( + new string[] { "folderID" }, + new string[] { folder.ID.ToString() }); + + if (x.Length == 0) + return false; + + x[0].parentFolderID = folder.ParentID; + + return m_Database.StoreFolder(x[0]); + } + + // We don't check the principal's ID here + // + public bool DeleteFolders(UUID principalID, List folderIDs) + { + foreach (UUID id in folderIDs) + { + InventoryFolderBase f = new InventoryFolderBase(); + f.ID = id; + PurgeFolder(f); + m_Database.DeleteFolders("folderID", id.ToString()); + } + + return true; + } + + public bool PurgeFolder(InventoryFolderBase folder) + { + XInventoryFolder[] subFolders = m_Database.GetFolders( + new string[] { "parentFolderID" }, + new string[] { folder.ID.ToString() }); + + foreach (XInventoryFolder x in subFolders) + PurgeFolder(ConvertToOpenSim(x)); + + m_Database.DeleteItems("parentFolderID", folder.ID.ToString()); + + return true; + } + + public bool AddItem(InventoryItemBase item) + { + return m_Database.StoreItem(ConvertFromOpenSim(item)); + } + + public bool UpdateItem(InventoryItemBase item) + { + return m_Database.StoreItem(ConvertFromOpenSim(item)); + } + + public bool MoveItems(UUID principalID, List items) + { + foreach (InventoryItemBase i in items) + { + m_Database.MoveItem(principalID.ToString(), i.ID.ToString(), + i.Folder.ToString()); + } + + return true; + } + + public bool DeleteItems(UUID principalID, List itemIDs) + { + foreach (UUID id in itemIDs) + m_Database.DeleteItems("inventoryID", id.ToString()); + + return true; + } + + public InventoryItemBase GetItem(InventoryItemBase item) + { + XInventoryItem[] items = m_Database.GetItems( + new string[] { "inventoryID" }, + new string[] { item.ID.ToString() }); + + if (items.Length == 0) + return null; + + return ConvertToOpenSim(items[0]); + } + + public InventoryFolderBase GetFolder(InventoryFolderBase folder) + { + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "folderID"}, + new string[] { folder.ID.ToString() }); + + if (folders.Length == 0) + return null; + + return ConvertToOpenSim(folders[0]); + } + + public List GetActiveGestures(UUID userId) + { + return null; + } + + public int GetAssetPermissions(UUID userID, UUID assetID) + { + return 0; + } + + // CM never needed those. Left unimplemented. + // Obsolete in core + // + public InventoryCollection GetUserInventory(UUID userID) + { + return null; + } + public void GetUserInventory(UUID userID, InventoryReceiptCallback callback) + { + } + + // Unused. + // + public bool HasInventoryForUser(UUID userID) + { + return false; + } + + // CM Helpers + // + private InventoryFolderBase ConvertToOpenSim(XInventoryFolder folder) + { + InventoryFolderBase newFolder = new InventoryFolderBase(); + + newFolder.ParentID = folder.parentFolderID; + newFolder.Type = (short)folder.type; + newFolder.Version = (ushort)folder.version; + newFolder.Name = folder.folderName; + newFolder.Owner = folder.agentID; + newFolder.ID = folder.folderID; + + return newFolder; + } + + private XInventoryFolder ConvertFromOpenSim(InventoryFolderBase folder) + { + XInventoryFolder newFolder = new XInventoryFolder(); + + newFolder.parentFolderID = folder.ParentID; + newFolder.type = (int)folder.Type; + newFolder.version = (int)folder.Version; + newFolder.folderName = folder.Name; + newFolder.agentID = folder.Owner; + newFolder.folderID = folder.ID; + + return newFolder; + } + + private InventoryItemBase ConvertToOpenSim(XInventoryItem item) + { + InventoryItemBase newItem = new InventoryItemBase(); + + newItem.AssetID = item.assetID; + newItem.AssetType = item.assetType; + newItem.Name = item.inventoryName; + newItem.Owner = item.avatarID; + newItem.ID = item.inventoryID; + newItem.InvType = item.invType; + newItem.Folder = item.parentFolderID; + newItem.CreatorId = item.creatorID.ToString(); + newItem.Description = item.inventoryDescription; + newItem.NextPermissions = (uint)item.inventoryNextPermissions; + newItem.CurrentPermissions = (uint)item.inventoryCurrentPermissions; + newItem.BasePermissions = (uint)item.inventoryBasePermissions; + newItem.EveryOnePermissions = (uint)item.inventoryEveryOnePermissions; + newItem.GroupPermissions = (uint)item.inventoryGroupPermissions; + newItem.GroupID = item.groupID; + newItem.GroupOwned = item.groupOwned; + newItem.SalePrice = item.salePrice; + newItem.SaleType = (byte)item.saleType; + newItem.Flags = (uint)item.flags; + newItem.CreationDate = item.creationDate; + + return newItem; + } + + private XInventoryItem ConvertFromOpenSim(InventoryItemBase item) + { + XInventoryItem newItem = new XInventoryItem(); + + newItem.assetID = item.AssetID; + newItem.assetType = item.AssetType; + newItem.inventoryName = item.Name; + newItem.avatarID = item.Owner; + newItem.inventoryID = item.ID; + newItem.invType = item.InvType; + newItem.parentFolderID = item.Folder; + newItem.creatorID = item.CreatorIdAsUuid; + newItem.inventoryDescription = item.Description; + newItem.inventoryNextPermissions = (int)item.NextPermissions; + newItem.inventoryCurrentPermissions = (int)item.CurrentPermissions; + newItem.inventoryBasePermissions = (int)item.BasePermissions; + newItem.inventoryEveryOnePermissions = (int)item.EveryOnePermissions; + newItem.inventoryGroupPermissions = (int)item.GroupPermissions; + newItem.groupID = item.GroupID; + newItem.groupOwned = item.GroupOwned; + newItem.salePrice = item.SalePrice; + newItem.saleType = (int)item.SaleType; + newItem.flags = (int)item.Flags; + newItem.creationDate = item.CreationDate; + + return newItem; + } + } +} -- cgit v1.1 From 0907d5d69e10ba5be79a6d03366ce3cfa59c0bec Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 4 Jan 2010 20:52:44 +0000 Subject: Finish conversion if XInventoryService --- OpenSim/Data/IXInventoryData.cs | 4 +- OpenSim/Data/MySQL/MySQLXInventoryData.cs | 55 +++++++++++++++++--- .../Services/InventoryService/XInventoryService.cs | 58 +++++++++++++++++----- 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs index 88174d9..cd9273e 100644 --- a/OpenSim/Data/IXInventoryData.cs +++ b/OpenSim/Data/IXInventoryData.cs @@ -77,6 +77,8 @@ namespace OpenSim.Data bool DeleteFolders(string field, string val); bool DeleteItems(string field, string val); - bool MoveItem(string principalID, string id, string newParent); + bool MoveItem(string id, string newParent); + XInventoryItem[] GetActiveGestures(UUID principalID); + int GetAssetPermissions(UUID principalID, UUID assetID); } } diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index dd3e6ea..0eebc9c 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -85,9 +85,19 @@ namespace OpenSim.Data.MySQL return m_Items.Delete(field, val); } - public bool MoveItem(string principalID, string id, string newParent) + public bool MoveItem(string id, string newParent) { - return m_Items.MoveItem(principalID, id, newParent); + return m_Items.MoveItem(id, newParent); + } + + public XInventoryItem[] GetActiveGestures(UUID principalID) + { + return m_Items.GetActiveGestures(principalID); + } + + public int GetAssetPermissions(UUID principalID, UUID assetID) + { + return m_Items.GetAssetPermissions(principalID, assetID); } } @@ -98,16 +108,49 @@ namespace OpenSim.Data.MySQL { } - public bool MoveItem(string principalID, string id, string newParent) + public bool MoveItem(string id, string newParent) { MySqlCommand cmd = new MySqlCommand(); - cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where agentID = ?AgentID and folderID = ?FolderID"); + cmd.CommandText = String.Format("update {0} set parentFolderID = ?ParentFolderID where inventoryID = ?InventoryID", m_Realm); cmd.Parameters.AddWithValue("?ParentFolderID", newParent); - cmd.Parameters.AddWithValue("?FolderID", id); - cmd.Parameters.AddWithValue("?AgentID", principalID); + cmd.Parameters.AddWithValue("?InventoryID", id); return ExecuteNonQuery(cmd) == 0 ? false : true; } + + public XInventoryItem[] GetActiveGestures(UUID principalID) + { + MySqlCommand cmd = new MySqlCommand(); + cmd.CommandText = String.Format("select * from inventoryitems where avatarId = ?uuid and assetType = ?type and flags = 1", m_Realm); + + cmd.Parameters.AddWithValue("?uuid", principalID.ToString()); + cmd.Parameters.AddWithValue("?type", (int)AssetType.Gesture); + + return DoQuery(cmd); + } + + public int GetAssetPermissions(UUID principalID, UUID assetID) + { + MySqlCommand cmd = new MySqlCommand(); + + cmd.CommandText = String.Format("select bit_or(inventoryCurrentPermissions) as inventoryCurrentPermissions from inventoryitems where avatarID = ?PrincipalID and assetID = ?AssetID group by assetID", m_Realm); + cmd.Parameters.AddWithValue("?PrincipalID", principalID.ToString()); + cmd.Parameters.AddWithValue("?AssetID", assetID.ToString()); + + IDataReader reader = ExecuteReader(cmd); + + int perms = 0; + + if (reader.Read()) + { + perms = Convert.ToInt32(reader["inventoryCurrentPermissions"]); + } + + reader.Close(); + CloseReaderCommand(cmd); + + return perms; + } } } diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 1e7f206..2c79c77 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -183,7 +183,10 @@ namespace OpenSim.Services.InventoryService List folders = new List(); foreach (XInventoryFolder x in allFolders) + { + m_log.DebugFormat("[INVENTORY]: Adding folder {0} to skeleton", x.folderName); folders.Add(ConvertToOpenSim(x)); + } return folders; } @@ -214,35 +217,48 @@ namespace OpenSim.Services.InventoryService public InventoryCollection GetFolderContent(UUID principalID, UUID folderID) { + // This method doesn't receive a valud principal id from the + // connector. So we disregard the principal and look + // by ID. + // + m_log.DebugFormat("[INVENTORY]: Fetch contents for folder {0}", folderID.ToString()); InventoryCollection inventory = new InventoryCollection(); inventory.UserID = principalID; inventory.Folders = new List(); inventory.Items = new List(); XInventoryFolder[] folders = m_Database.GetFolders( - new string[] { "agentID", "parentFolderID"}, - new string[] { principalID.ToString(), UUID.Zero.ToString() }); + new string[] { "parentFolderID"}, + new string[] { folderID.ToString() }); foreach (XInventoryFolder x in folders) + { + m_log.DebugFormat("[INVENTORY]: Adding folder {0} to response", x.folderName); inventory.Folders.Add(ConvertToOpenSim(x)); + } XInventoryItem[] items = m_Database.GetItems( - new string[] { "avatarID", "parentFolderID"}, - new string[] { principalID.ToString(), UUID.Zero.ToString() }); + new string[] { "parentFolderID"}, + new string[] { folderID.ToString() }); foreach (XInventoryItem i in items) + { + m_log.DebugFormat("[INVENTORY]: Adding item {0} to response", i.inventoryName); inventory.Items.Add(ConvertToOpenSim(i)); + } return inventory; } public List GetFolderItems(UUID principalID, UUID folderID) { + // Since we probably don't get a valid principal here, either ... + // List invItems = new List(); XInventoryItem[] items = m_Database.GetItems( - new string[] { "avatarID", "parentFolderID"}, - new string[] { principalID.ToString(), UUID.Zero.ToString() }); + new string[] { "parentFolderID"}, + new string[] { UUID.Zero.ToString() }); foreach (XInventoryItem i in items) invItems.Add(ConvertToOpenSim(i)); @@ -279,6 +295,8 @@ namespace OpenSim.Services.InventoryService // public bool DeleteFolders(UUID principalID, List folderIDs) { + // Ignore principal ID, it's bogus at connector level + // foreach (UUID id in folderIDs) { InventoryFolderBase f = new InventoryFolderBase(); @@ -297,7 +315,10 @@ namespace OpenSim.Services.InventoryService new string[] { folder.ID.ToString() }); foreach (XInventoryFolder x in subFolders) + { PurgeFolder(ConvertToOpenSim(x)); + m_Database.DeleteFolders("folderID", x.folderID.ToString()); + } m_Database.DeleteItems("parentFolderID", folder.ID.ToString()); @@ -316,10 +337,11 @@ namespace OpenSim.Services.InventoryService public bool MoveItems(UUID principalID, List items) { + // Principal is b0rked. *sigh* + // foreach (InventoryItemBase i in items) { - m_Database.MoveItem(principalID.ToString(), i.ID.ToString(), - i.Folder.ToString()); + m_Database.MoveItem(i.ID.ToString(), i.Folder.ToString()); } return true; @@ -327,6 +349,8 @@ namespace OpenSim.Services.InventoryService public bool DeleteItems(UUID principalID, List itemIDs) { + // Just use the ID... *facepalms* + // foreach (UUID id in itemIDs) m_Database.DeleteItems("inventoryID", id.ToString()); @@ -357,14 +381,24 @@ namespace OpenSim.Services.InventoryService return ConvertToOpenSim(folders[0]); } - public List GetActiveGestures(UUID userId) + public List GetActiveGestures(UUID principalID) { - return null; + XInventoryItem[] items = m_Database.GetActiveGestures(principalID); + + if (items.Length == 0) + return null; + + List ret = new List(); + + foreach (XInventoryItem x in items) + ret.Add(ConvertToOpenSim(x)); + + return ret; } - public int GetAssetPermissions(UUID userID, UUID assetID) + public int GetAssetPermissions(UUID principalID, UUID assetID) { - return 0; + return m_Database.GetAssetPermissions(principalID, assetID); } // CM never needed those. Left unimplemented. -- cgit v1.1 From 3724a38ab4694c75288cbf4ba848bd9894b5231d Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 5 Jan 2010 15:39:53 +0000 Subject: Allow estate managers (if estate_owner_is_god is set) to actually enter god mode. Allow god modification of objects if the object owner is the same god that wants to modify, this allows you to regain perms on your own objects after IAR import messed them up. --- OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index e837e9a..f66f01f 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -596,7 +596,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return objectOwnerMask; // Estate users should be able to edit anything in the sim - if (IsEstateManager(user) && m_RegionOwnerIsGod && !IsAdministrator(objectOwner)) + if (IsEstateManager(user) && m_RegionOwnerIsGod && (!IsAdministrator(objectOwner)) || objectOwner == user) return objectOwnerMask; // Admin should be able to edit anything in the sim (including admin objects) @@ -888,6 +888,9 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; + if (IsEstateManager(user) && m_RegionOwnerIsGod) + return true; + return IsAdministrator(user); } -- cgit v1.1 From 71adb37fa87f0ad8fa42c8156529bf72814fde58 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 7 Jan 2010 23:58:19 -0500 Subject: Fix llRotBetween --- .../Shared/Api/Implementation/LSL_Api.cs | 56 +++++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 76c79da..1469e7e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -722,6 +722,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { //A and B should both be normalized m_host.AddScriptLPS(1); + /* This method is more accurate than the SL one, and thus causes problems + for scripts that deal with the SL inaccuracy around 180-degrees -.- .._. + double dotProduct = LSL_Vector.Dot(a, b); LSL_Vector crossProduct = LSL_Vector.Cross(a, b); double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b); @@ -738,8 +741,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); return new LSL_Rotation((float)x, (float)y, (float)z, (float)w); - } - + */ + + // This method mimics the 180 errors found in SL + // See www.euclideanspace.com... angleBetween + LSL_Vector vec_a = a; + LSL_Vector vec_b = b; + + // Eliminate zero length + LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a); + LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b); + if (vec_a_mag < 0.00001 || + vec_b_mag < 0.00001) + { + return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + + // Normalize + vec_a = llVecNorm(vec_a); + vec_b = llVecNorm(vec_b); + + // Calculate axis and rotation angle + LSL_Vector axis = vec_a % vec_b; + LSL_Float cos_theta = vec_a * vec_b; + + // Check if parallel + if (cos_theta > 0.99999) + { + return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + + // Check if anti-parallel + else if (cos_theta < -0.99999) + { + LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a); + if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0); + return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0); + } + else // other rotation + { + LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f; + axis = llVecNorm(axis); + double x, y, z, s, t; + s = Math.Cos(theta); + t = Math.Sin(theta); + x = axis.x * t; + y = axis.y * t; + z = axis.z * t; + return new LSL_Rotation(x,y,z,s); + } + } + public void llWhisper(int channelID, string text) { m_host.AddScriptLPS(1); -- cgit v1.1 From a2aadb78a919323d62a5b4a44c0899b63641788b Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Fri, 8 Jan 2010 23:12:11 -0500 Subject: Maintain control() event stream --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index afd5f86..0eed284 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -4792,6 +4792,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP (x.CameraLeftAxis != lastarg.CameraLeftAxis) || (x.CameraUpAxis != lastarg.CameraUpAxis) || (x.ControlFlags != lastarg.ControlFlags) || + (x.ControlFlags != 0) || (x.Far != lastarg.Far) || (x.Flags != lastarg.Flags) || (x.State != lastarg.State) || -- cgit v1.1 From a87d7a12967b50fe83ebbaa7b57e531eb93158a2 Mon Sep 17 00:00:00 2001 From: Careminster Staff Date: Wed, 13 Jan 2010 22:45:17 -0600 Subject: Adds Land Banning. --- .../CoreModules/World/Land/LandManagementModule.cs | 130 +++++++++++++-------- .../Region/CoreModules/World/Land/LandObject.cs | 48 ++++++-- 2 files changed, 120 insertions(+), 58 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 9b39b09..d9b36a5 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -264,20 +264,57 @@ namespace OpenSim.Region.CoreModules.World.Land return parcelsNear; } - public void SendYouAreBannedNotice(ScenePresence avatar) + public void KickUserOffOfParcel(ScenePresence avatar) { - if (AllowedForcefulBans) + if (avatar.GodLevel == 0) { - avatar.ControllingClient.SendAlertMessage( - "You are not allowed on this parcel because you are banned. Please go away."); - - avatar.PhysicsActor.Position = avatar.lastKnownAllowedPosition; - avatar.PhysicsActor.Velocity = Vector3.Zero; + List parcelsNear = ParcelsNearPoint(avatar.AbsolutePosition); + foreach (ILandObject check in parcelsNear) + { + if (check.IsEitherBannedOrRestricted(avatar.UUID) != true) + { + Vector3 target = check.LandData.UserLocation; + avatar.TeleportWithMomentum(target); + return; + } + } } - else + } + public void MoveUserOutOfParcel(ScenePresence avatar) + { + if (avatar.GodLevel == 0) { - avatar.ControllingClient.SendAlertMessage( - "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim!"); + ILandObject land = m_scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + List parcelsNear = new List(); + + for (int x = -2; x <= 2; x += 2) + { + ILandObject check = GetLandObject(avatar.AbsolutePosition.X + x, avatar.AbsolutePosition.Y); + if (check != null) + { + if (check.IsEitherBannedOrRestricted(avatar.UUID) != true) + { + Vector3 target = new Vector3(avatar.AbsolutePosition.X + x, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); + avatar.TeleportWithMomentum(target); + avatar.Velocity = new Vector3(-avatar.Velocity.X - 5, avatar.Velocity.Y, avatar.Velocity.Z); + return; + } + } + } + for (int y = -2; y <= 2; y += 2) + { + ILandObject check = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y + y); + if (check != null) + { + if (check.IsEitherBannedOrRestricted(avatar.UUID) != true) + { + Vector3 target = new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y + y, avatar.AbsolutePosition.Z); + avatar.TeleportWithMomentum(target); + avatar.Velocity = new Vector3(avatar.Velocity.X, -avatar.Velocity.Y - 5, avatar.Velocity.Z); + return; + } + } + } } } @@ -297,16 +334,7 @@ namespace OpenSim.Region.CoreModules.World.Land { if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID)) { - SendYouAreBannedNotice(avatar); - } - else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID)) - { - avatar.ControllingClient.SendAlertMessage( - "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!)."); - } - else - { - avatar.sentMessageAboutRestrictedParcelFlyingDown = true; + MoveUserOutOfParcel(avatar); } } else @@ -317,28 +345,47 @@ namespace OpenSim.Region.CoreModules.World.Land } } - public void SendOutNearestBanLine(IClientAPI avatar) + public void SendOutNearestBanLine(ScenePresence avatar) { - List avatars = m_scene.GetAvatars(); - foreach (ScenePresence presence in avatars) + ILandObject checkBan = null; + for (int x = -2; x <= 2; x += 2) { - if (presence.UUID == avatar.AgentId) + checkBan = GetLandObject(avatar.AbsolutePosition.X + x, avatar.AbsolutePosition.Y); + if (checkBan != null) { - List checkLandParcels = ParcelsNearPoint(presence.AbsolutePosition); - foreach (ILandObject checkBan in checkLandParcels) + if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) { - if (checkBan.IsBannedFromLand(avatar.AgentId)) + if (checkBan.IsRestrictedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar); - return; //Only send one + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar.ControllingClient); + return; } - if (checkBan.IsRestrictedFromLand(avatar.AgentId)) + if (checkBan.IsBannedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar); - return; //Only send one + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar.ControllingClient); + return; + } + } + } + } + for (int y = -2; y <= 2; y += 2) + { + checkBan = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y + y); + if (checkBan != null) + { + if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) + { + if (checkBan.IsRestrictedFromLand(avatar.ControllingClient.AgentId)) + { + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar.ControllingClient); + return; + } + if (checkBan.IsBannedFromLand(avatar.ControllingClient.AgentId)) + { + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar.ControllingClient); + return; } } - return; } } } @@ -385,25 +432,14 @@ namespace OpenSim.Region.CoreModules.World.Land if (clientAvatar != null) { SendLandUpdate(clientAvatar); - SendOutNearestBanLine(remote_client); + SendOutNearestBanLine(clientAvatar); ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y); if (parcel != null) { if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && - clientAvatar.sentMessageAboutRestrictedParcelFlyingDown) - { - EventManagerOnAvatarEnteringNewParcel(clientAvatar, parcel.LandData.LocalID, - m_scene.RegionInfo.RegionID); - //They are going under the safety line! - if (!parcel.IsBannedFromLand(clientAvatar.UUID)) - { - clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false; - } - } - else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && parcel.IsBannedFromLand(clientAvatar.UUID)) { - SendYouAreBannedNotice(clientAvatar); + MoveUserOutOfParcel(clientAvatar); } } } @@ -451,7 +487,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (land != null) { - if (agentID == land.LandData.OwnerID) + if (m_scene.Permissions.CanEditParcel(agentID, land)) { land.UpdateAccessList(flags, entries, remote_client); } diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 1fa8630..1c65965 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -267,11 +267,7 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsEitherBannedOrRestricted(UUID avatar) { - if (IsBannedFromLand(avatar)) - { - return true; - } - else if (IsRestrictedFromLand(avatar)) + if (IsRestrictedFromLand(avatar) || IsBannedFromLand(avatar)) { return true; } @@ -280,7 +276,8 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsBannedFromLand(UUID avatar) { - if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) + ScenePresence SP = m_scene.GetScenePresence(avatar); + if ((LandData.Flags & (uint)ParcelFlags.UseBanList) > 0) { ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); entry.AgentID = avatar; @@ -288,8 +285,22 @@ namespace OpenSim.Region.CoreModules.World.Land entry.Time = new DateTime(); if (LandData.ParcelAccessList.Contains(entry)) { - //They are banned, so lets send them a notice about this parcel - return true; + if ((LandData.Flags & (uint)ParcelFlags.UseAccessGroup) > 0) + { + if (LandData.GroupID == SP.ControllingClient.ActiveGroupId) + { + return false; + } + else + { + //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel + return true; + } + } + else + { + return true; + } } } return false; @@ -297,7 +308,8 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsRestrictedFromLand(UUID avatar) { - if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) + ScenePresence SP = m_scene.GetScenePresence(avatar); + if ((LandData.Flags & (uint)ParcelFlags.UseAccessList) > 0) { ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); entry.AgentID = avatar; @@ -305,8 +317,22 @@ namespace OpenSim.Region.CoreModules.World.Land entry.Time = new DateTime(); if (!LandData.ParcelAccessList.Contains(entry)) { - //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel - return true; + if ((LandData.Flags & (uint)ParcelFlags.UseAccessGroup) > 0) + { + if (LandData.GroupID == SP.ControllingClient.ActiveGroupId) + { + return false; + } + else + { + //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel + return true; + } + } + else + { + return true; + } } } return false; -- cgit v1.1 From 884410501e50f0abb09ef1339ac74e22c2dfd39f Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 15 Jan 2010 20:19:06 +0000 Subject: Allow renaming of items that contain no-mod items --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 18ec25f..dd4c14b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1803,8 +1803,13 @@ namespace OpenSim.Region.Framework.Scenes } else { - item.BasePermissions = objectGroup.GetEffectivePermissions(); - item.CurrentPermissions = objectGroup.GetEffectivePermissions(); + uint ownerPerms = objectGroup.GetEffectivePermissions(); + if ((objectGroup.RootPart.OwnerMask & (uint)PermissionMask.Modify) != 0) + ownerPerms |= (uint)PermissionMask.Modify; + + item.BasePermissions = ownerPerms; + item.CurrentPermissions = ownerPerms; + item.NextPermissions = objectGroup.RootPart.NextOwnerMask; item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask; item.GroupPermissions = objectGroup.RootPart.GroupMask; -- cgit v1.1 From 44d523518af31075c77653eacc7489220db4abaa Mon Sep 17 00:00:00 2001 From: Careminster Staff Date: Sun, 17 Jan 2010 19:23:36 -0600 Subject: Adds land ejection and freezing. Adds more checks to land banning. --- .../CoreModules/World/Land/LandManagementModule.cs | 442 +++++++++++++++++++-- 1 file changed, 419 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index d9b36a5..23da1ae 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -81,6 +81,8 @@ namespace OpenSim.Region.CoreModules.World.Land private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; private bool m_allowedForcefulBans = true; + private string DefultGodParcelGroup; + private string DefultGodParcelName; // caches ExtendedLandData private Cache parcelInfoCache; @@ -153,6 +155,10 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelInfoRequest += ClientOnParcelInfoRequest; client.OnParcelDwellRequest += ClientOnParcelDwellRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; + client.OnParcelGodMark += ClientOnParcelGodMark; + client.OnSimWideDeletes += ClientOnSimWideDeletes; + client.OnParcelFreezeUser += ClientOnParcelFreezeUser; + client.OnParcelEjectUser += ClientOnParcelEjectUser; EntityBase presenceEntity; if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) @@ -264,22 +270,7 @@ namespace OpenSim.Region.CoreModules.World.Land return parcelsNear; } - public void KickUserOffOfParcel(ScenePresence avatar) - { - if (avatar.GodLevel == 0) - { - List parcelsNear = ParcelsNearPoint(avatar.AbsolutePosition); - foreach (ILandObject check in parcelsNear) - { - if (check.IsEitherBannedOrRestricted(avatar.UUID) != true) - { - Vector3 target = check.LandData.UserLocation; - avatar.TeleportWithMomentum(target); - return; - } - } - } - } + public void MoveUserOutOfParcel(ScenePresence avatar) { if (avatar.GodLevel == 0) @@ -296,7 +287,6 @@ namespace OpenSim.Region.CoreModules.World.Land { Vector3 target = new Vector3(avatar.AbsolutePosition.X + x, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); avatar.TeleportWithMomentum(target); - avatar.Velocity = new Vector3(-avatar.Velocity.X - 5, avatar.Velocity.Y, avatar.Velocity.Z); return; } } @@ -310,11 +300,73 @@ namespace OpenSim.Region.CoreModules.World.Land { Vector3 target = new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y + y, avatar.AbsolutePosition.Z); avatar.TeleportWithMomentum(target); - avatar.Velocity = new Vector3(avatar.Velocity.X, -avatar.Velocity.Y - 5, avatar.Velocity.Z); return; } } } + List allParcels = new List(); + allParcels = AllParcels(); + if (allParcels.Count != 1) + { + foreach (ILandObject parcel in allParcels) + { + if (parcel.IsEitherBannedOrRestricted(avatar.UUID) != true) + { + Vector3 temptarget = parcel.LandData.UserLocation; + if (parcel.ContainsPoint((int)parcel.LandData.UserLocation.X, (int)parcel.LandData.UserLocation.Y)) + { + avatar.TeleportWithMomentum(temptarget); + return; + } + else + { + for (int x = 0; x <= Constants.RegionSize / 3; x += 3) + { + for (int y = 0; y <= Constants.RegionSize / 3; y += 3) + { + if (parcel.ContainsPoint(x, y)) + { + temptarget = new Vector3(x, y, avatar.AbsolutePosition.Z); + avatar.TeleportWithMomentum(temptarget); + return; + } + } + } + } + } + } + } + //Move to region side + if (avatar.AbsolutePosition.X > avatar.AbsolutePosition.Y) + { + if (avatar.AbsolutePosition.X > .5 * Constants.RegionSize) + { + Vector3 target = new Vector3(Constants.RegionSize, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); ; + avatar.TeleportWithMomentum(target); + return; + } + else + { + Vector3 target = new Vector3(0, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); ; + avatar.TeleportWithMomentum(target); + return; + } + } + else + { + if (avatar.AbsolutePosition.Y > .5 * Constants.RegionSize) + { + Vector3 target = new Vector3(avatar.AbsolutePosition.X, Constants.RegionSize, avatar.AbsolutePosition.Z); ; + avatar.TeleportWithMomentum(target); + return; + } + else + { + Vector3 target = new Vector3(avatar.AbsolutePosition.X, 0, avatar.AbsolutePosition.Z); ; + avatar.TeleportWithMomentum(target); + return; + } + } } } @@ -357,12 +409,12 @@ namespace OpenSim.Region.CoreModules.World.Land { if (checkBan.IsRestrictedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar.ControllingClient); + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, true, (int)ParcelResult.Multiple, avatar.ControllingClient); return; } if (checkBan.IsBannedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar.ControllingClient); + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, true, (int)ParcelResult.Multiple, avatar.ControllingClient); return; } } @@ -377,12 +429,12 @@ namespace OpenSim.Region.CoreModules.World.Land { if (checkBan.IsRestrictedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar.ControllingClient); + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, true, (int)ParcelResult.Multiple, avatar.ControllingClient); return; } if (checkBan.IsBannedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar.ControllingClient); + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, true, (int)ParcelResult.Multiple, avatar.ControllingClient); return; } } @@ -490,6 +542,18 @@ namespace OpenSim.Region.CoreModules.World.Land if (m_scene.Permissions.CanEditParcel(agentID, land)) { land.UpdateAccessList(flags, entries, remote_client); + List presences = ((Scene)remote_client.Scene).GetAvatars(); + foreach (ScenePresence presence in presences) + { + land = GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); + if (land != null) + { + if (land.IsEitherBannedOrRestricted(presence.UUID)) + { + MoveUserOutOfParcel(presence); + } + } + } } } else @@ -1055,7 +1119,25 @@ namespace OpenSim.Region.CoreModules.World.Land m_landList.TryGetValue(localID, out land); } - if (land != null) land.UpdateLandProperties(args, remote_client); + if (land != null) + { + land.UpdateLandProperties(args, remote_client); + if ((args.ParcelFlags & (uint)(ParcelFlags.UseBanList | ParcelFlags.UseAccessList | ParcelFlags.UseAccessGroup | ParcelFlags.UsePassList)) != 0) + { + List presences = ((Scene)remote_client.Scene).GetAvatars(); + foreach (ScenePresence presence in presences) + { + land = GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); + if (land != null) + { + if (land.IsEitherBannedOrRestricted(presence.UUID)) + { + MoveUserOutOfParcel(presence); + } + } + } + } + } } public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) @@ -1473,5 +1555,319 @@ namespace OpenSim.Region.CoreModules.World.Land UpdateLandObject(localID, land.LandData); } + public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID) + { + ILandObject land = null; + List Land = ((Scene)client.Scene).LandChannel.AllParcels(); + foreach (ILandObject landObject in Land) + { + if (landObject.LandData.LocalID == landID) + { + land = landObject; + } + } + land.DeedToGroup(new UUID(DefultGodParcelGroup)); + land.LandData.Name = DefultGodParcelName; + land.SendLandUpdateToAvatarsOverMe(); + } + private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID) + { + ScenePresence SP; + ((Scene)client.Scene).TryGetAvatar(client.AgentId, out SP); + List returns = new List(); + if (SP.GodLevel != 0) + { + if (flags == 0) //All parcels, scripted or not + { + ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e) + { + if (e.OwnerID == targetID) + { + returns.Add(e); + } + } + ); + } + if (flags == 4) //All parcels, scripted object + { + ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e) + { + if (e.OwnerID == targetID) + { + if (e.scriptScore >= 0.01) + { + returns.Add(e); + } + } + } + ); + } + if (flags == 4) //not target parcel, scripted object + { + ((Scene)client.Scene).ForEachSOG(delegate(SceneObjectGroup e) + { + if (e.OwnerID == targetID) + { + ILandObject landobject = ((Scene)client.Scene).LandChannel.GetLandObject(e.AbsolutePosition.X, e.AbsolutePosition.Y); + if (landobject.LandData.OwnerID != e.OwnerID) + { + if (e.scriptScore >= 0.01) + { + returns.Add(e); + } + } + } + } + ); + } + foreach (SceneObjectGroup ol in returns) + { + ReturnObject(ol, client); + } + } + } + public void ReturnObject(SceneObjectGroup obj, IClientAPI client) + { + SceneObjectGroup[] objs = new SceneObjectGroup[1]; + objs[0] = obj; + ((Scene)client.Scene).returnObjects(objs, client.AgentId); + } + + Dictionary Timers = new Dictionary(); + + public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) + { + ScenePresence targetAvatar = null; + ((Scene)client.Scene).TryGetAvatar(target, out targetAvatar); + ScenePresence parcelManager = null; + ((Scene)client.Scene).TryGetAvatar(client.AgentId, out parcelManager); + System.Threading.Timer Timer; + + if (targetAvatar.GodLevel == 0) + { + ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); + if (!((Scene)client.Scene).Permissions.CanEditParcel(client.AgentId, land)) + return; + if (flags == 0) + { + targetAvatar.AllowMovement = false; + targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has frozen you for 30 seconds. You cannot move or interact with the world."); + parcelManager.ControllingClient.SendAlertMessage("Avatar Frozen."); + System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen); + Timer = new System.Threading.Timer(timeCB, targetAvatar, 30000, 0); + Timers.Add(targetAvatar.UUID, Timer); + } + else + { + targetAvatar.AllowMovement = true; + targetAvatar.ControllingClient.SendAlertMessage(parcelManager.Firstname + " " + parcelManager.Lastname + " has unfrozen you."); + parcelManager.ControllingClient.SendAlertMessage("Avatar Unfrozen."); + Timers.TryGetValue(targetAvatar.UUID, out Timer); + Timers.Remove(targetAvatar.UUID); + Timer.Dispose(); + } + } + } + private void OnEndParcelFrozen(object avatar) + { + ScenePresence targetAvatar = (ScenePresence)avatar; + targetAvatar.AllowMovement = true; + System.Threading.Timer Timer; + Timers.TryGetValue(targetAvatar.UUID, out Timer); + Timers.Remove(targetAvatar.UUID); + targetAvatar.ControllingClient.SendAgentAlertMessage("The freeze has worn off; you may go about your business.", false); + } + + + public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) + { + ScenePresence targetAvatar = null; + ((Scene)client.Scene).TryGetAvatar(target, out targetAvatar); + ScenePresence parcelManager = null; + ((Scene)client.Scene).TryGetAvatar(client.AgentId, out parcelManager); + //Just eject + if (flags == 0) + { + if (targetAvatar.GodLevel == 0) + { + ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); + if (!((Scene)client.Scene).Permissions.CanEditParcel(client.AgentId, land)) + return; + + Vector3 position = new Vector3(0, 0, 0); + List allParcels = new List(); + allParcels = AllParcels(); + if (allParcels.Count != 1) + { + foreach (ILandObject parcel in allParcels) + { + if (parcel.LandData.GlobalID != land.LandData.GlobalID) + { + if (parcel.IsEitherBannedOrRestricted(targetAvatar.UUID) != true) + { + for (int x = 1; x <= Constants.RegionSize; x += 2) + { + for (int y = 1; y <= Constants.RegionSize; y += 2) + { + if (parcel.ContainsPoint(x, y)) + { + position = new Vector3(x, y, targetAvatar.AbsolutePosition.Z); + targetAvatar.TeleportWithMomentum(position); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); + return; + } + } + } + } + } + } + } + Vector3 targetVector; + if (targetAvatar.AbsolutePosition.X > targetAvatar.AbsolutePosition.Y) + { + if (targetAvatar.AbsolutePosition.X > .5 * Constants.RegionSize) + { + targetVector = new Vector3(Constants.RegionSize, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ; + targetAvatar.TeleportWithMomentum(targetVector); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); + return; + } + else + { + targetVector = new Vector3(0, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ; + targetAvatar.TeleportWithMomentum(targetVector); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); + return; + } + } + else + { + if (targetAvatar.AbsolutePosition.Y > .5 * Constants.RegionSize) + { + targetVector = new Vector3(targetAvatar.AbsolutePosition.X, Constants.RegionSize, targetAvatar.AbsolutePosition.Z); ; + targetAvatar.TeleportWithMomentum(targetVector); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); + return; + } + else + { + targetVector = new Vector3(targetAvatar.AbsolutePosition.X, 0, targetAvatar.AbsolutePosition.Z); ; + targetAvatar.TeleportWithMomentum(targetVector); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected."); + return; + } + } + } + } + //Eject and ban + if (flags == 1) + { + if (targetAvatar.GodLevel == 0) + { + ILandObject land = ((Scene)client.Scene).LandChannel.GetLandObject(targetAvatar.AbsolutePosition.X, targetAvatar.AbsolutePosition.Y); + if (!((Scene)client.Scene).Permissions.CanEditParcel(client.AgentId, land)) + return; + + Vector3 position = new Vector3(0, 0, 0); + List allParcels = new List(); + allParcels = AllParcels(); + if (allParcels.Count != 1) + { + foreach (ILandObject parcel in allParcels) + { + if (parcel.LandData.GlobalID != land.LandData.GlobalID) + { + if (parcel.IsEitherBannedOrRestricted(targetAvatar.UUID) != true) + { + for (int x = 1; x <= Constants.RegionSize; x += 2) + { + for (int y = 1; y <= Constants.RegionSize; y += 2) + { + if (parcel.ContainsPoint(x, y)) + { + position = new Vector3(x, y, targetAvatar.AbsolutePosition.Z); + targetAvatar.TeleportWithMomentum(position); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned."); + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = targetAvatar.UUID; + entry.Flags = AccessList.Ban; + entry.Time = new DateTime(); + land.LandData.ParcelAccessList.Add(entry); + return; + } + } + } + } + } + } + } + Vector3 targetVector; + if (targetAvatar.AbsolutePosition.X > targetAvatar.AbsolutePosition.Y) + { + if (targetAvatar.AbsolutePosition.X > .5 * Constants.RegionSize) + { + targetVector = new Vector3(Constants.RegionSize, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ; + targetAvatar.TeleportWithMomentum(targetVector); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned."); + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = targetAvatar.UUID; + entry.Flags = AccessList.Ban; + entry.Time = new DateTime(); + land.LandData.ParcelAccessList.Add(entry); + return; + } + else + { + targetVector = new Vector3(0, targetAvatar.AbsolutePosition.Y, targetAvatar.AbsolutePosition.Z); ; + targetAvatar.TeleportWithMomentum(targetVector); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned."); + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = targetAvatar.UUID; + entry.Flags = AccessList.Ban; + entry.Time = new DateTime(); + land.LandData.ParcelAccessList.Add(entry); + return; + } + } + else + { + if (targetAvatar.AbsolutePosition.Y > .5 * Constants.RegionSize) + { + targetVector = new Vector3(targetAvatar.AbsolutePosition.X, Constants.RegionSize, targetAvatar.AbsolutePosition.Z); ; + targetAvatar.TeleportWithMomentum(targetVector); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned."); + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = targetAvatar.UUID; + entry.Flags = AccessList.Ban; + entry.Time = new DateTime(); + land.LandData.ParcelAccessList.Add(entry); + return; + } + else + { + targetVector = new Vector3(targetAvatar.AbsolutePosition.X, 0, targetAvatar.AbsolutePosition.Z); ; + targetAvatar.TeleportWithMomentum(targetVector); + targetAvatar.ControllingClient.SendAlertMessage("You have been ejected and banned by " + parcelManager.Firstname + " " + parcelManager.Lastname); + parcelManager.ControllingClient.SendAlertMessage("Avatar Ejected and Banned."); + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = targetAvatar.UUID; + entry.Flags = AccessList.Ban; + entry.Time = new DateTime(); + land.LandData.ParcelAccessList.Add(entry); + return; + } + } + } + } + } } } -- cgit v1.1 From f4e30664e6b327257db196512f0b6e304399214b Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 18 Jan 2010 01:55:45 +0000 Subject: Fix a typo --- OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 23da1ae..6a0e8d1 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -81,8 +81,8 @@ namespace OpenSim.Region.CoreModules.World.Land private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; private bool m_allowedForcefulBans = true; - private string DefultGodParcelGroup; - private string DefultGodParcelName; + private string DefaultGodParcelGroup; + private string DefaultGodParcelName; // caches ExtendedLandData private Cache parcelInfoCache; @@ -1566,8 +1566,8 @@ namespace OpenSim.Region.CoreModules.World.Land land = landObject; } } - land.DeedToGroup(new UUID(DefultGodParcelGroup)); - land.LandData.Name = DefultGodParcelName; + land.DeedToGroup(new UUID(DefaultGodParcelGroup)); + land.LandData.Name = DefaultGodParcelName; land.SendLandUpdateToAvatarsOverMe(); } private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID) -- cgit v1.1 From 51bb31156502c391ac84aa207fce125a4299d755 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 18 Jan 2010 02:53:31 +0000 Subject: Add chat banning. Staff patch --- .../Region/CoreModules/Avatar/Chat/ChatModule.cs | 51 +++++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index e3e8718..acc3a78 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -49,6 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat private int m_shoutdistance = 100; private int m_whisperdistance = 10; private List m_scenes = new List(); + private List FreezeCache = new List(); private string m_adminPrefix = ""; internal object m_syncy = new object(); @@ -172,7 +173,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat return; } - DeliverChatToAvatars(ChatSourceType.Agent, c); + if (FreezeCache.Contains(c.Sender.AgentId.ToString())) + { + if (c.Type != ChatTypeEnum.StartTyping || c.Type != ChatTypeEnum.StopTyping) + c.Sender.SendAgentAlertMessage("You may not talk as you are frozen.", false); + } + else + { + DeliverChatToAvatars(ChatSourceType.Agent, c); + } } public virtual void OnChatFromWorld(Object sender, OSChatMessage c) @@ -232,7 +241,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat s.ForEachScenePresence( delegate(ScenePresence presence) { - TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix+fromName, c.Type, message, sourceType); + ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); + if (Presencecheck != null) + { + if (Presencecheck.IsEitherBannedOrRestricted(c.SenderUUID) != true) + { + TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix+fromName, c.Type, message, sourceType); + } + } + } ); } @@ -322,5 +339,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, fromAgentID,(byte)src,(byte)ChatAudibleLevel.Fully); } + + Dictionary Timers = new Dictionary(); + public void ParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) + { + System.Threading.Timer Timer; + if (flags == 0) + { + FreezeCache.Add(target.ToString()); + System.Threading.TimerCallback timeCB = new System.Threading.TimerCallback(OnEndParcelFrozen); + Timer = new System.Threading.Timer(timeCB, target, 30000, 0); + Timers.Add(target, Timer); + } + else + { + FreezeCache.Remove(target.ToString()); + Timers.TryGetValue(target, out Timer); + Timers.Remove(target); + Timer.Dispose(); + } + } + + private void OnEndParcelFrozen(object avatar) + { + UUID target = (UUID)avatar; + FreezeCache.Remove(target.ToString()); + System.Threading.Timer Timer; + Timers.TryGetValue(target, out Timer); + Timers.Remove(target); + Timer.Dispose(); + } } } -- cgit v1.1 From d9c48e70a9a01f56135ede2cef9ec45c7dddf567 Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 18 Jan 2010 17:56:27 +0100 Subject: Fix a major security problem with osSetDynamicTexture which allowed the deletion of /any/ asset. --- .../Scripting/DynamicTexture/DynamicTextureModule.cs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index f51d0c2..679c871 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -358,11 +358,18 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture // tmptex.DefaultTexture.Fullbright = true; part.UpdateTexture(tmptex); - } - - if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) - { - scene.AssetService.Delete(oldID.ToString()); + } + + if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) + { + if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); + if (oldAsset != null) + { + if (oldAsset.Temporary == true) + { + scene.AssetService.Delete(oldID.ToString()); + } + } } } -- cgit v1.1 From 6772c9d2b6d05c985174f514aa8df2aacd33a201 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 18 Jan 2010 17:35:49 +0000 Subject: Comment the asset deletion handler. It can be abused and is not currently needed. --- OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs index 3f33da6..f33bb90 100644 --- a/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs +++ b/OpenSim/Server/Handlers/Asset/AssetServerDeleteHandler.cs @@ -63,7 +63,7 @@ namespace OpenSim.Server.Handlers.Asset if (p.Length > 0) { - result = m_AssetService.Delete(p[0]); + // result = m_AssetService.Delete(p[0]); } XmlSerializer xs = new XmlSerializer(typeof(bool)); -- cgit v1.1 From 24056dc98ba94b32ac98cc0a3b1b85d5f8ef3de6 Mon Sep 17 00:00:00 2001 From: Careminster Staff Date: Mon, 18 Jan 2010 16:23:13 -0600 Subject: Adds example to OpenSim.ini.example for Admin Default Parcel settings --- OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | 10 ++++++++-- bin/OpenSim.ini.example | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 6a0e8d1..28669b9 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -81,7 +81,7 @@ namespace OpenSim.Region.CoreModules.World.Land private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; private bool m_allowedForcefulBans = true; - private string DefaultGodParcelGroup; + private UUID DefaultGodParcelGroup; private string DefaultGodParcelName; // caches ExtendedLandData @@ -96,6 +96,12 @@ namespace OpenSim.Region.CoreModules.World.Land public void Initialise(IConfigSource source) { + IConfig cnf = source.Configs["LandManagement"]; + if (cnf == null) + { + DefaultGodParcelGroup = new UUID(cnf.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString())); + DefaultGodParcelName = cnf.GetString("DefaultAdministratorParcelName", "Default Parcel"); + } } public void AddRegion(Scene scene) @@ -1566,7 +1572,7 @@ namespace OpenSim.Region.CoreModules.World.Land land = landObject; } } - land.DeedToGroup(new UUID(DefaultGodParcelGroup)); + land.DeedToGroup(DefaultGodParcelGroup); land.LandData.Name = DefaultGodParcelName; land.SendLandUpdateToAvatarsOverMe(); } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index c96e938..23004a4 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -1351,6 +1351,9 @@ ; For example- http://127.0.0.1:9000/SStats/ ; enabled=false +[LandManagement] +; DefaultAdministratorGroupUUID = ""; +; DefaultAdministratorParcelName = ""; ;; ;; These are defaults that are overwritten below in [Architecture]. -- cgit v1.1 From 496a8a4f7ca5422daa30913595b6b1a03fa8a59a Mon Sep 17 00:00:00 2001 From: CasperW Date: Wed, 20 Jan 2010 22:14:43 +0100 Subject: Fixed an issue with PayPrice sometimes being shared between multiple objects --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a7c14cf..4c97467 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -109,7 +109,7 @@ namespace OpenSim.Region.Framework.Scenes // TODO: This needs to be persisted in next XML version update! [XmlIgnore] - public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; + public int[] PayPrice = {-2,-2,-2,-2,-2}; [XmlIgnore] public PhysicsActor PhysActor; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 085d61f..a5aecd8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8946,12 +8946,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSLError("List must have at least 4 elements"); return; } - m_host.ParentGroup.RootPart.PayPrice[0]=price; - - m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; - m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; - m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; - m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; + int[] nPrice = new int[5]; + nPrice[0]=price; + nPrice[1] = (LSL_Integer)quick_pay_buttons.Data[0]; + nPrice[2] = (LSL_Integer)quick_pay_buttons.Data[1]; + nPrice[3] = (LSL_Integer)quick_pay_buttons.Data[2]; + nPrice[4] = (LSL_Integer)quick_pay_buttons.Data[3]; + m_host.ParentGroup.RootPart.PayPrice = nPrice; m_host.ParentGroup.HasGroupChanged = true; } -- cgit v1.1 From 66692f90e3b70ccdec8c148342578cd54acc4406 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 21 Jan 2010 14:39:11 -0500 Subject: ChODE Object Linear Motion update --- OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs | 187 ++++++++++++---------- OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs | 2 +- 2 files changed, 102 insertions(+), 87 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs index ef2dccc..9e145ec 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs @@ -82,13 +82,6 @@ namespace OpenSim.Region.Physics.OdePlugin private IntPtr m_body = IntPtr.Zero; // private IntPtr m_jointGroup = IntPtr.Zero; // private IntPtr m_aMotor = IntPtr.Zero; - - // Correction factors, to match Sl - private static float m_linearVelocityFactor = 0.9f; - private static float m_linearAttackFactor = 0.4f; - private static float m_linearDecayFactor = 0.5f; - private static float m_linearFrictionFactor = 1.2f; - // Vehicle properties private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind @@ -103,15 +96,15 @@ namespace OpenSim.Region.Physics.OdePlugin // LIMIT_ROLL_ONLY // Linear properties - private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time - private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL, for max limiting - private Vector3 m_dir = Vector3.Zero; // velocity applied to body - private Vector3 m_linearFrictionTimescale = Vector3.Zero; - private float m_linearMotorDecayTimescale = 0; - private float m_linearMotorTimescale = 0; - private Vector3 m_lastLinearVelocityVector = Vector3.Zero; - // private bool m_LinearMotorSetLastFrame = false; - // private Vector3 m_linearMotorOffset = Vector3.Zero; + private Vector3 m_linearMotorDirection = Vector3.Zero; // (was m_linearMotorDirectionLASTSET) the (local) Velocity + //requested by LSL + private float m_linearMotorTimescale = 0; // Motor Attack rate set by LSL + private float m_linearMotorDecayTimescale = 0; // Motor Decay rate set by LSL + private Vector3 m_linearFrictionTimescale = Vector3.Zero; // General Friction set by LSL + + private Vector3 m_lLinMotorDVel = Vector3.Zero; // decayed motor + private Vector3 m_lLinObjectVel = Vector3.Zero; // local frame object velocity + private Vector3 m_wLinObjectVel = Vector3.Zero; // world frame object velocity //Angular properties private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor @@ -241,7 +234,7 @@ namespace OpenSim.Region.Physics.OdePlugin break; case Vehicle.LINEAR_MOTOR_DIRECTION: m_linearMotorDirection = new Vector3(pValue, pValue, pValue); - m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); + UpdateLinDecay(); break; case Vehicle.LINEAR_MOTOR_OFFSET: // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); @@ -273,9 +266,8 @@ namespace OpenSim.Region.Physics.OdePlugin m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.LINEAR_MOTOR_DIRECTION: - pValue *= m_linearVelocityFactor; - m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, decayed by time - m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, for max limiting + m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, for max limiting + UpdateLinDecay(); break; case Vehicle.LINEAR_MOTOR_OFFSET: // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -304,7 +296,7 @@ namespace OpenSim.Region.Physics.OdePlugin case Vehicle.TYPE_SLED: m_linearFrictionTimescale = new Vector3(30, 1, 1000); m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_linearMotorDirection = Vector3.Zero; +// m_lLinMotorVel = Vector3.Zero; m_linearMotorTimescale = 1000; m_linearMotorDecayTimescale = 120; m_angularMotorDirection = Vector3.Zero; @@ -330,7 +322,7 @@ namespace OpenSim.Region.Physics.OdePlugin case Vehicle.TYPE_CAR: m_linearFrictionTimescale = new Vector3(100, 2, 1000); m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_linearMotorDirection = Vector3.Zero; +// m_lLinMotorVel = Vector3.Zero; m_linearMotorTimescale = 1; m_linearMotorDecayTimescale = 60; m_angularMotorDirection = Vector3.Zero; @@ -357,7 +349,7 @@ namespace OpenSim.Region.Physics.OdePlugin case Vehicle.TYPE_BOAT: m_linearFrictionTimescale = new Vector3(10, 3, 2); m_angularFrictionTimescale = new Vector3(10,10,10); - m_linearMotorDirection = Vector3.Zero; +// m_lLinMotorVel = Vector3.Zero; m_linearMotorTimescale = 5; m_linearMotorDecayTimescale = 60; m_angularMotorDirection = Vector3.Zero; @@ -385,7 +377,7 @@ namespace OpenSim.Region.Physics.OdePlugin case Vehicle.TYPE_AIRPLANE: m_linearFrictionTimescale = new Vector3(200, 10, 5); m_angularFrictionTimescale = new Vector3(20, 20, 20); - m_linearMotorDirection = Vector3.Zero; +// m_lLinMotorVel = Vector3.Zero; m_linearMotorTimescale = 2; m_linearMotorDecayTimescale = 60; m_angularMotorDirection = Vector3.Zero; @@ -412,7 +404,6 @@ namespace OpenSim.Region.Physics.OdePlugin case Vehicle.TYPE_BALLOON: m_linearFrictionTimescale = new Vector3(5, 5, 5); m_angularFrictionTimescale = new Vector3(10, 10, 10); - m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 5; m_linearMotorDecayTimescale = 60; m_angularMotorDirection = Vector3.Zero; @@ -453,7 +444,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) return; frcount++; // used to limit debug comment output - if (frcount > 100) + if (frcount > 24) frcount = 0; MoveLinear(pTimestep, pParentScene); @@ -463,63 +454,90 @@ namespace OpenSim.Region.Physics.OdePlugin internal void Halt() { // Kill all motions, when non-physical m_linearMotorDirection = Vector3.Zero; - m_linearMotorDirectionLASTSET = Vector3.Zero; - m_dir = Vector3.Zero; - m_lastLinearVelocityVector = Vector3.Zero; + m_lLinMotorDVel = Vector3.Zero; + m_lLinObjectVel = Vector3.Zero; + m_wLinObjectVel = Vector3.Zero; m_angularMotorDirection = Vector3.Zero; m_angularMotorVelocity = Vector3.Zero; m_lastAngularVelocity = Vector3.Zero; } + + private void UpdateLinDecay() + { + if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X; + if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y; + if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z; + } // else let the motor decay on its own private void MoveLinear(float pTimestep, OdeScene _pParentScene) { - if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant - { - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + Vector3 acceleration = new Vector3(0f, 0f, 0f); - // add drive to body - float linfactor = m_linearMotorTimescale/pTimestep; - // Linear accel - Vector3 addAmount1 = (m_linearMotorDirection/linfactor) * 0.8f; - // Differential accel - Vector3 addAmount2 = ((m_linearMotorDirection - m_lastLinearVelocityVector)/linfactor) * 1.6f; - // SL correction - Vector3 addAmount = (addAmount1 + addAmount2) * m_linearAttackFactor; - m_lastLinearVelocityVector += addAmount; // lastLinearVelocityVector is the current body velocity vector -//if(frcount == 0) Console.WriteLine("AL {0} + AD {1} AS{2} V {3}", addAmount1, addAmount2, addAmount, m_lastLinearVelocityVector); - // This will work temporarily, but we really need to compare speed on an axis - // KF: Limit body velocity to applied velocity? - if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) - m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; - if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) - m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; - if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) - m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; - - // decay applied velocity - Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); - //Console.WriteLine("decay: " + decayfraction); - m_linearMotorDirection -= m_linearMotorDirection * decayfraction * m_linearDecayFactor; - //Console.WriteLine("actual: " + m_linearMotorDirection); - } - else - { // requested is not significant - // if what remains of applied is small, zero it. - if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) - m_lastLinearVelocityVector = Vector3.Zero; - } - - - // convert requested object velocity to world-referenced vector - m_dir = m_lastLinearVelocityVector; d.Quaternion rot = d.BodyGetQuaternion(Body); Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object - m_dir *= rotq; // apply obj rotation to velocity vector + Quaternion irotq = Quaternion.Inverse(rotq); + d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame + Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z); + acceleration = vel_now - m_wLinObjectVel; + m_lLinObjectVel = vel_now * irotq; + + if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate + { + if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f) + { + float decayfactor = m_linearMotorDecayTimescale/pTimestep; + Vector3 decayAmount = (m_lLinMotorDVel/decayfactor); + m_lLinMotorDVel -= decayAmount; + } + else + { + float decayfactor = 3.0f - (0.57f * (float)Math.Log((double)(m_linearMotorDecayTimescale))); + Vector3 decel = Vector3.Normalize(m_lLinMotorDVel) * decayfactor * pTimestep; + m_lLinMotorDVel -= decel; + } + if (m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) + { + m_lLinMotorDVel = Vector3.Zero; + } + else + { + if (Math.Abs(m_lLinMotorDVel.X) < Math.Abs(m_lLinObjectVel.X)) m_lLinObjectVel.X = m_lLinMotorDVel.X; + if (Math.Abs(m_lLinMotorDVel.Y) < Math.Abs(m_lLinObjectVel.Y)) m_lLinObjectVel.Y = m_lLinMotorDVel.Y; + if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z; + } + } - // add Gravity and Buoyancy - // KF: So far I have found no good method to combine a script-requested - // .Z velocity and gravity. Therefore only 0g will used script-requested - // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. + if ( (! m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! m_lLinObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) + { + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + if (m_linearMotorTimescale < 300.0f) + { + Vector3 attack_error = m_lLinMotorDVel - m_lLinObjectVel; + float linfactor = m_linearMotorTimescale/pTimestep; + Vector3 attackAmount = (attack_error/linfactor) * 1.3f; + m_lLinObjectVel += attackAmount; + } + if (m_linearFrictionTimescale.X < 300.0f) + { + float fricfactor = m_linearFrictionTimescale.X / pTimestep; + float fricX = m_lLinObjectVel.X / fricfactor; + m_lLinObjectVel.X -= fricX; + } + if (m_linearFrictionTimescale.Y < 300.0f) + { + float fricfactor = m_linearFrictionTimescale.Y / pTimestep; + float fricY = m_lLinObjectVel.Y / fricfactor; + m_lLinObjectVel.Y -= fricY; + } + if (m_linearFrictionTimescale.Z < 300.0f) + { + float fricfactor = m_linearFrictionTimescale.Z / pTimestep; + float fricZ = m_lLinObjectVel.Z / fricfactor; + m_lLinObjectVel.Z -= fricZ; + } + } + m_wLinObjectVel = m_lLinObjectVel * rotq; + // Add Gravity and Buoyancy Vector3 grav = Vector3.Zero; if(m_VehicleBuoyancy < 1.0f) { @@ -528,10 +546,7 @@ namespace OpenSim.Region.Physics.OdePlugin d.Mass objMass; d.BodyGetMass(Body, out objMass); // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); - // Preserve the current Z velocity - d.Vector3 vel_now = d.BodyGetLinearVel(Body); - m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity + grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); // Applied later as a force } // else its 1.0, no gravity. // Check if hovering @@ -567,24 +582,24 @@ namespace OpenSim.Region.Physics.OdePlugin { d.Mass objMass; d.BodyGetMass(Body, out objMass); - m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale); + m_wLinObjectVel.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale); //KF: m_VhoverEfficiency is not yet implemented } else { - m_dir.Z = 0f; + m_wLinObjectVel.Z = 0f; } } - + else + { // not hovering, Gravity rules + m_wLinObjectVel.Z = vel_now.Z; +//if(frcount == 0) Console.WriteLine(" Z {0} a.Z {1}", m_wLinObjectVel.Z, acceleration.Z); + } // Apply velocity - d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z); + d.BodySetLinearVel(Body, m_wLinObjectVel.X, m_wLinObjectVel.Y, m_wLinObjectVel.Z); // apply gravity force d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); - - - // apply friction - Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); - m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount * m_linearFrictionFactor; +//if(frcount == 0) Console.WriteLine("Grav {0}", grav); } // end MoveLinear() private void MoveAngular(float pTimestep) @@ -633,7 +648,7 @@ namespace OpenSim.Region.Physics.OdePlugin if(m_verticalAttractionTimescale < 300) { - float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); + float VAservo = 0.0167f / (m_verticalAttractionTimescale * pTimestep); // get present body rotation d.Quaternion rot = d.BodyGetQuaternion(Body); Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs index 60786d4..deb6164 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs @@ -229,7 +229,7 @@ namespace OpenSim.Region.Physics.OdePlugin public int bodyFramesAutoDisable = 20; - protected DateTime m_lastframe = DateTime.UtcNow; + private DateTime m_lastframe = DateTime.UtcNow; private float[] _watermap; private bool m_filterCollisions = true; -- cgit v1.1 From 1abb70cc73c997c08a416fecf689b83453f853d0 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 21 Jan 2010 19:31:02 -0500 Subject: Add glue for llSetVehicleFlags(), llRemoveVehicleFlags(). ChODE: Add associated methods. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 18 +++++++++++++++++- .../Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs | 10 ++++++++++ .../BulletDotNETPlugin/BulletDotNETCharacter.cs | 10 ++++++++++ .../Physics/BulletDotNETPlugin/BulletDotNETPrim.cs | 10 ++++++++++ .../Region/Physics/BulletXPlugin/BulletXPlugin.cs | 10 ++++++++++ OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs | 10 ++++++++++ OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs | 10 ++++++++++ OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 12 +++++++++++- OpenSim/Region/Physics/Manager/PhysicsActor.cs | 12 ++++++++++++ OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 10 ++++++++++ OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 10 ++++++++++ OpenSim/Region/Physics/POSPlugin/POSCharacter.cs | 10 ++++++++++ OpenSim/Region/Physics/POSPlugin/POSPrim.cs | 10 ++++++++++ OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs | 20 ++++++++++++++++++++ .../Shared/Api/Implementation/LSL_Api.cs | 16 ++++++++++++++-- 15 files changed, 174 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 4c97467..04be9fc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2963,7 +2963,23 @@ namespace OpenSim.Region.Framework.Scenes PhysActor.VehicleRotationParam(param, rotation); } } - + + public void SetVehicleFlags(int flags) + { + if (PhysActor != null) + { + PhysActor.VehicleFlagsSet(flags); + } + } + + public void RemoveVehicleFlags(int flags) + { + if (PhysActor != null) + { + PhysActor.VehicleFlagsRemove(flags); + } + } + public void SetGroup(UUID groupID, IClientAPI client) { _groupID = groupID; diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs index 31366db..25b9099 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs @@ -184,7 +184,17 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin { } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + } + public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs index a3344dd..120d040 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs @@ -361,7 +361,17 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + } + public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs index 9603ea4..f430def 100644 --- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs +++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETPrim.cs @@ -396,7 +396,17 @@ namespace OpenSim.Region.Physics.BulletDotNETPlugin { //TODO: } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + } + public override void SetVolumeDetect(int param) { //TODO: GhostObject diff --git a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs index d5d146e..9113ebe 100644 --- a/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs +++ b/OpenSim/Region/Physics/BulletXPlugin/BulletXPlugin.cs @@ -984,7 +984,17 @@ namespace OpenSim.Region.Physics.BulletXPlugin { } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + } + public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index aa0acb7..2eb519f 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -733,7 +733,17 @@ namespace OpenSim.Region.Physics.OdePlugin { } + + public override void VehicleFlagsSet(int flags) + { + } + + public override void VehicleFlagsRemove(int flags) + { + + } + public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs index 9e145ec..14d5caa 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs @@ -286,7 +286,17 @@ namespace OpenSim.Region.Physics.OdePlugin } }//end ProcessRotationVehicleParam + + internal void ProcessFlagsVehicleSet(int flags) + { + m_flags |= (VehicleFlag)flags; + } + internal void ProcessFlagsVehicleRemove(int flags) + { + m_flags &= ~((VehicleFlag)flags); + } + internal void ProcessTypeChange(Vehicle pType) { // Set Defaults For Type diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 6e6b44f..29a3dd9 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -2415,7 +2415,17 @@ Console.WriteLine(" JointCreateFixed"); { m_vehicle.ProcessRotationVehicleParam((Vehicle) param, rotation); } - + + public override void VehicleFlagsSet(int flags) + { + m_vehicle.ProcessFlagsVehicleSet(flags); + } + + public override void VehicleFlagsRemove(int flags) + { + m_vehicle.ProcessFlagsVehicleRemove(flags); + } + public override void SetVolumeDetect(int param) { lock (_parent_scene.OdeLock) diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 9c192ed..f43de48 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -208,6 +208,8 @@ namespace OpenSim.Region.Physics.Manager public abstract void VehicleFloatParam(int param, float value); public abstract void VehicleVectorParam(int param, Vector3 value); public abstract void VehicleRotationParam(int param, Quaternion rotation); + public abstract void VehicleFlagsSet(int flags); + public abstract void VehicleFlagsRemove(int flags); public abstract void SetVolumeDetect(int param); // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more @@ -351,7 +353,17 @@ namespace OpenSim.Region.Physics.Manager { } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + } + public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index a38fccc..b713142 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -733,7 +733,17 @@ namespace OpenSim.Region.Physics.OdePlugin { } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + } + public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 567fd0e..010d97f 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -2352,6 +2352,16 @@ Console.WriteLine(" JointCreateFixed"); { m_vehicle.ProcessRotationVehicleParam((Vehicle) param, rotation); } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + + } public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs b/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs index 566b4e7..491e200 100644 --- a/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs +++ b/OpenSim/Region/Physics/POSPlugin/POSCharacter.cs @@ -181,7 +181,17 @@ namespace OpenSim.Region.Physics.POSPlugin { } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + } + public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs index edccf47..f8d49f9 100644 --- a/OpenSim/Region/Physics/POSPlugin/POSPrim.cs +++ b/OpenSim/Region/Physics/POSPlugin/POSPrim.cs @@ -138,7 +138,17 @@ namespace OpenSim.Region.Physics.POSPlugin { } + + public override void VehicleFlagsSet(int flags) + { + } + + public override void VehicleFlagsRemove(int flags) + { + + } + public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs index 24eb6b1..e54065c 100644 --- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs +++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPlugin.cs @@ -370,7 +370,17 @@ namespace OpenSim.Region.Physics.PhysXPlugin { } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + } + public override void SetVolumeDetect(int param) { @@ -774,7 +784,17 @@ namespace OpenSim.Region.Physics.PhysXPlugin { } + + public override void VehicleFlagsSet(int flags) + { + + } + + public override void VehicleFlagsRemove(int flags) + { + } + public override void SetVolumeDetect(int param) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a5aecd8..33218aa 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6315,13 +6315,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetVehicleFlags(int flags) { m_host.AddScriptLPS(1); - NotImplemented("llSetVehicleFlags"); + if (m_host.ParentGroup != null) + { + if (!m_host.ParentGroup.IsDeleted) + { + m_host.ParentGroup.RootPart.SetVehicleFlags(flags); + } + } } public void llRemoveVehicleFlags(int flags) { m_host.AddScriptLPS(1); - NotImplemented("llRemoveVehicleFlags"); + if (m_host.ParentGroup != null) + { + if (!m_host.ParentGroup.IsDeleted) + { + m_host.ParentGroup.RootPart.RemoveVehicleFlags(flags); + } + } } public void llSitTarget(LSL_Vector offset, LSL_Rotation rot) -- cgit v1.1 From e9c9a74e0ade505ee8d8d8e7790141f758a65f61 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 26 Jan 2010 15:12:41 +0000 Subject: Some merge fixups --- .../Avatar/InstantMessage/OfflineMessageModule.cs | 9 +++++---- .../Framework/Scenes/SceneObjectGroup.Inventory.cs | 4 ++-- .../Framework/Scenes/SceneObjectPartInventory.cs | 2 +- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 18 +++--------------- 4 files changed, 11 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index 3e86848..8f289c0 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -180,11 +180,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage private void RetrieveInstantMessages(IClientAPI client) { - if (m_RestURL != "") - { - m_log.DebugFormat("[OFFLINE MESSAGING] Retrieving stored messages for {0}", client.AgentId); + if (m_RestURL == String.Empty) + return; + + m_log.DebugFormat("[OFFLINE MESSAGING] Retrieving stored messages for {0}", client.AgentId); - List msglist = SynchronousRestObjectPoster.BeginPostObject>( + List msglist = SynchronousRestObjectPoster.BeginPostObject>( "POST", m_RestURL + "/RetrieveMessages/", client.AgentId); if (msglist != null) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index aea005e..8b58b3e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -74,7 +74,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Stop the scripts contained in all the prims in this group /// - public void RemoveScriptInstances() + public void RemoveScriptInstances(bool sceneObjectBeingDeleted) { lockPartsForRead(true); List values = new List(m_parts.Values); @@ -82,7 +82,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in values) { - part.Inventory.RemoveScriptInstances(); + part.Inventory.RemoveScriptInstances(sceneObjectBeingDeleted); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 1de0092..9661775 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -249,7 +249,7 @@ namespace OpenSim.Region.Framework.Scenes { if ((int)InventoryType.LSL == item.InvType) { - RemoveScriptInstance(item.ItemID); + RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); m_part.RemoveScriptEvents(item.ItemID); } } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 73850e1..35d57d8 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -885,12 +885,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.ClearQueue(); instance.Stop(0); - SceneObjectPart part = - m_Scene.GetSceneObjectPart(localID); - - if (part != null) - part.RemoveScriptEvents(itemID); - // bool objectRemoved = false; lock (m_PrimObjects) @@ -923,18 +917,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance = null; -<<<<<<< HEAD:OpenSim/Region/ScriptEngine/XEngine/XEngine.cs ObjectRemoved handlerObjectRemoved = OnObjectRemoved; if (handlerObjectRemoved != null) + { + SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); handlerObjectRemoved(part.UUID); -======= - ObjectRemoved handlerObjectRemoved = OnObjectRemoved; - if (handlerObjectRemoved != null) - { - SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); - handlerObjectRemoved(part.UUID); - } ->>>>>>> master:OpenSim/Region/ScriptEngine/XEngine/XEngine.cs + } CleanAssemblies(); -- cgit v1.1 From 862caa72a80b597ccbf1ae82300af89f9103dbf9 Mon Sep 17 00:00:00 2001 From: Revolution Date: Wed, 27 Jan 2010 21:08:55 -0600 Subject: Fixes terrain editing. Changes ThrottleOutPacketType to task instead of land. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 33210d7..64e45d0 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -1098,7 +1098,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); layerpack.Header.Reliable = true; - OutPacket(layerpack, ThrottleOutPacketType.Land); + OutPacket(layerpack, ThrottleOutPacketType.Task); } catch (Exception e) { -- cgit v1.1 From cfca9e1e811f6cdea6b7c3338f7f783a07f8e0ac Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 29 Jan 2010 07:20:13 +0000 Subject: Revert "Updates all IRegionModules to the new style region modules." This reverts commit ec3c31e61e5e540f822891110df9bc978655bbaf. --- .../LoadRegions/LoadRegionsPlugin.cs | 4 +- OpenSim/Client/MXP/MXPModule.cs | 36 ++-- .../AssetTransaction/AssetTransactionModule.cs | 35 +--- .../Agent/Capabilities/CapabilitiesModule.cs | 2 +- .../Region/CoreModules/Agent/IPBan/IPBanModule.cs | 40 ++-- .../Agent/TextureDownload/TextureDownloadModule.cs | 33 +--- .../Agent/TextureSender/J2KDecoderModule.cs | 33 +--- .../Region/CoreModules/Agent/Xfer/XferModule.cs | 30 +-- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 29 +-- .../CoreModules/Avatar/Combat/CombatModule.cs | 32 +--- .../CoreModules/Avatar/Dialog/DialogModule.cs | 32 +--- .../CoreModules/Avatar/Friends/FriendsModule.cs | 54 ++---- .../CoreModules/Avatar/Gestures/GesturesModule.cs | 30 +-- .../Region/CoreModules/Avatar/Gods/GodsModule.cs | 28 +-- .../CoreModules/Avatar/Groups/GroupsModule.cs | 35 +--- .../Avatar/InstantMessage/InstantMessageModule.cs | 53 ++---- .../Avatar/InstantMessage/MessageTransferModule.cs | 54 ++---- .../Avatar/InstantMessage/MuteListModule.cs | 48 ++--- .../Avatar/InstantMessage/OfflineMessageModule.cs | 41 ++-- .../Avatar/InstantMessage/PresenceModule.cs | 61 ++---- .../Inventory/Archiver/InventoryArchiverModule.cs | 35 +--- .../Inventory/Transfer/InventoryTransferModule.cs | 63 ++---- .../Region/CoreModules/Avatar/Lure/LureModule.cs | 61 ++---- .../CoreModules/Avatar/ObjectCaps/ObjectAdd.cs | 55 ++---- .../Avatar/Profiles/AvatarProfilesModule.cs | 32 ++-- .../Framework/EventQueue/EventQueueGetModule.cs | 40 ++-- .../Framework/Monitoring/MonitorModule.cs | 103 ++++------ .../Hypergrid/HGStandaloneLoginModule.cs | 83 +++----- OpenSim/Region/CoreModules/InterGrid/OGSRadmin.cs | 31 ++- .../InterGrid/OpenGridProtocolModule.cs | 100 ++++------ .../DynamicTexture/DynamicTextureModule.cs | 60 ++---- .../Scripting/EMailModules/EmailModule.cs | 32 +--- .../Scripting/HttpRequest/ScriptsHttpRequests.cs | 36 ++-- .../CoreModules/Scripting/LSLHttp/UrlModule.cs | 2 - .../Scripting/LoadImageURL/LoadImageURLModule.cs | 37 ++-- .../Scripting/VectorRender/VectorRenderModule.cs | 41 ++-- .../Scripting/WorldComm/WorldCommModule.cs | 33 ++-- .../CoreModules/Scripting/XMLRPC/XMLRPCModule.cs | 51 +---- .../Asset/AssetServiceInConnectorModule.cs | 2 +- .../Grid/HypergridServiceInConnectorModule.cs | 2 +- .../Inventory/InventoryServiceInConnectorModule.cs | 2 +- .../Land/LandServiceInConnectorModule.cs | 2 +- .../Neighbour/NeighbourServiceInConnectorModule.cs | 2 +- .../SimulationServiceInConnectorModule.cs | 2 +- .../Interregion/LocalInterregionComms.cs | 4 +- .../Interregion/RESTInterregionComms.cs | 16 +- .../CoreModules/World/Archiver/ArchiverModule.cs | 1 - .../Region/CoreModules/World/Cloud/CloudModule.cs | 30 +-- .../World/Estate/EstateManagementModule.cs | 58 +++--- .../World/Permissions/PermissionsModule.cs | 212 ++++++++------------- .../Region/CoreModules/World/Sound/SoundModule.cs | 33 +--- OpenSim/Region/CoreModules/World/Sun/SunModule.cs | 96 +++++----- .../World/Vegetation/VegetationModule.cs | 27 +-- .../Region/CoreModules/World/Wind/WindModule.cs | 45 ++--- .../CoreModules/World/WorldMap/MapImageModule.cs | 30 +-- .../CoreModules/World/WorldMap/MapSearchModule.cs | 35 +--- OpenSim/Region/DataSnapshot/DataSnapshotManager.cs | 55 +++--- .../Region/Framework/Interfaces/ICloudModule.cs | 2 +- .../Region/Framework/Interfaces/IEmailModule.cs | 2 +- .../Region/Framework/Interfaces/IEstateModule.cs | 2 +- OpenSim/Region/Framework/Interfaces/ISunModule.cs | 2 +- OpenSim/Region/Framework/Interfaces/IWindModule.cs | 2 +- .../InternetRelayClientView/IRCStackModule.cs | 32 +--- .../Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 72 ++----- .../ContentManagementModule.cs | 47 ++--- .../Scripting/Minimodule/MRMModule.cs | 64 +++---- .../RegionReadyModule/RegionReadyModule.cs | 6 +- .../ScriptModuleComms/ScriptModuleCommsModule.cs | 1 - .../XmlRpcRouterModule/XmlRpcGridRouterModule.cs | 28 +-- .../XmlRpcRouterModule/XmlRpcRouterModule.cs | 30 +-- .../FreeswitchServiceInConnectorModule.cs | 2 +- .../SvnSerialiser/SvnBackupModule.cs | 28 +-- .../Region/OptionalModules/World/NPC/NPCModule.cs | 28 +-- .../World/TreePopulator/TreePopulatorModule.cs | 41 ++-- OpenSim/Region/UserStatistics/WebStatsModule.cs | 33 ++-- OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs | 9 +- 76 files changed, 879 insertions(+), 1811 deletions(-) diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs index 64863c5..6fd3d30 100644 --- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs +++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs @@ -99,7 +99,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions regionLoader.SetIniConfigSource(m_openSim.ConfigSource.Source); RegionInfo[] regionsToLoad = regionLoader.LoadRegions(); - /*m_log.Info("[LOADREGIONSPLUGIN]: Loading specific shared modules..."); + m_log.Info("[LOADREGIONSPLUGIN]: Loading specific shared modules..."); m_log.Info("[LOADREGIONSPLUGIN]: DynamicTextureModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new DynamicTextureModule()); m_log.Info("[LOADREGIONSPLUGIN]: InstantMessageModule..."); @@ -111,7 +111,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions m_log.Info("[LOADREGIONSPLUGIN]: AssetTransactionModule..."); m_openSim.ModuleLoader.LoadDefaultSharedModule(new AssetTransactionModule()); m_log.Info("[LOADREGIONSPLUGIN]: Done."); - */ + if (!CheckRegionsForSanity(regionsToLoad)) { m_log.Error("[LOADREGIONS]: Halting startup due to conflicts in region configurations"); diff --git a/OpenSim/Client/MXP/MXPModule.cs b/OpenSim/Client/MXP/MXPModule.cs index 47417ab..0b442cc 100644 --- a/OpenSim/Client/MXP/MXPModule.cs +++ b/OpenSim/Client/MXP/MXPModule.cs @@ -31,7 +31,6 @@ using System.Reflection; using System.Text; using System.Timers; using log4net; -using Mono.Addins; using MXP; using Nini.Config; using OpenMetaverse; @@ -45,8 +44,7 @@ namespace OpenSim.Client.MXP /** * MXP Client Module which adds MXP support to client / region communication. */ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MXPModule : ISharedRegionModule + public class MXPModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -59,23 +57,15 @@ namespace OpenSim.Client.MXP private readonly Dictionary m_scenes = new Dictionary(); private bool m_shutdown; - public void Initialise(IConfigSource source) - { - m_config = source; - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { if (!m_scenes.ContainsKey(scene.RegionInfo.RegionID)) m_scenes.Add(scene.RegionInfo.RegionID, scene); + + m_config = source; } - public void RegionLoaded(Scene scene) + public void PostInitialise() { if (m_config.Configs["MXP"] != null) { @@ -86,7 +76,7 @@ namespace OpenSim.Client.MXP m_port = con.GetInt("Port", m_port); - m_server = new MXPPacketServer(m_port, m_scenes, m_config.Configs["StandAlone"].GetBoolean("accounts_authenticate", true)); + m_server = new MXPPacketServer(m_port, m_scenes,m_config.Configs["StandAlone"].GetBoolean("accounts_authenticate",true)); m_ticker = new Timer(100); m_ticker.AutoReset = false; @@ -99,14 +89,6 @@ namespace OpenSim.Client.MXP } } - public void RemoveRegion(Scene scene) - { - } - - public void PostInitialise() - { - } - void ticker_Elapsed(object sender, ElapsedEventArgs e) { try @@ -139,5 +121,11 @@ namespace OpenSim.Client.MXP { get { return "MXP ClientStack Module"; } } + + public bool IsSharedModule + { + get { return true; } + } + } } diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 7012037..1077f4a 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -27,7 +27,6 @@ using System; using System.Collections.Generic; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -36,8 +35,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class AssetTransactionModule : ISharedRegionModule, IAgentAssetTransactions + public class AssetTransactionModule : IRegionModule, IAgentAssetTransactions { private readonly Dictionary RegisteredScenes = new Dictionary(); private bool m_dumpAssetsToFile = false; @@ -61,14 +59,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction //m_log.Debug("creating AgentAssetTransactionModule"); } - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) - { - - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource config) { if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) { @@ -86,23 +79,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction m_scene = scene; } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - if (RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) - RegisteredScenes.Remove(scene.RegionInfo.RegionID); - scene.UnregisterModuleInterface(this); - scene.EventManager.OnNewClient -= NewClient; - } - public void PostInitialise() { } @@ -116,6 +92,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction get { return "AgentTransactionModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion public void NewClient(IClientAPI client) diff --git a/OpenSim/Region/CoreModules/Agent/Capabilities/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Agent/Capabilities/CapabilitiesModule.cs index 886173f..2a1355b 100644 --- a/OpenSim/Region/CoreModules/Agent/Capabilities/CapabilitiesModule.cs +++ b/OpenSim/Region/CoreModules/Agent/Capabilities/CapabilitiesModule.cs @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Agent.Capabilities public void RemoveRegion(Scene scene) { - scene.UnregisterModuleInterface(this); + m_scene.UnregisterModuleInterface(this); } public void PostInitialise() {} diff --git a/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs b/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs index f7f2eff..bfe2a71 100644 --- a/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs +++ b/OpenSim/Region/CoreModules/Agent/IPBan/IPBanModule.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.IO; using System.Text; -using Mono.Addins; using Nini.Config; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -37,27 +36,21 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Agent.IPBan { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class IPBanModule : ISharedRegionModule + public class IPBanModule : IRegionModule { - #region Implementation of ISharedRegionModule + #region Implementation of IRegionModule private List m_bans = new List(); - private Dictionary SceneBanners = new Dictionary(); - public void Initialise(IConfigSource source) + public void Initialise(Scene scene, IConfigSource source) { - } - - public void AddRegion(Scene scene) - { - SceneBanners.Add(scene, new SceneBanner(scene, m_bans)); + new SceneBanner(scene, m_bans); lock (m_bans) { foreach (EstateBan ban in scene.RegionInfo.EstateSettings.EstateBans) { - if (!String.IsNullOrEmpty(ban.BannedHostIPMask)) + if (!String.IsNullOrEmpty(ban.BannedHostIPMask)) m_bans.Add(ban.BannedHostIPMask); if (!String.IsNullOrEmpty(ban.BannedHostNameMask)) m_bans.Add(ban.BannedHostNameMask); @@ -65,12 +58,7 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan } } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) + public void PostInitialise() { if (File.Exists("bans.txt")) { @@ -82,18 +70,9 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan } } - public void RemoveRegion(Scene scene) - { - if(SceneBanners.ContainsKey(scene)) - SceneBanners.Remove(scene); - } - - public void PostInitialise() - { - } - public void Close() { + } public string Name @@ -101,6 +80,11 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan get { return "IPBanModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion /// diff --git a/OpenSim/Region/CoreModules/Agent/TextureDownload/TextureDownloadModule.cs b/OpenSim/Region/CoreModules/Agent/TextureDownload/TextureDownloadModule.cs index c4d84cb..71ff28c 100644 --- a/OpenSim/Region/CoreModules/Agent/TextureDownload/TextureDownloadModule.cs +++ b/OpenSim/Region/CoreModules/Agent/TextureDownload/TextureDownloadModule.cs @@ -30,7 +30,6 @@ using System.Collections.Generic; using System.Reflection; using System.Threading; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -42,8 +41,7 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Agent.TextureDownload { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class TextureDownloadModule : INonSharedRegionModule + public class TextureDownloadModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -67,14 +65,11 @@ namespace OpenSim.Region.CoreModules.Agent.TextureDownload { } - #region INonSharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) - { - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource config) { + if (m_scene == null) { //m_log.Debug("Creating Texture download module"); @@ -95,23 +90,10 @@ namespace OpenSim.Region.CoreModules.Agent.TextureDownload } } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) + public void PostInitialise() { } - public void RemoveRegion(Scene scene) - { - if(m_scenes.Contains(scene)) - m_scenes.Remove(scene); - scene.EventManager.OnNewClient -= NewClient; - scene.EventManager.OnRemovePresence -= EventManager_OnRemovePresence; - } - public void Close() { } @@ -121,6 +103,11 @@ namespace OpenSim.Region.CoreModules.Agent.TextureDownload get { return "TextureDownloadModule"; } } + public bool IsSharedModule + { + get { return false; } + } + #endregion /// diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs index ff87493..7ac8bed 100644 --- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs +++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs @@ -32,7 +32,6 @@ using System.Reflection; using System.Text; using System.Threading; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; @@ -46,8 +45,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender { public delegate void J2KDecodeDelegate(UUID assetID); - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class J2KDecoderModule : ISharedRegionModule, IJ2KDecoder + public class J2KDecoderModule : IRegionModule, IJ2KDecoder { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -60,19 +58,16 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender /// Reference to a scene (doesn't matter which one as long as it can load the cache module) private Scene m_scene; - #region ISharedRegionModule + #region IRegionModule public string Name { get { return "J2KDecoderModule"; } } - - public J2KDecoderModule() - { - } + public bool IsSharedModule { get { return true; } } - public void Initialise(IConfigSource source) + public J2KDecoderModule() { } - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { if (m_scene == null) m_scene = scene; @@ -80,30 +75,16 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender scene.RegisterModuleInterface(this); } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) - { - m_cache = m_scene.RequestModuleInterface(); - } - - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - } - public void PostInitialise() { + m_cache = m_scene.RequestModuleInterface(); } public void Close() { } - #endregion + #endregion IRegionModule #region IJ2KDecoder diff --git a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs index d062361..ef7dce8 100644 --- a/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs +++ b/OpenSim/Region/CoreModules/Agent/Xfer/XferModule.cs @@ -27,7 +27,6 @@ using System; using System.Collections.Generic; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -36,8 +35,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Agent.Xfer { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class XferModule : INonSharedRegionModule, IXfer + public class XferModule : IRegionModule, IXfer { private Scene m_scene; private Dictionary Requests = new Dictionary(); @@ -54,13 +52,9 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer public DateTime timeStamp; } - #region INonSharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) - { - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource config) { m_scene = scene; m_scene.EventManager.OnNewClient += NewClient; @@ -68,21 +62,10 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer m_scene.RegisterModuleInterface(this); } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) + public void PostInitialise() { } - public void RemoveRegion(Scene scene) - { - scene.EventManager.OnNewClient -= NewClient; - scene.UnregisterModuleInterface(this); - } - public void Close() { } @@ -92,6 +75,11 @@ namespace OpenSim.Region.CoreModules.Agent.Xfer get { return "XferModule"; } } + public bool IsSharedModule + { + get { return false; } + } + #endregion #region IXfer Members diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 6bbbd56..35c59aa 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -28,7 +28,6 @@ using System; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -39,8 +38,7 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class AvatarFactoryModule : IAvatarFactory, ISharedRegionModule + public class AvatarFactoryModule : IAvatarFactory, IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene = null; @@ -77,16 +75,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return appearance; } - public void Initialise(IConfigSource source) - { - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += NewClient; @@ -95,18 +84,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory { m_scene = scene; } - } - public void RegionLoaded(Scene scene) - { } - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - scene.EventManager.OnNewClient -= NewClient; - } - public void PostInitialise() { } @@ -120,6 +100,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory get { return "Default Avatar Factory"; } } + public bool IsSharedModule + { + get { return false; } + } + public void NewClient(IClientAPI client) { client.OnAvatarNowWearing += AvatarIsWearing; diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs index b7d12aa..61b6d65 100644 --- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs @@ -27,7 +27,6 @@ using System; using System.Collections.Generic; -using Mono.Addins; using Nini.Config; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -35,8 +34,7 @@ using OpenMetaverse; namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class CombatModule : ISharedRegionModule + public class CombatModule : IRegionModule { //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -55,17 +53,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule /// /// /// - public void Initialise(IConfigSource config) - { - - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource config) { lock (m_scenel) { @@ -83,17 +71,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.EventManager.OnAvatarKilled -= KillAvatar; - scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; - m_scenel.Remove(scene.RegionInfo.RegionHandle); - } - public void PostInitialise() { } @@ -107,6 +84,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule get { return "CombatModule"; } } + public bool IsSharedModule + { + get { return true; } + } + private void KillAvatar(uint killerObjectLocalID, ScenePresence DeadAvatar) { if (killerObjectLocalID == 0) diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index ecffc7a..72ec869 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -25,11 +25,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -39,46 +37,28 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Avatar.Dialog { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class DialogModule : ISharedRegionModule, IDialogModule + public class DialogModule : IRegionModule, IDialogModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Scene m_scene; - public void Initialise(IConfigSource source) - { - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { m_scene = scene; m_scene.RegisterModuleInterface(this); - + m_scene.AddCommand( this, "alert", "alert ", "Send an alert to a user", HandleAlertConsoleCommand); m_scene.AddCommand( this, "alert general", "alert general ", "Send an alert to everyone", HandleAlertConsoleCommand); } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - } - - public void PostInitialise() { } + + public void PostInitialise() {} public void Close() {} public string Name { get { return "Dialog Module"; } } + public bool IsSharedModule { get { return false; } } public void SendAlertToUser(IClientAPI client, string message) { diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 7254180..086d4fe 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -31,7 +31,6 @@ using System.Collections.Generic; using System.Net; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using Nwc.XmlRpc; using OpenMetaverse; @@ -82,8 +81,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends - Terminate Friendship messages (single) */ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class FriendsModule : ISharedRegionModule, IFriendsModule + public class FriendsModule : IRegionModule, IFriendsModule { private class Transaction { @@ -113,23 +111,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private IGridService m_gridServices = null; - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) - { - - } - - public void PostInitialise() - { - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource config) { lock (m_scenes) { @@ -144,9 +128,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (!m_scenes.ContainsKey(scene.RegionInfo.RegionHandle)) m_scenes[scene.RegionInfo.RegionHandle] = scene; } - + scene.RegisterModuleInterface(this); - + scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; @@ -154,34 +138,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends scene.EventManager.OnClientClosed += ClientClosed; } - public void RegionLoaded(Scene scene) + public void PostInitialise() { if (m_scenes.Count > 0) { - m_TransferModule = scene.RequestModuleInterface(); - m_gridServices = scene.GridService; + m_TransferModule = m_initialScene.RequestModuleInterface(); + m_gridServices = m_initialScene.GridService; } if (m_TransferModule == null) m_log.Error("[FRIENDS]: Unable to find a message transfer module, friendship offers will not work"); } - public void RemoveRegion(Scene scene) - { - MainServer.Instance.RemoveXmlRPCHandler("presence_update_bulk"); - MainServer.Instance.RemoveXmlRPCHandler("terminate_friend"); - - if (m_scenes.ContainsKey(scene.RegionInfo.RegionHandle)) - m_scenes.Remove(scene.RegionInfo.RegionHandle); - - scene.UnregisterModuleInterface(this); - - scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; - scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; - scene.EventManager.OnMakeChildAgent -= MakeChildAgent; - scene.EventManager.OnClientClosed -= ClientClosed; - } - public void Close() { } @@ -191,6 +158,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends get { return "FriendsModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion #region IInterregionFriendsComms diff --git a/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs index c306f94..8ce5092 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gestures/GesturesModule.cs @@ -25,10 +25,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -39,41 +37,23 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Gestures { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class GesturesModule : INonSharedRegionModule + public class GesturesModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Scene m_scene; - public void Initialise(IConfigSource source) - { - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { m_scene = scene; + m_scene.EventManager.OnNewClient += OnNewClient; } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - if(m_scene == scene) - m_scene = null; - scene.EventManager.OnNewClient -= OnNewClient; - } + public void PostInitialise() {} public void Close() {} public string Name { get { return "Gestures Module"; } } + public bool IsSharedModule { get { return false; } } private void OnNewClient(IClientAPI client) { diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index 3914f2e..50171a3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs @@ -25,9 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; using System.Collections.Generic; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -36,8 +34,7 @@ using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Gods { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class GodsModule : INonSharedRegionModule, IGodsModule + public class GodsModule : IRegionModule, IGodsModule { /// Special UUID for actions that apply to all agents private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb"); @@ -45,34 +42,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods protected Scene m_scene; protected IDialogModule m_dialogModule; - public void Initialise(IConfigSource source) - { - - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { m_scene = scene; m_dialogModule = m_scene.RequestModuleInterface(); m_scene.RegisterModuleInterface(this); } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - } + public void PostInitialise() {} public void Close() {} public string Name { get { return "Gods Module"; } } + public bool IsSharedModule { get { return false; } } public void RequestGodlikePowers( UUID agentID, UUID sessionID, UUID token, bool godLike, IClientAPI controllingClient) diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs index 7ff8d30..31363e5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs @@ -25,11 +25,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -38,8 +36,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Avatar.Groups { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class GroupsModule : ISharedRegionModule + public class GroupsModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -58,9 +55,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups private static GroupMembershipData osGroup = new GroupMembershipData(); - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { IConfig groupsConfig = config.Configs["Groups"]; @@ -79,15 +76,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups if (groupsConfig.GetString("Module", "Default") != "Default") return; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { lock (m_SceneList) { if (!m_SceneList.Contains(scene)) @@ -110,19 +99,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - if (m_SceneList.Contains(scene)) - m_SceneList.Remove(scene); - scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnClientClosed -= OnClientClosed; - scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; - } - public void PostInitialise() { } @@ -147,6 +123,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups get { return "GroupsModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion private void OnNewClient(IClientAPI client) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs index e1bde4b..9a68749 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs @@ -24,12 +24,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -39,8 +36,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class InstantMessageModule : ISharedRegionModule + public class InstantMessageModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -51,11 +47,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage private readonly List m_scenes = new List(); - #region ISharedRegionModule Members + #region IRegionModule Members private IMessageTransferModule m_TransferModule = null; - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { if (config.Configs["Messaging"] != null) { @@ -66,15 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } m_enabled = true; - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { lock (m_scenes) { if (!m_scenes.Contains(scene)) @@ -86,27 +74,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } } - public void RegionLoaded(Scene scene) - { - if (!m_enabled) - return; - - m_TransferModule = - m_scenes[0].RequestModuleInterface(); - - if (m_TransferModule == null) - m_log.Error("[INSTANT MESSAGE]: No message transfer module, " + - "IM will not work!"); - } - - public void RemoveRegion(Scene scene) - { - if (m_scenes.Contains(scene)) - m_scenes.Remove(scene); - scene.EventManager.OnClientConnect -= OnClientConnect; - scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; - } - void OnClientConnect(IClientCore client) { IClientIM clientIM; @@ -118,6 +85,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage public void PostInitialise() { + if (!m_enabled) + return; + + m_TransferModule = + m_scenes[0].RequestModuleInterface(); + + if (m_TransferModule == null) + m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+ + "IM will not work!"); } public void Close() @@ -129,6 +105,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage get { return "InstantMessageModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion public void OnInstantMessage(IClientAPI client, GridInstantMessage im) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 16bdfdd..e5159b3 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -30,7 +30,6 @@ using System.Collections.Generic; using System.Net; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using Nwc.XmlRpc; using OpenMetaverse; @@ -41,8 +40,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MessageTransferModule : ISharedRegionModule, IMessageTransferModule + public class MessageTransferModule : IRegionModule, IMessageTransferModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -52,9 +50,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage protected Dictionary m_UserRegionMap = new Dictionary(); public event UndeliveredMessage OnUndeliveredMessage; - private bool m_enabled = true; - public virtual void Initialise(IConfigSource config) + public virtual void Initialise(Scene scene, IConfigSource config) { IConfig cnf = config.Configs["Messaging"]; if (cnf != null && cnf.GetString( @@ -62,49 +59,27 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage "MessageTransferModule") { m_log.Debug("[MESSAGE TRANSFER]: Disabled by configuration"); - m_enabled = false; + return; } cnf = config.Configs["Startup"]; if (cnf != null) m_Gridmode = cnf.GetBoolean("gridmode", false); - } - public Type ReplaceableInterface - { - get { return null; } - } + // m_Enabled = true; - public void AddRegion(Scene scene) - { - if (m_enabled) + lock (m_Scenes) { - lock (m_Scenes) + if (m_Scenes.Count == 0) { - if (m_Scenes.Count == 0) - { - MainServer.Instance.AddXmlRPCHandler( - "grid_instant_message", processXMLRPCGridInstantMessage); - } - - m_log.Debug("[MESSAGE TRANSFER]: Message transfer module active"); - scene.RegisterModuleInterface(this); - m_Scenes.Add(scene); + MainServer.Instance.AddXmlRPCHandler( + "grid_instant_message", processXMLRPCGridInstantMessage); } - } - } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - if (m_Scenes.Contains(scene)) - m_Scenes.Remove(scene); - MainServer.Instance.RemoveXmlRPCHandler( - "grid_instant_message"); - scene.UnregisterModuleInterface(this); + m_log.Debug("[MESSAGE TRANSFER]: Message transfer module active"); + scene.RegisterModuleInterface(this); + m_Scenes.Add(scene); + } } public virtual void PostInitialise() @@ -120,6 +95,11 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage get { return "MessageTransferModule"; } } + public virtual bool IsSharedModule + { + get { return true; } + } + public virtual void SendInstantMessage(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs index 3570495..2d4a635 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MuteListModule.cs @@ -28,7 +28,6 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -40,8 +39,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Avatar.MuteList { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MuteListModule : ISharedRegionModule + public class MuteListModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -49,7 +47,7 @@ namespace OpenSim.Region.CoreModules.Avatar.MuteList private List m_SceneList = new List(); private string m_RestURL = String.Empty; - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { if (!enabled) return; @@ -68,24 +66,19 @@ namespace OpenSim.Region.CoreModules.Avatar.MuteList enabled = false; return; } - m_RestURL = cnf.GetString("MuteListURL", ""); - if (m_RestURL == "") - { - m_log.Error("[MUTE LIST] Module was enabled, but no URL is given, disabling"); - enabled = false; - return; - } - } - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) - { lock (m_SceneList) { + if (m_SceneList.Count == 0) + { + m_RestURL = cnf.GetString("MuteListURL", ""); + if (m_RestURL == "") + { + m_log.Error("[MUTE LIST] Module was enabled, but no URL is given, disabling"); + enabled = false; + return; + } + } if (!m_SceneList.Contains(scene)) m_SceneList.Add(scene); @@ -93,18 +86,6 @@ namespace OpenSim.Region.CoreModules.Avatar.MuteList } } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - if (m_SceneList.Contains(scene)) - m_SceneList.Remove(scene); - - scene.EventManager.OnNewClient -= OnNewClient; - } - public void PostInitialise() { if (!enabled) @@ -121,6 +102,11 @@ namespace OpenSim.Region.CoreModules.Avatar.MuteList get { return "MuteListModule"; } } + public bool IsSharedModule + { + get { return true; } + } + public void Close() { } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index 8f289c0..0727fa9 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -28,7 +28,6 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -41,8 +40,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class OfflineMessageModule : ISharedRegionModule + public class OfflineMessageModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -51,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage private string m_RestURL = String.Empty; private bool m_ForwardOfflineGroupMessages = true; - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { if (!enabled) return; @@ -85,23 +83,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage return; } } - } - } - - public Type ReplaceableInterface - { - get { return null; } - } + if (!m_SceneList.Contains(scene)) + m_SceneList.Add(scene); - public void AddRegion(Scene scene) - { - if (!m_SceneList.Contains(scene)) - m_SceneList.Add(scene); - - scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnNewClient += OnNewClient; + } } - public void RegionLoaded(Scene scene) + public void PostInitialise() { if (!enabled) return; @@ -131,22 +120,16 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage m_log.Debug("[OFFLINE MESSAGING] Offline messages enabled"); } - public void RemoveRegion(Scene scene) - { - if (m_SceneList.Contains(scene)) - m_SceneList.Remove(scene); - scene.EventManager.OnNewClient -= OnNewClient; - } - - public void PostInitialise() - { - } - public string Name { get { return "OfflineMessageModule"; } } + public bool IsSharedModule + { + get { return true; } + } + public void Close() { } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs index f5498f4..f5ab454 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/PresenceModule.cs @@ -24,14 +24,11 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -using System; using System.Collections; using System.Collections.Generic; using System.Net; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using Nwc.XmlRpc; using OpenMetaverse; @@ -42,8 +39,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class PresenceModule : ISharedRegionModule, IPresenceModule + public class PresenceModule : IRegionModule, IPresenceModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -63,7 +59,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage public event PresenceChange OnPresenceChange; public event BulkPresenceData OnBulkPresenceData; - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { lock (m_Scenes) { @@ -82,38 +78,28 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage m_Gridmode = cnf.GetBoolean("gridmode", false); m_Enabled = true; - } - } - } - public Type ReplaceableInterface - { - get { return null; } - } + m_initialScene = scene; + } - public void AddRegion(Scene scene) - { - if (m_Enabled) - { - m_initialScene = scene; if (m_Gridmode) NotifyMessageServerOfStartup(scene); m_Scenes.Add(scene); + } - scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; - scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; - } + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; + scene.EventManager.OnMakeChildAgent += OnMakeChildAgent; } - public void RegionLoaded(Scene scene) + public void PostInitialise() { } - public void RemoveRegion(Scene scene) + public void Close() { if (!m_Gridmode || !m_Enabled) return; @@ -130,28 +116,21 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } } - NotifyMessageServerOfShutdown(scene); - if(m_Scenes.Contains(scene)) - m_Scenes.Remove(scene); - - scene.UnregisterModuleInterface(this); - - scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; - scene.EventManager.OnMakeChildAgent -= OnMakeChildAgent; - } - - public void PostInitialise() - { + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + NotifyMessageServerOfShutdown(scene); + } } - public void Close() + public string Name { + get { return "PresenceModule"; } } - public string Name + public bool IsSharedModule { - get { return "PresenceModule"; } + get { return true; } } public void RequestBulkPresenceData(UUID[] users) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index a04ab22..ecd60bd 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -30,7 +30,6 @@ using System.Collections.Generic; using System.IO; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -42,11 +41,10 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] /// /// This module loads and saves OpenSimulator inventory archives /// - public class InventoryArchiverModule : ISharedRegionModule, IInventoryArchiverModule + public class InventoryArchiverModule : IRegionModule, IInventoryArchiverModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -84,28 +82,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver DisablePresenceChecks = disablePresenceChecks; } - public void Initialise(IConfigSource source) - { - - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { if (m_scenes.Count == 0) { scene.RegisterModuleInterface(this); OnInventoryArchiveSaved += SaveInvConsoleCommandCompleted; - + scene.AddCommand( this, "load iar", "load iar []", - "Load user inventory archive.", HandleLoadInvConsoleCommand); - + "Load user inventory archive.", HandleLoadInvConsoleCommand); + scene.AddCommand( this, "save iar", "save iar []", @@ -113,21 +101,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver m_aScene = scene; } - + m_scenes[scene.RegionInfo.RegionID] = scene; } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - if(m_scenes.ContainsKey(scene.RegionInfo.RegionID)) - m_scenes.Remove(scene.RegionInfo.RegionID); - } - public void PostInitialise() {} public void Close() {} diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index abf440e..b60b32b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -40,8 +39,7 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule + public class InventoryTransferModule : IInventoryTransferModule, IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -52,11 +50,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer new Dictionary(); private IMessageTransferModule m_TransferModule = null; - private bool m_enabled = true; - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { if (config.Configs["Messaging"] != null) { @@ -65,61 +62,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (config.Configs["Messaging"].GetString( "InventoryTransferModule", "InventoryTransferModule") != "InventoryTransferModule") - m_enabled = false; + return; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { - if (m_enabled) + if (!m_Scenelist.Contains(scene)) { - if (!m_Scenelist.Contains(scene)) - { - m_Scenelist.Add(scene); + m_Scenelist.Add(scene); - scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnClientClosed += ClientLoggedOut; - scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - } + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnClientClosed += ClientLoggedOut; + scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; } } - public void RegionLoaded(Scene scene) + public void PostInitialise() { - if (m_enabled) + if (m_Scenelist.Count > 0) { - if (m_Scenelist.Count > 0) - { - m_TransferModule = m_Scenelist[0].RequestModuleInterface(); - if (m_TransferModule == null) - m_log.Error("[INVENTORY TRANSFER] No Message transfer module found, transfers will be local only"); - } + m_TransferModule = m_Scenelist[0].RequestModuleInterface(); + if (m_TransferModule == null) + m_log.Error("[INVENTORY TRANSFER] No Message transfer module found, transfers will be local only"); } } - public void RemoveRegion(Scene scene) - { - if (m_Scenelist.Contains(scene)) - m_Scenelist.Remove(scene); - - scene.UnregisterModuleInterface(this); - - scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnClientClosed -= ClientLoggedOut; - scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; - } - - public void PostInitialise() - { - } - public void Close() { } diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index 973d27f..261bd6c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -38,72 +37,36 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Avatar.Lure { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class LureModule : ISharedRegionModule + public class LureModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private readonly List m_scenes = new List(); - private bool m_enabled = true; - private IMessageTransferModule m_TransferModule = null; - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { if (config.Configs["Messaging"] != null) { if (config.Configs["Messaging"].GetString( "LureModule", "LureModule") != "LureModule") - m_enabled = false; + return; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { - if (m_enabled) + lock (m_scenes) { - lock (m_scenes) + if (!m_scenes.Contains(scene)) { - if (!m_scenes.Contains(scene)) - { - m_scenes.Add(scene); - scene.EventManager.OnNewClient += OnNewClient; - scene.EventManager.OnIncomingInstantMessage += - OnGridInstantMessage; - } + m_scenes.Add(scene); + scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnIncomingInstantMessage += + OnGridInstantMessage; } } } - public void RegionLoaded(Scene scene) - { - if (m_enabled) - { - m_TransferModule = - m_scenes[0].RequestModuleInterface(); - - if (m_TransferModule == null) - m_log.Error("[INSTANT MESSAGE]: No message transfer module, " + - "lures will not work!"); - } - } - - public void RemoveRegion(Scene scene) - { - if (m_scenes.Contains(scene)) - m_scenes.Remove(scene); - scene.EventManager.OnNewClient -= OnNewClient; - scene.EventManager.OnIncomingInstantMessage -= - OnGridInstantMessage; - } - void OnNewClient(IClientAPI client) { client.OnInstantMessage += OnInstantMessage; @@ -113,6 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure public void PostInitialise() { + m_TransferModule = + m_scenes[0].RequestModuleInterface(); + + if (m_TransferModule == null) + m_log.Error("[INSTANT MESSAGE]: No message transfer module, "+ + "lures will not work!"); } public void Close() diff --git a/OpenSim/Region/CoreModules/Avatar/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/CoreModules/Avatar/ObjectCaps/ObjectAdd.cs index 748b42c..63a93aa 100644 --- a/OpenSim/Region/CoreModules/Avatar/ObjectCaps/ObjectAdd.cs +++ b/OpenSim/Region/CoreModules/Avatar/ObjectCaps/ObjectAdd.cs @@ -29,7 +29,6 @@ using System; using System.Collections; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -42,54 +41,24 @@ using Caps=OpenSim.Framework.Capabilities.Caps; namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class ObjectAdd : ISharedRegionModule + public class ObjectAdd : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource pSource) + public void Initialise(Scene pScene, IConfigSource pSource) { - - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) - { - m_scene = scene; + m_scene = pScene; m_scene.EventManager.OnRegisterCaps += RegisterCaps; } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.EventManager.OnRegisterCaps -= RegisterCaps; - } - public void PostInitialise() { } - public void Close() - { - - } - - public string Name - { - get { return "ObjectAddModule"; } - } - public void RegisterCaps(UUID agentID, Caps caps) { UUID capuuid = UUID.Random(); @@ -379,6 +348,22 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps Array.Reverse(resultbytes); return String.Format("{0}",Convert.ToBase64String(resultbytes)); } + + public void Close() + { + + } + + public string Name + { + get { return "ObjectAddModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + #endregion } } diff --git a/OpenSim/Region/CoreModules/Avatar/Profiles/AvatarProfilesModule.cs b/OpenSim/Region/CoreModules/Avatar/Profiles/AvatarProfilesModule.cs index 7fcb0e1..8cf58c6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Profiles/AvatarProfilesModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Profiles/AvatarProfilesModule.cs @@ -30,7 +30,6 @@ using System.Collections; using System.Globalization; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -39,17 +38,20 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Avatar.Profiles { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class AvatarProfilesModule : INonSharedRegionModule + public class AvatarProfilesModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; private IProfileModule m_profileModule = null; private bool m_enabled = true; - #region INonSharedRegionModule Members + public AvatarProfilesModule() + { + } - public void Initialise(IConfigSource config) + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) { IConfig profileConfig = config.Configs["Profile"]; if (profileConfig != null) @@ -60,31 +62,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Profiles return; } } - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { m_scene = scene; m_scene.EventManager.OnNewClient += NewClient; } - public void RegionLoaded(Scene scene) + public void PostInitialise() { if (!m_enabled) return; m_profileModule = m_scene.RequestModuleInterface(); } - public void RemoveRegion(Scene scene) - { - scene.EventManager.OnNewClient -= NewClient; - } - public void Close() { } @@ -94,6 +83,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Profiles get { return "AvatarProfilesModule"; } } + public bool IsSharedModule + { + get { return false; } + } + #endregion public void NewClient(IClientAPI client) diff --git a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs index 1ee6f0d..0c6cb1b 100644 --- a/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EventQueue/EventQueueGetModule.cs @@ -32,7 +32,6 @@ using System.Net; using System.Reflection; using System.Threading; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Packets; @@ -53,13 +52,11 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue public OSDMap body; } - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class EventQueueGetModule : IEventQueue, INonSharedRegionModule + public class EventQueueGetModule : IEventQueue, IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Scene m_scene = null; private IConfigSource m_gConfig; - private IConfig m_startupConfig; bool enabledYN = false; private Dictionary m_ids = new Dictionary(); @@ -68,31 +65,23 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue private Dictionary m_QueueUUIDAvatarMapping = new Dictionary(); private Dictionary m_AvatarQueueUUIDMapping = new Dictionary(); - #region INonSharedRegionModule methods - public virtual void Initialise(IConfigSource config) + #region IRegionModule methods + public virtual void Initialise(Scene scene, IConfigSource config) { m_gConfig = config; - m_startupConfig = m_gConfig.Configs["Startup"]; - } + IConfig startupConfig = m_gConfig.Configs["Startup"]; - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) - { - ReadConfigAndPopulate(scene, m_startupConfig, "Startup"); + ReadConfigAndPopulate(scene, startupConfig, "Startup"); if (enabledYN) { m_scene = scene; scene.RegisterModuleInterface(this); - + // Register fallback handler // Why does EQG Fail on region crossings! - + //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); scene.EventManager.OnNewClient += OnNewClient; @@ -110,19 +99,16 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue { m_gConfig = null; } + } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) + private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p) { + enabledYN = startupConfig.GetBoolean("EventQueue", true); } - private void ReadConfigAndPopulate(Scene scene, IConfig startupConfig, string p) + public void PostInitialise() { - enabledYN = startupConfig.GetBoolean("EventQueue", true); } public virtual void Close() @@ -134,6 +120,10 @@ namespace OpenSim.Region.CoreModules.Framework.EventQueue get { return "EventQueueGetModule"; } } + public bool IsSharedModule + { + get { return false; } + } #endregion /// diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index 0135d33..f15f8f6 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs @@ -25,12 +25,10 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -41,8 +39,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Framework.Monitoring { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MonitorModule : INonSharedRegionModule + public class MonitorModule : IRegionModule { private Scene m_scene; private readonly List m_monitors = new List(); @@ -65,19 +62,9 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring } } - #region Implementation of INonSharedRegionModule + #region Implementation of IRegionModule - public void Initialise(IConfigSource source) - { - - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { m_scene = scene; @@ -90,51 +77,6 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring MainServer.Instance.AddHTTPHandler("/monitorstats/" + m_scene.RegionInfo.RegionID + "/", StatsPage); } - public void RegionLoaded(Scene scene) - { - m_monitors.Add(new AgentCountMonitor(m_scene)); - m_monitors.Add(new ChildAgentCountMonitor(m_scene)); - m_monitors.Add(new GCMemoryMonitor()); - m_monitors.Add(new ObjectCountMonitor(m_scene)); - m_monitors.Add(new PhysicsFrameMonitor(m_scene)); - m_monitors.Add(new PhysicsUpdateFrameMonitor(m_scene)); - m_monitors.Add(new PWSMemoryMonitor()); - m_monitors.Add(new ThreadCountMonitor()); - m_monitors.Add(new TotalFrameMonitor(m_scene)); - m_monitors.Add(new EventFrameMonitor(m_scene)); - m_monitors.Add(new LandFrameMonitor(m_scene)); - m_monitors.Add(new LastFrameTimeMonitor(m_scene)); - - m_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor)); - - foreach (IAlert alert in m_alerts) - { - alert.OnTriggerAlert += OnTriggerAlert; - } - } - - public void RemoveRegion(Scene scene) - { - MainServer.Instance.RemoveHTTPHandler("", "/monitorstats/" + m_scene.RegionInfo.RegionID + "/"); - m_monitors.Clear(); - - foreach (IAlert alert in m_alerts) - { - alert.OnTriggerAlert -= OnTriggerAlert; - } - m_alerts.Clear(); - } - - public void Close() - { - - } - - public string Name - { - get { return "Region Health Monitoring Module"; } - } - public Hashtable StatsPage(Hashtable request) { // If request was for a specific monitor @@ -190,10 +132,49 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring return ereply; } + public void PostInitialise() + { + m_monitors.Add(new AgentCountMonitor(m_scene)); + m_monitors.Add(new ChildAgentCountMonitor(m_scene)); + m_monitors.Add(new GCMemoryMonitor()); + m_monitors.Add(new ObjectCountMonitor(m_scene)); + m_monitors.Add(new PhysicsFrameMonitor(m_scene)); + m_monitors.Add(new PhysicsUpdateFrameMonitor(m_scene)); + m_monitors.Add(new PWSMemoryMonitor()); + m_monitors.Add(new ThreadCountMonitor()); + m_monitors.Add(new TotalFrameMonitor(m_scene)); + m_monitors.Add(new EventFrameMonitor(m_scene)); + m_monitors.Add(new LandFrameMonitor(m_scene)); + m_monitors.Add(new LastFrameTimeMonitor(m_scene)); + + m_alerts.Add(new DeadlockAlert(m_monitors.Find(x => x is LastFrameTimeMonitor) as LastFrameTimeMonitor)); + + foreach (IAlert alert in m_alerts) + { + alert.OnTriggerAlert += OnTriggerAlert; + } + } + void OnTriggerAlert(System.Type reporter, string reason, bool fatal) { m_log.Error("[Monitor] " + reporter.Name + " for " + m_scene.RegionInfo.RegionName + " reports " + reason + " (Fatal: " + fatal + ")"); } + + public void Close() + { + + } + + public string Name + { + get { return "Region Health Monitoring Module"; } + } + + public bool IsSharedModule + { + get { return false; } + } + #endregion } } diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs index f9c594b..0b54746 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -32,7 +32,6 @@ using System.Net; using System.Reflection; using System.Text.RegularExpressions; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using Nwc.XmlRpc; @@ -47,8 +46,7 @@ using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.CoreModules.Hypergrid { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class HGStandaloneLoginModule : ISharedRegionModule, ILoginServiceToRegionsConnector + public class HGStandaloneLoginModule : IRegionModule, ILoginServiceToRegionsConnector { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -58,58 +56,47 @@ namespace OpenSim.Region.CoreModules.Hypergrid protected bool m_enabled = false; // Module is only enabled if running in standalone mode protected HGLoginAuthService m_loginService; - private bool authenticate = true; - private string welcomeMessage = "Welcome to OpenSim"; - private IConfig startupConfig; - private IConfig standaloneConfig; - - #region ISharedRegionModule Members - - public void Initialise(IConfigSource source) - { - startupConfig = source.Configs["Startup"]; - standaloneConfig = source.Configs["StandAlone"]; - if (standaloneConfig != null) - { - authenticate = standaloneConfig.GetBoolean("accounts_authenticate", true); - welcomeMessage = standaloneConfig.GetString("welcome_message"); - } - m_enabled = !startupConfig.GetBoolean("gridmode", false); - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { - } + #region IRegionModule Members - public void RegionLoaded(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { if (m_firstScene == null) { m_firstScene = scene; + IConfig startupConfig = source.Configs["Startup"]; + if (startupConfig != null) + { + m_enabled = !startupConfig.GetBoolean("gridmode", false); + } + if (m_enabled) { m_log.Debug("[HGLogin]: HGlogin module enabled"); + bool authenticate = true; + string welcomeMessage = "Welcome to OpenSim"; + IConfig standaloneConfig = source.Configs["StandAlone"]; + if (standaloneConfig != null) + { + authenticate = standaloneConfig.GetBoolean("accounts_authenticate", true); + welcomeMessage = standaloneConfig.GetString("welcome_message"); + } //TODO: fix casting. LibraryRootFolder rootFolder = m_firstScene.CommsManager.UserProfileCacheService.LibraryRoot as LibraryRootFolder; - + IHttpServer httpServer = MainServer.Instance; //TODO: fix the casting of the user service, maybe by registering the userManagerBase with scenes, or refactoring so we just need a IUserService reference - m_loginService + m_loginService = new HGLoginAuthService( - (UserManagerBase)m_firstScene.CommsManager.UserAdminService, - welcomeMessage, - m_firstScene.CommsManager.InterServiceInventoryService, - m_firstScene.CommsManager.NetworkServersInfo, - authenticate, - rootFolder, + (UserManagerBase)m_firstScene.CommsManager.UserAdminService, + welcomeMessage, + m_firstScene.CommsManager.InterServiceInventoryService, + m_firstScene.CommsManager.NetworkServersInfo, + authenticate, + rootFolder, this); httpServer.AddXmlRPCHandler("hg_login", m_loginService.XmlRpcLoginMethod); @@ -126,19 +113,6 @@ namespace OpenSim.Region.CoreModules.Hypergrid } } - public void RemoveRegion(Scene scene) - { - if (scene == m_firstScene) - { - IHttpServer httpServer = MainServer.Instance; - httpServer.RemoveXmlRPCHandler("hg_login"); - httpServer.RemoveXmlRPCHandler("check_auth_session"); - httpServer.RemoveXmlRPCHandler("get_avatar_appearance"); - httpServer.RemoveXmlRPCHandler("update_avatar_appearance"); - } - m_scenes.Remove(scene); - } - public void PostInitialise() { @@ -154,6 +128,11 @@ namespace OpenSim.Region.CoreModules.Hypergrid get { return "HGStandaloneLoginModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion protected void AddScene(Scene scene) diff --git a/OpenSim/Region/CoreModules/InterGrid/OGSRadmin.cs b/OpenSim/Region/CoreModules/InterGrid/OGSRadmin.cs index 4534024..0f2ba32 100644 --- a/OpenSim/Region/CoreModules/InterGrid/OGSRadmin.cs +++ b/OpenSim/Region/CoreModules/InterGrid/OGSRadmin.cs @@ -32,7 +32,6 @@ using System.Net; using System.Reflection; using System.Text; using log4net; -using Mono.Addins; using Nini.Config; using Nwc.XmlRpc; using OpenMetaverse; @@ -43,8 +42,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.InterGrid { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class OGSRadmin : ISharedRegionModule + public class OGSRadmin : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private readonly List m_scenes = new List(); @@ -58,6 +56,7 @@ namespace OpenSim.Region.CoreModules.InterGrid get { return "OGS Supporting RAdmin"; } } + public void Initialise(IConfigSource source) { m_settings = source; @@ -68,11 +67,6 @@ namespace OpenSim.Region.CoreModules.InterGrid } - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) { lock (m_scenes) @@ -83,11 +77,15 @@ namespace OpenSim.Region.CoreModules.InterGrid { lock (m_scenes) m_scenes.Remove(scene); - MainServer.Instance.RemoveXmlRPCHandler("grid_message"); } public void RegionLoaded(Scene scene) { + + } + + public void PostInitialise() + { if (m_settings.Configs["Startup"].GetBoolean("gridmode", false)) { m_com = m_scenes[0].CommsManager; @@ -95,8 +93,21 @@ namespace OpenSim.Region.CoreModules.InterGrid } } - public void PostInitialise() + #endregion + + #region IRegionModule + + public void Initialise(Scene scene, IConfigSource source) + { + m_settings = source; + + lock (m_scenes) + m_scenes.Add(scene); + } + + public bool IsSharedModule { + get { return true; } } #endregion diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs index 8bb0fa9..10a3232 100644 --- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs +++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs @@ -35,7 +35,6 @@ using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Web; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -76,9 +75,8 @@ namespace OpenSim.Region.CoreModules.InterGrid public bool visible_to_parent; public string teleported_into_region; } - - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class OpenGridProtocolModule : ISharedRegionModule + + public class OpenGridProtocolModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_scene = new List(); @@ -94,22 +92,21 @@ namespace OpenSim.Region.CoreModules.InterGrid private bool httpSSL = false; private uint httpsslport = 0; private bool GridMode = false; - private bool m_enabled = false; - private IConfig cfg = null; - private IConfig httpcfg = null; - private IConfig startupcfg = null; - - #region ISharedRegionModule Members - public void Initialise(IConfigSource config) + #region IRegionModule Members + + public void Initialise(Scene scene, IConfigSource config) { + bool enabled = false; + IConfig cfg = null; + IConfig httpcfg = null; + IConfig startupcfg = null; try { cfg = config.Configs["OpenGridProtocol"]; - } - catch (NullReferenceException) + } catch (NullReferenceException) { - m_enabled = false; + enabled = false; } try @@ -131,15 +128,15 @@ namespace OpenSim.Region.CoreModules.InterGrid if (startupcfg != null) { - GridMode = m_enabled = startupcfg.GetBoolean("gridmode", false); + GridMode = enabled = startupcfg.GetBoolean("gridmode", false); } if (cfg != null) { - m_enabled = cfg.GetBoolean("ogp_enabled", false); + enabled = cfg.GetBoolean("ogp_enabled", false); LastNameSuffix = cfg.GetString("ogp_lastname_suffix", "_EXTERNAL"); FirstNamePrefix = cfg.GetString("ogp_firstname_prefix", ""); - if (m_enabled) + if (enabled) { m_log.Warn("[OGP]: Open Grid Protocol is on, Listening for Clients on /agent/"); lock (m_scene) @@ -168,61 +165,35 @@ namespace OpenSim.Region.CoreModules.InterGrid } } + // can't pick the region 'agent' because it would conflict with our agent domain handler + // a zero length region name would conflict with are base region seed cap + if (!SceneListDuplicateCheck(scene.RegionInfo.RegionName) && scene.RegionInfo.RegionName.ToLower() != "agent" && scene.RegionInfo.RegionName.Length > 0) + { + MainServer.Instance.AddLLSDHandler( + "/" + HttpUtility.UrlPathEncode(scene.RegionInfo.RegionName.ToLower()), + ProcessRegionDomainSeed); + } + + if (!m_scene.Contains(scene)) + m_scene.Add(scene); } } } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) - { - if (m_enabled) + lock (m_scene) { - lock (m_scene) + if (m_scene.Count == 1) { - if (m_scene.Count == 1) + if (httpcfg != null) { - if (httpcfg != null) - { - httpSSL = httpcfg.GetBoolean("http_listener_ssl", false); - httpsCN = httpcfg.GetString("http_listener_cn", scene.RegionInfo.ExternalHostName); - if (httpsCN.Length == 0) - httpsCN = scene.RegionInfo.ExternalHostName; - httpsslport = (uint)httpcfg.GetInt("http_listener_sslport", ((int)scene.RegionInfo.HttpPort + 1)); - } + httpSSL = httpcfg.GetBoolean("http_listener_ssl", false); + httpsCN = httpcfg.GetString("http_listener_cn", scene.RegionInfo.ExternalHostName); + if (httpsCN.Length == 0) + httpsCN = scene.RegionInfo.ExternalHostName; + httpsslport = (uint)httpcfg.GetInt("http_listener_sslport",((int)scene.RegionInfo.HttpPort + 1)); } } - // can't pick the region 'agent' because it would conflict with our agent domain handler - // a zero length region name would conflict with are base region seed cap - if (!SceneListDuplicateCheck(scene.RegionInfo.RegionName) && scene.RegionInfo.RegionName.ToLower() != "agent" && scene.RegionInfo.RegionName.Length > 0) - { - MainServer.Instance.AddLLSDHandler( - "/" + HttpUtility.UrlPathEncode(scene.RegionInfo.RegionName.ToLower()), - ProcessRegionDomainSeed); - } - - if (!m_scene.Contains(scene)) - m_scene.Add(scene); } } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - MainServer.Instance.RemoveLLSDHandler( - "/" + HttpUtility.UrlPathEncode(scene.RegionInfo.RegionName.ToLower()), - ProcessRegionDomainSeed); - - if (m_scene.Contains(scene)) - m_scene.Remove(scene); - } public void PostInitialise() { @@ -238,6 +209,11 @@ namespace OpenSim.Region.CoreModules.InterGrid get { return "OpenGridProtocolModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion public OSD ProcessRegionDomainSeed(string path, OSD request, string endpoint) diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 40b7159..679c871 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; @@ -41,8 +40,7 @@ using System.Reflection; namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class DynamicTextureModule : ISharedRegionModule, IDynamicTextureManager + public class DynamicTextureModule : IRegionModule, IDynamicTextureManager { //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -212,14 +210,9 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture #endregion - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) - { - - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource config) { if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) { @@ -228,24 +221,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) - { - RegisteredScenes.Remove(scene.RegionInfo.RegionID); - scene.UnregisterModuleInterface(this); - } - } - public void PostInitialise() { } @@ -259,6 +234,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture get { return "DynamicTextureModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion #region Nested type: DynamicTextureUpdater @@ -378,18 +358,18 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture // tmptex.DefaultTexture.Fullbright = true; part.UpdateTexture(tmptex); - } - - if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) - { - if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); - if (oldAsset != null) - { - if (oldAsset.Temporary == true) - { - scene.AssetService.Delete(oldID.ToString()); - } - } + } + + if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) + { + if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); + if (oldAsset != null) + { + if (oldAsset.Temporary == true) + { + scene.AssetService.Delete(oldID.ToString()); + } + } } } diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs index d6ed468..83f004d 100644 --- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs @@ -32,7 +32,6 @@ using System.Text.RegularExpressions; using DotNetOpenMail; using DotNetOpenMail.SmtpAuth; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -41,7 +40,6 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Scripting.EmailModules { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class EmailModule : IEmailModule { // @@ -96,7 +94,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules } } - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { m_Config = config; IConfig SMTPConfig; @@ -138,16 +136,7 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules m_Enabled = false; return; } - m_log.Info("[EMAIL] Activated DefaultEmailModule"); - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { // It's a go! if (m_Enabled) { @@ -166,20 +155,8 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules m_Scenes.Add(scene.RegionInfo.RegionHandle, scene); } } - } - } - - public void RegionLoaded(Scene scene) - { - } - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - - if (m_Scenes.ContainsKey(scene.RegionInfo.RegionHandle)) - { - m_Scenes.Remove(scene.RegionInfo.RegionHandle); + m_log.Info("[EMAIL] Activated DefaultEmailModule"); } } @@ -196,6 +173,11 @@ namespace OpenSim.Region.CoreModules.Scripting.EmailModules get { return "DefaultEmailModule"; } } + public bool IsSharedModule + { + get { return true; } + } + /// /// Delay function using thread in seconds /// diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index e331b8d..d78931a 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -31,7 +31,6 @@ using System.IO; using System.Net; using System.Text; using System.Threading; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -85,8 +84,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Scripting.HttpRequest { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class HttpRequestModule : ISharedRegionModule, IHttpRequestModule + public class HttpRequestModule : IRegionModule, IHttpRequestModule { private object HttpListLock = new object(); private int httpTimeout = 30000; @@ -231,35 +229,18 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest #endregion - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) - { - m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); - m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); - - m_pendingRequests = new Dictionary(); - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource config) { m_scene = scene; m_scene.RegisterModuleInterface(this); - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void RegionLoaded(Scene scene) - { - } + m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); + m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); + m_pendingRequests = new Dictionary(); } public void PostInitialise() @@ -275,6 +256,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest get { return m_name; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion } diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 6ce55a9..9b565ed 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -126,8 +126,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void RemoveRegion(Scene scene) { - scene.UnregisterModuleInterface(this); - scene.EventManager.OnScriptReset -= OnScriptReset; } public void Close() diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 35ce2cb..c23cea5 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -29,7 +29,6 @@ using System; using System.Drawing; using System.IO; using System.Net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; @@ -40,8 +39,7 @@ using System.Reflection; namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class LoadImageURLModule : ISharedRegionModule, IDynamicTextureRender + public class LoadImageURLModule : IRegionModule, IDynamicTextureRender { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -99,28 +97,20 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL #endregion - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) - { - m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); - m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource config) { if (m_scene == null) { m_scene = scene; } + + m_proxyurl = config.Configs["Startup"].GetString("HttpProxy"); + m_proxyexcepts = config.Configs["Startup"].GetString("HttpProxyExceptions"); } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) + public void PostInitialise() { m_textureManager = m_scene.RequestModuleInterface(); if (m_textureManager != null) @@ -129,14 +119,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL } } - public void RemoveRegion(Scene scene) - { - } - - public void PostInitialise() - { - } - public void Close() { } @@ -146,6 +128,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL get { return m_name; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion private void MakeHttpRequest(string url, UUID requestID) diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 71b01a1..d57a8e5 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -31,7 +31,6 @@ using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; @@ -44,8 +43,7 @@ using System.Reflection; namespace OpenSim.Region.CoreModules.Scripting.VectorRender { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class VectorRenderModule : ISharedRegionModule, IDynamicTextureRender + public class VectorRenderModule : IRegionModule, IDynamicTextureRender { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -112,10 +110,15 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender #endregion - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { + if (m_scene == null) + { + m_scene = scene; + } + if (m_graph == null) { Bitmap bitmap = new Bitmap(1024, 1024, PixelFormat.Format32bppArgb); @@ -130,20 +133,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender m_log.DebugFormat("[VECTORRENDERMODULE]: using font \"{0}\" for text rendering.", m_fontName); } - public void AddRegion(Scene scene) - { - if (m_scene == null) - { - m_scene = scene; - } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) + public void PostInitialise() { m_textureManager = m_scene.RequestModuleInterface(); if (m_textureManager != null) @@ -152,14 +142,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } } - public void RemoveRegion(Scene scene) - { - } - - public void PostInitialise() - { - } - public void Close() { } @@ -169,6 +151,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender get { return m_name; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion private void Draw(string data, UUID id, string extraParams) diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index d935c56..93aa88c 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -28,7 +28,6 @@ using System; using System.Collections; using System.Collections.Generic; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -86,8 +85,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Scripting.WorldComm { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class WorldCommModule : ISharedRegionModule, IWorldComm + public class WorldCommModule : IRegionModule, IWorldComm { // private static readonly ILog m_log = // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -100,9 +98,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm private int m_saydistance = 30; private int m_shoutdistance = 100; - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { // wrap this in a try block so that defaults will work if // the config file doesn't specify otherwise. @@ -122,6 +120,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (maxlisteners < 1) maxlisteners = int.MaxValue; if (maxhandles < 1) maxhandles = int.MaxValue; +<<<<<<< HEAD:OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs m_listenerManager = new ListenerManager(maxlisteners, maxhandles); m_pendingQ = new Queue(); m_pending = Queue.Synchronized(m_pendingQ); @@ -133,26 +132,19 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm public void AddRegion(Scene scene) { +======= +>>>>>>> ec3c31e... Updates all IRegionModules to the new style region modules.:OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs m_scene = scene; m_scene.RegisterModuleInterface(this); + m_listenerManager = new ListenerManager(maxlisteners, maxhandles); m_scene.EventManager.OnChatFromClient += DeliverClientMessage; m_scene.EventManager.OnChatBroadcast += DeliverClientMessage; + m_pendingQ = new Queue(); + m_pending = Queue.Synchronized(m_pendingQ); } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) + public void PostInitialise() { - scene.UnregisterModuleInterface(this); - scene.EventManager.OnChatFromClient -= DeliverClientMessage; - scene.EventManager.OnChatBroadcast -= DeliverClientMessage; } public void Close() @@ -164,6 +156,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm get { return "WorldCommModule"; } } + public bool IsSharedModule + { + get { return false; } + } + #endregion #region IWorldComm Members diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs index a9147fb6..27b64bf 100644 --- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs @@ -32,7 +32,6 @@ using System.Net; using System.Reflection; using System.Threading; using log4net; -using Mono.Addins; using Nini.Config; using Nwc.XmlRpc; using OpenMetaverse; @@ -77,8 +76,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Scripting.XMLRPC { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class XMLRPCModule : ISharedRegionModule, IXMLRPC + public class XMLRPCModule : IRegionModule, IXMLRPC { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -96,9 +94,9 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC private int RemoteReplyScriptWait = 300; private object XMLRPCListLock = new object(); - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { // We need to create these early because the scripts might be calling // But since this gets called for every region, we need to make sure they @@ -118,14 +116,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC { } } - } - - public void PostInitialise() - { - } - public void AddRegion(Scene scene) - { if (!m_scenes.Contains(scene)) { m_scenes.Add(scene); @@ -134,12 +125,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC } } - public Type ReplaceableInterface - { - get { return null; } - } - private Dictionary m_HttpServers = new Dictionary(); - public void RegionLoaded(Scene scene) + public void PostInitialise() { if (IsEnabled()) { @@ -147,31 +133,9 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC // Attach xmlrpc handlers m_log.Info("[REMOTE_DATA]: " + "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); - BaseHttpServer httpServer = new BaseHttpServer((uint)m_remoteDataPort); + BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort); httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); httpServer.Start(); - m_HttpServers.Add(scene, httpServer); - } - } - - public void RemoveRegion(Scene scene) - { - if (m_scenes.Contains(scene)) - m_scenes.Remove(scene); - scene.UnregisterModuleInterface(this); - if (IsEnabled()) - { - // Start http server - // Attach xmlrpc handlers - if (m_HttpServers.ContainsKey(scene)) - { - BaseHttpServer httpServer; - m_HttpServers.TryGetValue(scene, out httpServer); - m_log.Info("[REMOTE_DATA]: " + - "Stopping XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); - httpServer.RemoveXmlRPCHandler("llRemoteData"); - httpServer.Stop(); - } } } @@ -184,6 +148,11 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC get { return m_name; } } + public bool IsSharedModule + { + get { return true; } + } + public int Port { get { return m_remoteDataPort; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs index d3e2db7..879cc70 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Asset/AssetServiceInConnectorModule.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Asset private IConfigSource m_Config; bool m_Registered = false; - #region ISharedRegionModule interface + #region IRegionModule interface public void Initialise(IConfigSource config) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/HypergridServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/HypergridServiceInConnectorModule.cs index a895a3f..b12d778 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/HypergridServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Grid/HypergridServiceInConnectorModule.cs @@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Grid bool m_Registered = false; HypergridServiceInConnector m_HypergridHandler; - #region ISharedRegionModule interface + #region IRegionModule interface public void Initialise(IConfigSource config) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs index 4c74725..54c6d89 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory private IConfigSource m_Config; bool m_Registered = false; - #region ISharedRegionModule interface + #region IRegionModule interface public void Initialise(IConfigSource config) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs index dcc6dec..bce160a 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs @@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land private IConfigSource m_Config; private List m_Scenes = new List(); - #region ISharedRegionModule interface + #region IRegionModule interface public void Initialise(IConfigSource config) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs index a5c5ef6..8a90370 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs @@ -50,7 +50,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour private IConfigSource m_Config; private List m_Scenes = new List(); - #region ISharedRegionModule interface + #region IRegionModule interface public void Initialise(IConfigSource config) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs index c2cea16..f28a318 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Simulation/SimulationServiceInConnectorModule.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Simulation private IConfigSource m_Config; bool m_Registered = false; - #region ISharedRegionModule interface + #region IRegionModule interface public void Initialise(IConfigSource config) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs index 71d7993..d68c683 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs @@ -48,7 +48,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion #endregion /* Events */ - #region ISharedRegionModule + #region IRegionModule public void Initialise(IConfigSource config) { @@ -136,7 +136,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion } } - #endregion + #endregion /* IRegionModule */ #region IInterregionComms diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/RESTInterregionComms.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/RESTInterregionComms.cs index ca07a28..0357c60 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/RESTInterregionComms.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/RESTInterregionComms.cs @@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion protected bool m_safemode; protected IPAddress m_thisIP; - #region ISharedRegionModule + #region IRegionModule public virtual void Initialise(IConfigSource config) { @@ -149,7 +149,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion MainServer.Instance.AddHTTPHandler("/object/", ObjectHandler); } - #endregion + #endregion /* IRegionModule */ #region IInterregionComms @@ -435,12 +435,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion } OSDMap resp = new OSDMap(2); - string reason = String.Empty; - uint teleportFlags = 0; - if (args.ContainsKey("teleport_flags")) - { - teleportFlags = args["teleport_flags"].AsUInteger(); - } + string reason = String.Empty; + uint teleportFlags = 0; + if (args.ContainsKey("teleport_flags")) + { + teleportFlags = args["teleport_flags"].AsUInteger(); + } // This is the meaning of POST agent m_regionClient.AdjustUserInformation(aCircuit); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index c738b65..fc8d4e1 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -81,7 +81,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void RemoveRegion(Scene scene) { - scene.UnregisterModuleInterface(this); } public void Close() diff --git a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs index a2cfce6..5fa3dc2 100644 --- a/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs +++ b/OpenSim/Region/CoreModules/World/Cloud/CloudModule.cs @@ -27,7 +27,6 @@ using System; using System.Collections.Generic; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -36,7 +35,6 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class CloudModule : ICloudModule { // private static readonly log4net.ILog m_log @@ -50,7 +48,7 @@ namespace OpenSim.Region.CoreModules private float m_cloudDensity = 1.0F; private float[] cloudCover = new float[16 * 16]; - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { IConfig cloudConfig = config.Configs["Cloud"]; @@ -60,17 +58,10 @@ namespace OpenSim.Region.CoreModules m_cloudDensity = cloudConfig.GetFloat("density", 0.5F); m_frameUpdateRate = cloudConfig.GetInt("cloud_update_rate", 1000); } - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { if (m_enabled) { + m_scene = scene; scene.EventManager.OnNewClient += CloudsToClient; @@ -80,18 +71,9 @@ namespace OpenSim.Region.CoreModules GenerateCloudCover(); m_ready = true; - } - } - public void RegionLoaded(Scene scene) - { - } + } - public void RemoveRegion(Scene scene) - { - scene.EventManager.OnNewClient -= CloudsToClient; - scene.UnregisterModuleInterface(this); - scene.EventManager.OnFrame -= CloudUpdate; } public void PostInitialise() @@ -114,6 +96,12 @@ namespace OpenSim.Region.CoreModules get { return "CloudModule"; } } + public bool IsSharedModule + { + get { return false; } + } + + public float CloudCover(int x, int y, int z) { float cover = 0f; diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 39836ae..695cced 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -30,7 +30,6 @@ using System.IO; using System.Reflection; using System.Security; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -39,7 +38,6 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.World.Estate { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class EstateManagementModule : IEstateModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -900,16 +898,7 @@ namespace OpenSim.Region.CoreModules.World.Estate #region IRegionModule Members - public void Initialise(IConfigSource source) - { - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { m_scene = scene; m_scene.RegisterModuleInterface(this); @@ -931,29 +920,6 @@ namespace OpenSim.Region.CoreModules.World.Estate consoleSetTerrainHeights); } - public void RegionLoaded(Scene scene) - { - // Sets up the sun module based on the saved Estate and Region Settings - // DO NOT REMOVE or the sun will stop working - TriggerEstateToolsSunUpdate(); - } - - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - scene.EventManager.OnNewClient -= EventManager_OnNewClient; - scene.EventManager.OnRequestChangeWaterHeight -= changeWaterHeight; - } - - public void Close() - { - } - - public string Name - { - get { return "EstateManagementModule"; } - } - #region Console Commands public void consoleSetTerrainTexture(string module, string[] args) @@ -1040,6 +1006,28 @@ namespace OpenSim.Region.CoreModules.World.Estate } #endregion + + public void PostInitialise() + { + // Sets up the sun module based no the saved Estate and Region Settings + // DO NOT REMOVE or the sun will stop working + TriggerEstateToolsSunUpdate(); + } + + public void Close() + { + } + + public string Name + { + get { return "EstateManagementModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + #endregion #region Other Functions diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 5b15065..1533462 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -90,8 +89,7 @@ enum GroupPowers : long namespace OpenSim.Region.CoreModules.World.Permissions { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class PermissionsModule : INonSharedRegionModule + public class PermissionsModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -151,10 +149,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions #endregion - #region INonSharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { + m_scene = scene; + IConfig myConfig = config.Configs["Startup"]; string permissionModules = myConfig.GetString("permissionmodules", "DefaultPermissionsModule"); @@ -179,57 +179,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_bypassPermissions) m_log.Info("[PERMISSIONS]: serviceside_object_permissions = false in ini file so disabling all region service permission checks"); else - m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); - - string grant = myConfig.GetString("GrantLSL",""); - if (grant.Length > 0) { - foreach (string uuidl in grant.Split(',')) { - string uuid = uuidl.Trim(" \t".ToCharArray()); - GrantLSL.Add(uuid, true); - } - } - - grant = myConfig.GetString("GrantCS",""); - if (grant.Length > 0) { - foreach (string uuidl in grant.Split(',')) { - string uuid = uuidl.Trim(" \t".ToCharArray()); - GrantCS.Add(uuid, true); - } - } - - grant = myConfig.GetString("GrantVB",""); - if (grant.Length > 0) { - foreach (string uuidl in grant.Split(',')) { - string uuid = uuidl.Trim(" \t".ToCharArray()); - GrantVB.Add(uuid, true); - } - } - - grant = myConfig.GetString("GrantJS", ""); - if (grant.Length > 0) - { - foreach (string uuidl in grant.Split(',')) - { - string uuid = uuidl.Trim(" \t".ToCharArray()); - GrantJS.Add(uuid, true); - } - } - - grant = myConfig.GetString("GrantYP", ""); - if (grant.Length > 0) - { - foreach (string uuidl in grant.Split(',')) - { - string uuid = uuidl.Trim(" \t".ToCharArray()); - GrantYP.Add(uuid, true); - } - } - - } - - public void AddRegion(Scene scene) - { - m_scene = scene; + m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); //Register functions with Scene External Checks! m_scene.Permissions.OnBypassPermissions += BypassPermissions; @@ -262,23 +212,23 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene.Permissions.OnLinkObject += CanLinkObject; //NOT YET IMPLEMENTED m_scene.Permissions.OnDelinkObject += CanDelinkObject; //NOT YET IMPLEMENTED m_scene.Permissions.OnBuyLand += CanBuyLand; //NOT YET IMPLEMENTED - + m_scene.Permissions.OnViewNotecard += CanViewNotecard; //NOT YET IMPLEMENTED m_scene.Permissions.OnViewScript += CanViewScript; //NOT YET IMPLEMENTED m_scene.Permissions.OnEditNotecard += CanEditNotecard; //NOT YET IMPLEMENTED m_scene.Permissions.OnEditScript += CanEditScript; //NOT YET IMPLEMENTED - + m_scene.Permissions.OnCreateObjectInventory += CanCreateObjectInventory; //NOT IMPLEMENTED HERE m_scene.Permissions.OnEditObjectInventory += CanEditObjectInventory;//MAYBE FULLY IMPLEMENTED m_scene.Permissions.OnCopyObjectInventory += CanCopyObjectInventory; //NOT YET IMPLEMENTED m_scene.Permissions.OnDeleteObjectInventory += CanDeleteObjectInventory; //NOT YET IMPLEMENTED m_scene.Permissions.OnResetScript += CanResetScript; - + m_scene.Permissions.OnCreateUserInventory += CanCreateUserInventory; //NOT YET IMPLEMENTED m_scene.Permissions.OnCopyUserInventory += CanCopyUserInventory; //NOT YET IMPLEMENTED m_scene.Permissions.OnEditUserInventory += CanEditUserInventory; //NOT YET IMPLEMENTED m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; //NOT YET IMPLEMENTED - + m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED m_scene.Permissions.OnUseObjectReturn += CanUseObjectReturn; //NOT YET IMPLEMENTED @@ -296,87 +246,52 @@ namespace OpenSim.Region.CoreModules.World.Permissions "debug permissions ", "Enable permissions debugging", HandleDebugPermissions); - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) - { - m_friendsModule = m_scene.RequestModuleInterface(); + + + string grant = myConfig.GetString("GrantLSL",""); + if (grant.Length > 0) { + foreach (string uuidl in grant.Split(',')) { + string uuid = uuidl.Trim(" \t".ToCharArray()); + GrantLSL.Add(uuid, true); + } + } - if (m_friendsModule == null) - m_log.Error("[PERMISSIONS]: Friends module not found, friend permissions will not work"); - else - m_log.Info("[PERMISSIONS]: Friends module found, friend permissions enabled"); - } + grant = myConfig.GetString("GrantCS",""); + if (grant.Length > 0) { + foreach (string uuidl in grant.Split(',')) { + string uuid = uuidl.Trim(" \t".ToCharArray()); + GrantCS.Add(uuid, true); + } + } - public void RemoveRegion(Scene scene) - { - scene.Permissions.OnBypassPermissions -= BypassPermissions; - scene.Permissions.OnSetBypassPermissions -= SetBypassPermissions; - scene.Permissions.OnPropagatePermissions -= PropagatePermissions; - scene.Permissions.OnGenerateClientFlags -= GenerateClientFlags; - scene.Permissions.OnAbandonParcel -= CanAbandonParcel; - scene.Permissions.OnReclaimParcel -= CanReclaimParcel; - scene.Permissions.OnDeedParcel -= CanDeedParcel; - scene.Permissions.OnDeedObject -= CanDeedObject; - scene.Permissions.OnIsGod -= IsGod; - scene.Permissions.OnDuplicateObject -= CanDuplicateObject; - scene.Permissions.OnDeleteObject -= CanDeleteObject; //MAYBE FULLY IMPLEMENTED - scene.Permissions.OnEditObject -= CanEditObject; //MAYBE FULLY IMPLEMENTED - scene.Permissions.OnEditParcel -= CanEditParcel; //MAYBE FULLY IMPLEMENTED - scene.Permissions.OnInstantMessage -= CanInstantMessage; - scene.Permissions.OnInventoryTransfer -= CanInventoryTransfer; //NOT YET IMPLEMENTED - scene.Permissions.OnIssueEstateCommand -= CanIssueEstateCommand; //FULLY IMPLEMENTED - scene.Permissions.OnMoveObject -= CanMoveObject; //MAYBE FULLY IMPLEMENTED - scene.Permissions.OnObjectEntry -= CanObjectEntry; - scene.Permissions.OnReturnObject -= CanReturnObject; //NOT YET IMPLEMENTED - scene.Permissions.OnRezObject -= CanRezObject; //MAYBE FULLY IMPLEMENTED - scene.Permissions.OnRunConsoleCommand -= CanRunConsoleCommand; - scene.Permissions.OnRunScript -= CanRunScript; //NOT YET IMPLEMENTED - scene.Permissions.OnCompileScript -= CanCompileScript; - scene.Permissions.OnSellParcel -= CanSellParcel; - scene.Permissions.OnTakeObject -= CanTakeObject; - scene.Permissions.OnTakeCopyObject -= CanTakeCopyObject; - scene.Permissions.OnTerraformLand -= CanTerraformLand; - scene.Permissions.OnLinkObject -= CanLinkObject; //NOT YET IMPLEMENTED - scene.Permissions.OnDelinkObject -= CanDelinkObject; //NOT YET IMPLEMENTED - scene.Permissions.OnBuyLand -= CanBuyLand; //NOT YET IMPLEMENTED - - scene.Permissions.OnViewNotecard -= CanViewNotecard; //NOT YET IMPLEMENTED - scene.Permissions.OnViewScript -= CanViewScript; //NOT YET IMPLEMENTED - scene.Permissions.OnEditNotecard -= CanEditNotecard; //NOT YET IMPLEMENTED - scene.Permissions.OnEditScript -= CanEditScript; //NOT YET IMPLEMENTED - - scene.Permissions.OnCreateObjectInventory -= CanCreateObjectInventory; //NOT IMPLEMENTED HERE - scene.Permissions.OnEditObjectInventory -= CanEditObjectInventory;//MAYBE FULLY IMPLEMENTED - scene.Permissions.OnCopyObjectInventory -= CanCopyObjectInventory; //NOT YET IMPLEMENTED - scene.Permissions.OnDeleteObjectInventory -= CanDeleteObjectInventory; //NOT YET IMPLEMENTED - scene.Permissions.OnResetScript -= CanResetScript; - - scene.Permissions.OnCreateUserInventory -= CanCreateUserInventory; //NOT YET IMPLEMENTED - scene.Permissions.OnCopyUserInventory -= CanCopyUserInventory; //NOT YET IMPLEMENTED - scene.Permissions.OnEditUserInventory -= CanEditUserInventory; //NOT YET IMPLEMENTED - scene.Permissions.OnDeleteUserInventory -= CanDeleteUserInventory; //NOT YET IMPLEMENTED - - scene.Permissions.OnTeleport -= CanTeleport; //NOT YET IMPLEMENTED - scene.Permissions.OnUseObjectReturn -= CanUseObjectReturn; //NOT YET IMPLEMENTED - } + grant = myConfig.GetString("GrantVB",""); + if (grant.Length > 0) { + foreach (string uuidl in grant.Split(',')) { + string uuid = uuidl.Trim(" \t".ToCharArray()); + GrantVB.Add(uuid, true); + } + } - public void PostInitialise() - { - } + grant = myConfig.GetString("GrantJS", ""); + if (grant.Length > 0) + { + foreach (string uuidl in grant.Split(',')) + { + string uuid = uuidl.Trim(" \t".ToCharArray()); + GrantJS.Add(uuid, true); + } + } - public void Close() - { - } + grant = myConfig.GetString("GrantYP", ""); + if (grant.Length > 0) + { + foreach (string uuidl in grant.Split(',')) + { + string uuid = uuidl.Trim(" \t".ToCharArray()); + GrantYP.Add(uuid, true); + } + } - public string Name - { - get { return "PermissionsModule"; } } public void HandleBypassPermissions(string module, string[] args) @@ -449,6 +364,31 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_log.InfoFormat("[PERMISSIONS] Set permissions debugging to {0} in {1}", m_debugPermissions, m_scene.RegionInfo.RegionName); } } + + public void PostInitialise() + { + m_friendsModule = m_scene.RequestModuleInterface(); + + if (m_friendsModule == null) + m_log.Error("[PERMISSIONS]: Friends module not found, friend permissions will not work"); + else + m_log.Info("[PERMISSIONS]: Friends module found, friend permissions enabled"); + } + + public void Close() + { + } + + public string Name + { + get { return "PermissionsModule"; } + } + + public bool IsSharedModule + { + get { return false; } + } + #endregion #region Helper Functions diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index ed7bfe1..37f1f2e 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -26,7 +26,6 @@ */ using System; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -35,44 +34,26 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.World.Sound { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SoundModule : INonSharedRegionModule, ISoundModule + public class SoundModule : IRegionModule, ISoundModule { //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Scene m_scene; - public void Initialise(IConfigSource source) - { - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { m_scene = scene; - + m_scene.EventManager.OnNewClient += OnNewClient; - + m_scene.RegisterModuleInterface(this); } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.EventManager.OnNewClient -= OnNewClient; - scene.UnregisterModuleInterface(this); - } + public void PostInitialise() {} public void Close() {} public string Name { get { return "Sound Module"; } } - + public bool IsSharedModule { get { return false; } } + private void OnNewClient(IClientAPI client) { client.OnSoundTrigger += TriggerSound; diff --git a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs index 948c47c..0712a7f 100644 --- a/OpenSim/Region/CoreModules/World/Sun/SunModule.cs +++ b/OpenSim/Region/CoreModules/World/Sun/SunModule.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -38,7 +37,6 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class SunModule : ISunModule { /// @@ -280,12 +278,27 @@ namespace OpenSim.Region.CoreModules return GetCurrentSunHour() + 6.0f; } - #region INonSharedRegionModule Methods + #region IRegion Methods // Called immediately after the module is loaded for a given region // i.e. Immediately after instance creation. - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { + m_scene = scene; + m_frame = 0; + + // This one puts an entry in the main help screen + m_scene.AddCommand(this, String.Empty, "sun", "Usage: sun [param] [value] - Get or Update Sun module paramater", null); + + // This one enables the ability to type just "sun" without any parameters + m_scene.AddCommand(this, "sun", "", "", HandleSunConsoleCommand); + foreach (KeyValuePair kvp in GetParamList()) + { + m_scene.AddCommand(this, String.Format("sun {0}", kvp.Key), String.Format("{0} - {1}", kvp.Key, kvp.Value), "", HandleSunConsoleCommand); + } + + + TimeZone local = TimeZone.CurrentTimeZone; TicksUTCOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks; m_log.Debug("[SUN]: localtime offset is " + TicksUTCOffset); @@ -333,43 +346,7 @@ namespace OpenSim.Region.CoreModules // m_latitude = d_latitude; // m_longitude = d_longitude; } - } - - public void Close() - { - ready = false; - - // Remove our hooks - m_scene.EventManager.OnFrame -= SunUpdate; - m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; - m_scene.EventManager.OnEstateToolsSunUpdate -= EstateToolsSunUpdate; - m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour; - } - - public string Name - { - get { return "SunModule"; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) - { - m_scene = scene; - m_frame = 0; - - // This one puts an entry in the main help screen - m_scene.AddCommand(this, String.Empty, "sun", "Usage: sun [param] [value] - Get or Update Sun module paramater", null); - // This one enables the ability to type just "sun" without any parameters - m_scene.AddCommand(this, "sun", "", "", HandleSunConsoleCommand); - foreach (KeyValuePair kvp in GetParamList()) - { - m_scene.AddCommand(this, String.Format("sun {0}", kvp.Key), String.Format("{0} - {1}", kvp.Key, kvp.Value), "", HandleSunConsoleCommand); - } switch (m_RegionMode) { case "T1": @@ -377,8 +354,8 @@ namespace OpenSim.Region.CoreModules case "SL": // Time taken to complete a cycle (day and season) - SecondsPerSunCycle = (uint)(m_DayLengthHours * 60 * 60); - SecondsPerYear = (uint)(SecondsPerSunCycle * m_YearLengthDays); + SecondsPerSunCycle = (uint) (m_DayLengthHours * 60 * 60); + SecondsPerYear = (uint) (SecondsPerSunCycle*m_YearLengthDays); // Ration of real-to-virtual time @@ -387,17 +364,17 @@ namespace OpenSim.Region.CoreModules // Speed of rotation needed to complete a cycle in the // designated period (day and season) - SunSpeed = m_SunCycle / SecondsPerSunCycle; - SeasonSpeed = m_SeasonalCycle / SecondsPerYear; + SunSpeed = m_SunCycle/SecondsPerSunCycle; + SeasonSpeed = m_SeasonalCycle/SecondsPerYear; // Horizon translation - HorizonShift = m_HorizonShift; // Z axis translation + HorizonShift = m_HorizonShift; // Z axis translation // HoursToRadians = (SunCycle/24)*VWTimeRatio; // Insert our event handling hooks - scene.EventManager.OnFrame += SunUpdate; + scene.EventManager.OnFrame += SunUpdate; scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; scene.EventManager.OnEstateToolsSunUpdate += EstateToolsSunUpdate; scene.EventManager.OnGetCurrentTimeAsLindenSunHour += GetCurrentTimeAsLindenSunHour; @@ -414,21 +391,34 @@ namespace OpenSim.Region.CoreModules } scene.RegisterModuleInterface(this); + } - public void RegionLoaded(Scene scene) + + public void PostInitialise() { } - public void RemoveRegion(Scene scene) + public void Close() { - scene.RegisterModuleInterface(this); - scene.EventManager.OnFrame -= SunUpdate; - scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; - scene.EventManager.OnEstateToolsSunUpdate -= EstateToolsSunUpdate; - scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour; + ready = false; + + // Remove our hooks + m_scene.EventManager.OnFrame -= SunUpdate; + m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; + m_scene.EventManager.OnEstateToolsSunUpdate -= EstateToolsSunUpdate; + m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour; + } + + public string Name + { + get { return "SunModule"; } } + public bool IsSharedModule + { + get { return false; } + } #endregion #region EventManager Events diff --git a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs index 0b487ed..c2ad7b8 100644 --- a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs +++ b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs @@ -28,7 +28,6 @@ using System; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -37,8 +36,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Avatar.Vegetation { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class VegetationModule : INonSharedRegionModule, IVegetationModule + public class VegetationModule : IRegionModule, IVegetationModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -47,34 +45,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Vegetation protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.Grass, PCode.NewTree, PCode.Tree }; public PCode[] CreationCapabilities { get { return creationCapabilities; } } - public void Initialise(IConfigSource source) - { - } - - public void AddRegion(Scene scene) + public void Initialise(Scene scene, IConfigSource source) { m_scene = scene; m_scene.RegisterModuleInterface(this); } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - } public void PostInitialise() {} public void Close() {} public string Name { get { return "Vegetation Module"; } } - + public bool IsSharedModule { get { return false; } } + public SceneObjectGroup AddTree( UUID uuid, UUID groupID, Vector3 scale, Quaternion rotation, Vector3 position, Tree treeType, bool newTree) { diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs index cd3706d..3283c1f 100644 --- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs +++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs @@ -55,19 +55,17 @@ namespace OpenSim.Region.CoreModules private IWindModelPlugin m_activeWindPlugin = null; private const string m_dWindPluginName = "SimpleRandomWind"; - private string m_desiredWindPlugin = "SimpleRandomWind"; private Dictionary m_availableWindPlugins = new Dictionary(); // Simplified windSpeeds based on the fact that the client protocal tracks at a resolution of 16m private Vector2[] windSpeeds = new Vector2[16 * 16]; - private IConfig windConfig; #region IRegion Methods - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { - windConfig = config.Configs["Wind"]; - m_desiredWindPlugin = m_dWindPluginName; + IConfig windConfig = config.Configs["Wind"]; + string desiredWindPlugin = m_dWindPluginName; if (windConfig != null) { @@ -78,18 +76,10 @@ namespace OpenSim.Region.CoreModules // Determine which wind model plugin is desired if (windConfig.Contains("wind_plugin")) { - m_desiredWindPlugin = windConfig.GetString("wind_plugin"); + desiredWindPlugin = windConfig.GetString("wind_plugin"); } } - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { if (m_enabled) { m_log.InfoFormat("[WIND] Enabled with an update rate of {0} frames.", m_frameUpdateRate); @@ -105,30 +95,30 @@ namespace OpenSim.Region.CoreModules } // Check for desired plugin - if (m_availableWindPlugins.ContainsKey(m_desiredWindPlugin)) + if (m_availableWindPlugins.ContainsKey(desiredWindPlugin)) { - m_activeWindPlugin = m_availableWindPlugins[m_desiredWindPlugin]; + m_activeWindPlugin = m_availableWindPlugins[desiredWindPlugin]; - m_log.InfoFormat("[WIND] {0} plugin found, initializing.", m_desiredWindPlugin); + m_log.InfoFormat("[WIND] {0} plugin found, initializing.", desiredWindPlugin); if (windConfig != null) { m_activeWindPlugin.Initialise(); m_activeWindPlugin.WindConfig(m_scene, windConfig); } - } + } // if the plug-in wasn't found, default to no wind. if (m_activeWindPlugin == null) { - m_log.ErrorFormat("[WIND] Could not find specified wind plug-in: {0}", m_desiredWindPlugin); + m_log.ErrorFormat("[WIND] Could not find specified wind plug-in: {0}", desiredWindPlugin); m_log.ErrorFormat("[WIND] Defaulting to no wind."); } // This one puts an entry in the main help screen m_scene.AddCommand(this, String.Empty, "wind", "Usage: wind [value] - Get or Update Wind paramaters", null); - + // This one enables the ability to type just the base command without any parameters m_scene.AddCommand(this, "wind", "", "", HandleConsoleCommand); @@ -137,7 +127,7 @@ namespace OpenSim.Region.CoreModules { m_scene.AddCommand(this, String.Format("wind base wind_plugin {0}", windPlugin.Name), String.Format("{0} - {1}", windPlugin.Name, windPlugin.Description), "", HandleConsoleBaseCommand); m_scene.AddCommand(this, String.Format("wind base wind_update_rate"), "Change the wind update rate.", "", HandleConsoleBaseCommand); - + foreach (KeyValuePair kvp in windPlugin.WindParams()) { m_scene.AddCommand(this, String.Format("wind {0} {1}", windPlugin.Name, kvp.Key), String.Format("{0} : {1} - {2}", windPlugin.Name, kvp.Key, kvp.Value), "", HandleConsoleParamCommand); @@ -159,17 +149,11 @@ namespace OpenSim.Region.CoreModules m_ready = true; } - } - public void RegionLoaded(Scene scene) - { } - public void RemoveRegion(Scene scene) + public void PostInitialise() { - scene.EventManager.OnFrame -= WindUpdate; - scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion; - scene.UnregisterModuleInterface(this); } public void Close() @@ -198,6 +182,11 @@ namespace OpenSim.Region.CoreModules get { return "WindModule"; } } + public bool IsSharedModule + { + get { return false; } + } + #endregion diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs index 6bda1e9..285d36a 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs @@ -30,7 +30,6 @@ using System.Collections.Generic; using System.Drawing; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; @@ -60,8 +59,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap public face[] trns; } - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MapImageModule : IMapImageGenerator, INonSharedRegionModule + public class MapImageModule : IMapImageGenerator, IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -130,38 +128,25 @@ namespace OpenSim.Region.CoreModules.World.WorldMap #endregion - #region INonSharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource source) + public void Initialise(Scene scene, IConfigSource source) { + m_scene = scene; m_config = source; IConfig startupConfig = m_config.Configs["Startup"]; if (startupConfig.GetString("MapImageModule", "MapImageModule") != "MapImageModule") return; - } - public void AddRegion(Scene scene) - { - m_scene = scene; m_scene.RegisterModuleInterface(this); } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) + public void PostInitialise() { } - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - } - public void Close() { } @@ -171,6 +156,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap get { return "MapImageModule"; } } + public bool IsSharedModule + { + get { return false; } + } + #endregion // TODO: unused: diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs index dd33673..be46fa5 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs @@ -24,12 +24,9 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -using System; using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -41,8 +38,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.CoreModules.World.WorldMap { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MapSearchModule : ISharedRegionModule + public class MapSearchModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -50,12 +46,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap Scene m_scene = null; // only need one for communication with GridService List m_scenes = new List(); - #region ISharedRegionModule Members - public void Initialise(IConfigSource source) - { - } - - public void AddRegion(Scene scene) + #region IRegionModule Members + public void Initialise(Scene scene, IConfigSource source) { if (m_scene == null) { @@ -66,22 +58,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap scene.EventManager.OnNewClient += OnNewClient; } - public Type ReplaceableInterface - { - get { return null; } - } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - if(m_scenes.Contains(scene)) - m_scenes.Remove(scene); - scene.EventManager.OnNewClient -= OnNewClient; - } - public void PostInitialise() { } @@ -97,6 +73,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap get { return "MapSearchModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion private void OnNewClient(IClientAPI client) diff --git a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs index b0cefc3..4df9094 100644 --- a/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs +++ b/OpenSim/Region/DataSnapshot/DataSnapshotManager.cs @@ -33,7 +33,6 @@ using System.Net; using System.Reflection; using System.Xml; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -44,8 +43,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.DataSnapshot { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class DataSnapshotManager : ISharedRegionModule, IDataSnapshot + public class DataSnapshotManager : IRegionModule, IDataSnapshot { #region Class members //Information from config @@ -91,7 +89,7 @@ namespace OpenSim.Region.DataSnapshot #region IRegionModule - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { if (!m_configLoaded) { @@ -142,29 +140,24 @@ namespace OpenSim.Region.DataSnapshot return; } } - } - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void AddRegion(Scene scene) - { - if (m_enabled) - { - //Hand it the first scene, assuming that all scenes have the same BaseHTTPServer - new DataRequestHandler(scene, this); + if (m_enabled) + { + //Hand it the first scene, assuming that all scenes have the same BaseHTTPServer + new DataRequestHandler(scene, this); - m_hostname = scene.RegionInfo.ExternalHostName; - m_snapStore = new SnapshotStore(m_snapsDir, m_gridinfo, m_listener_port, m_hostname); + m_hostname = scene.RegionInfo.ExternalHostName; + m_snapStore = new SnapshotStore(m_snapsDir, m_gridinfo, m_listener_port, m_hostname); - MakeEverythingStale(); + MakeEverythingStale(); - if (m_dataServices != "" && m_dataServices != "noservices") - NotifyDataServices(m_dataServices, "online"); + if (m_dataServices != "" && m_dataServices != "noservices") + NotifyDataServices(m_dataServices, "online"); + } + } + if (m_enabled) + { m_log.Info("[DATASNAPSHOT]: Scene added to module."); m_snapStore.AddScene(scene); @@ -198,25 +191,20 @@ namespace OpenSim.Region.DataSnapshot } else { - m_log.Info("[DATASNAPSHOT]: Data snapshot disabled, not adding scene to module (or anything else)."); + m_log.Warn("[DATASNAPSHOT]: Data snapshot disabled, not adding scene to module (or anything else)."); } } - public void RegionLoaded(Scene scene) + public void Close() { + if (m_enabled && m_dataServices != "" && m_dataServices != "noservices") + NotifyDataServices(m_dataServices, "offline"); } - public void RemoveRegion(Scene scene) - { - if (m_scenes.Contains(scene)) - m_scenes.Remove(scene); - m_snapStore.RemoveScene(scene); - } - public void Close() + public bool IsSharedModule { - if (m_enabled && m_dataServices != "" && m_dataServices != "noservices") - NotifyDataServices(m_dataServices, "offline"); + get { return true; } } public string Name @@ -226,6 +214,7 @@ namespace OpenSim.Region.DataSnapshot public void PostInitialise() { + } #endregion diff --git a/OpenSim/Region/Framework/Interfaces/ICloudModule.cs b/OpenSim/Region/Framework/Interfaces/ICloudModule.cs index 879114b..f8a5bad 100644 --- a/OpenSim/Region/Framework/Interfaces/ICloudModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ICloudModule.cs @@ -28,7 +28,7 @@ namespace OpenSim.Region.Framework.Interfaces { - public interface ICloudModule : INonSharedRegionModule + public interface ICloudModule : IRegionModule { /// /// Retrieves the cloud density at the given region coordinates diff --git a/OpenSim/Region/Framework/Interfaces/IEmailModule.cs b/OpenSim/Region/Framework/Interfaces/IEmailModule.cs index bdad0b4..3a2c423 100644 --- a/OpenSim/Region/Framework/Interfaces/IEmailModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEmailModule.cs @@ -38,7 +38,7 @@ namespace OpenSim.Region.Framework.Interfaces public int numLeft; } - public interface IEmailModule : ISharedRegionModule + public interface IEmailModule : IRegionModule { void SendEmail(UUID objectID, string address, string subject, string body); Email GetNextEmail(UUID objectID, string sender, string subject); diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 347818c..890fa31 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -29,7 +29,7 @@ using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces { - public interface IEstateModule : INonSharedRegionModule + public interface IEstateModule : IRegionModule { uint GetRegionFlags(); bool IsManager(UUID avatarID); diff --git a/OpenSim/Region/Framework/Interfaces/ISunModule.cs b/OpenSim/Region/Framework/Interfaces/ISunModule.cs index 8231716..819ae11 100644 --- a/OpenSim/Region/Framework/Interfaces/ISunModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISunModule.cs @@ -29,7 +29,7 @@ using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces { - public interface ISunModule : INonSharedRegionModule + public interface ISunModule : IRegionModule { double GetSunParameter(string param); diff --git a/OpenSim/Region/Framework/Interfaces/IWindModule.cs b/OpenSim/Region/Framework/Interfaces/IWindModule.cs index 4a26a71..10ecc32 100644 --- a/OpenSim/Region/Framework/Interfaces/IWindModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IWindModule.cs @@ -29,7 +29,7 @@ using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces { - public interface IWindModule : INonSharedRegionModule + public interface IWindModule : IRegionModule { /// diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs index ec040db..cfe1278 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/IRCStackModule.cs @@ -25,11 +25,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; using System.Net; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -37,23 +35,24 @@ using OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server; namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class IRCStackModule : INonSharedRegionModule + public class IRCStackModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IRCServer m_server; // private Scene m_scene; - private int portNo; - #region Implementation of ISharedRegionModule + #region Implementation of IRegionModule - public void Initialise(IConfigSource source) + public void Initialise(Scene scene, IConfigSource source) { if (null != source.Configs["IRCd"] && source.Configs["IRCd"].GetBoolean("Enabled",false)) { - portNo = source.Configs["IRCd"].GetInt("Port",6666); + int portNo = source.Configs["IRCd"].GetInt("Port",6666); +// m_scene = scene; + m_server = new IRCServer(IPAddress.Parse("0.0.0.0"), portNo, scene); + m_server.OnNewIRCClient += m_server_OnNewIRCClient; } } @@ -69,20 +68,9 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView m_log.Info("[IRCd] Added user to Scene"); } - public void AddRegion(Scene scene) - { - if (portNo != null) - { - m_server = new IRCServer(IPAddress.Parse("0.0.0.0"), portNo, scene); - m_server.OnNewIRCClient += m_server_OnNewIRCClient; - } - } - public void RegionLoaded(Scene scene) + public void PostInitialise() { - } - public void RemoveRegion(Scene scene) - { } public void Close() @@ -95,9 +83,9 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView get { return "IRCClientStackModule"; } } - public Type ReplaceableInterface + public bool IsSharedModule { - get { return null; } + get { return false; } } #endregion diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index 23ae307..b04b076 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -38,7 +38,6 @@ using System.Collections.Generic; using System.Reflection; using OpenMetaverse; using log4net; -using Mono.Addins; using Nini.Config; using Nwc.XmlRpc; using OpenSim.Framework; @@ -54,8 +53,7 @@ using System.Text.RegularExpressions; namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class FreeSwitchVoiceModule : ISharedRegionModule, IVoiceModule + public class FreeSwitchVoiceModule : IRegionModule, IVoiceModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -110,8 +108,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice private IConfig m_config; - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { + m_scene = scene; m_config = config.Configs["FreeSwitchVoice"]; if (null == m_config) @@ -225,21 +224,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice return; } } - } - public void AddRegion(Scene scene) - { - m_scene = scene; - if (m_pluginEnabled) + if (m_pluginEnabled) { // we need to capture scene in an anonymous method // here as we need it later in the callbacks scene.EventManager.OnRegisterCaps += delegate(UUID agentID, Caps caps) - { - OnRegisterCaps(scene, agentID, caps); - }; - - + { + OnRegisterCaps(scene, agentID, caps); + }; + + try { @@ -259,53 +254,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice m_log.Error("[FreeSwitchVoice]: Certificate validation handler change not supported. You may get ssl certificate validation errors teleporting from your region to some SSL regions."); } } - + } + } + + public void PostInitialise() + { if (m_pluginEnabled) { m_log.Info("[FreeSwitchVoice] registering IVoiceModule with the scene"); - + // register the voice interface for this module, so the script engine can call us m_scene.RegisterModuleInterface(this); } } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - if (UseProxy) - { - MainServer.Instance.RemoveHTTPHandler("", String.Format("{0}/", m_freeSwitchAPIPrefix)); - } - else - { - MainServer.Instance.RemoveHTTPHandler("", String.Format("{0}/viv_get_prelogin.php", m_freeSwitchAPIPrefix)); - - MainServer.Instance.RemoveHTTPHandler("", String.Format("{0}/viv_signin.php", m_freeSwitchAPIPrefix)); - - MainServer.Instance.RemoveHTTPHandler("", String.Format("{0}/freeswitch-config", m_freeSwitchAPIPrefix)); - - MainServer.Instance.RemoveHTTPHandler("", String.Format("{0}/viv_buddy.php", m_freeSwitchAPIPrefix)); - } - scene.EventManager.OnRegisterCaps -= delegate(UUID agentID, Caps caps) - { - OnRegisterCaps(scene, agentID, caps); - }; - scene.UnregisterModuleInterface(this); - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void PostInitialise() - { - } - public void Close() { } @@ -314,6 +277,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice { get { return "FreeSwitchVoiceModule"; } } + + public bool IsSharedModule + { + get { return true; } + } // // implementation of IVoiceModule, called by osSetParcelSIPAddress script function diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs index 6769d59..3d1c346 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementModule.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -38,7 +38,6 @@ using System.Threading; using OpenMetaverse; -using Mono.Addins; using Nini.Config; using OpenSim; @@ -51,8 +50,7 @@ using log4net; namespace OpenSim.Region.OptionalModules.ContentManagement { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class ContentManagementModule : ISharedRegionModule + public class ContentManagementModule : IRegionModule { #region Static Fields @@ -62,20 +60,22 @@ namespace OpenSim.Region.OptionalModules.ContentManagement #region Fields - private bool initialised = false; - private CMController m_control = null; - private bool m_enabled = false; - private CMModel m_model = null; - private bool m_posted = false; - private CMView m_view = null; - private string databaseDir = "./"; - private string database = "FileSystemDatabase"; - private int channel = 345; + bool initialised = false; + CMController m_control = null; + bool m_enabled = false; + CMModel m_model = null; + bool m_posted = false; + CMView m_view = null; #endregion Fields #region Public Properties + public bool IsSharedModule + { + get { return true; } + } + public string Name { get { return "ContentManagementModule"; } @@ -89,8 +89,11 @@ namespace OpenSim.Region.OptionalModules.ContentManagement { } - public void Initialise(IConfigSource source) + public void Initialise(Scene scene, IConfigSource source) { + string databaseDir = "./"; + string database = "FileSystemDatabase"; + int channel = 345; try { if (source.Configs["CMS"] == null) @@ -112,15 +115,13 @@ namespace OpenSim.Region.OptionalModules.ContentManagement m_log.ErrorFormat("[Content Management]: Exception thrown while reading parameters from configuration file. Message: " + e); m_enabled = false; } - } - public void AddRegion(Scene scene) - { if (!m_enabled) { m_log.Info("[Content Management]: Content Management System is not Enabled."); return; } + lock (this) { if (!initialised) //only init once @@ -141,18 +142,6 @@ namespace OpenSim.Region.OptionalModules.ContentManagement } } } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - } - - public Type ReplaceableInterface - { - get { return null; } - } public void PostInitialise() { diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs index f24bcdc..4521f8e 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs @@ -38,7 +38,6 @@ using System.Security.Policy; using System.Text; using log4net; using Microsoft.CSharp; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -47,8 +46,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class MRMModule : INonSharedRegionModule, IMRMModule + public class MRMModule : IRegionModule, IMRMModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; @@ -64,14 +62,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule private IConfig m_config; - private bool m_hidden = true; - public void RegisterExtension(T instance) { m_extensions[typeof (T)] = instance; } - public void Initialise(IConfigSource source) + public void Initialise(Scene scene, IConfigSource source) { if (source.Configs["MRM"] != null) { @@ -80,10 +76,19 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule if (source.Configs["MRM"].GetBoolean("Enabled", false)) { m_log.Info("[MRM] Enabling MRM Module"); - + m_scene = scene; + // when hidden, we don't listen for client initiated script events // only making the MRM engine available for region modules - m_hidden = source.Configs["MRM"].GetBoolean("Hidden", false); + if (!source.Configs["MRM"].GetBoolean("Hidden", false)) + { + scene.EventManager.OnRezScript += EventManager_OnRezScript; + scene.EventManager.OnStopScript += EventManager_OnStopScript; + } + + scene.EventManager.OnFrame += EventManager_OnFrame; + + scene.RegisterModuleInterface(this); } else { @@ -96,39 +101,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule } } - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) - { - m_scene = scene; - if (!m_hidden) - { - scene.EventManager.OnRezScript += EventManager_OnRezScript; - scene.EventManager.OnStopScript += EventManager_OnStopScript; - } - scene.EventManager.OnFrame += EventManager_OnFrame; - - scene.RegisterModuleInterface(this); - } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - if (!m_hidden) - { - scene.EventManager.OnRezScript -= EventManager_OnRezScript; - scene.EventManager.OnStopScript -= EventManager_OnStopScript; - } - scene.EventManager.OnFrame -= EventManager_OnFrame; - - scene.UnregisterModuleInterface(this); - } - void EventManager_OnStopScript(uint localID, UUID itemID) { if (m_scripts.ContainsKey(itemID)) @@ -330,6 +302,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule mmb.InitMiniModule(world, host, itemID); } + public void PostInitialise() + { + + } + public void Close() { foreach (KeyValuePair pair in m_scripts) @@ -343,6 +320,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule get { return "MiniRegionModule"; } } + public bool IsSharedModule + { + get { return false; } + } + /// /// Stolen from ScriptEngine Common /// diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 999756a..c653e98 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -100,10 +100,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady if (!m_enabled) return; - scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; - scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; + m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; + m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; - scene = null; + m_scene = null; } public void Close() diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index df01938..44c9ada 100644 --- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -58,7 +58,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms public void RemoveRegion(Scene scene) { - scene.UnregisterModuleInterface(this); } public void RegionLoaded(Scene scene) diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs index f2a0e53..d18ac0a 100644 --- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcGridRouterModule.cs @@ -30,7 +30,6 @@ using System.Collections.Generic; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; @@ -50,8 +49,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule public string uri; } - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class XmlRpcGridRouter : INonSharedRegionModule, IXmlRpcRouter + public class XmlRpcGridRouter : IRegionModule, IXmlRpcRouter { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -61,7 +59,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule private bool m_Enabled = false; private string m_ServerURI = String.Empty; - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { IConfig startupConfig = config.Configs["Startup"]; if (startupConfig == null) @@ -77,26 +75,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule return; } + scene.RegisterModuleInterface(this); m_Enabled = true; } } - public void AddRegion(Scene scene) + public void PostInitialise() { - scene.RegisterModuleInterface(this); - } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - } - - public Type ReplaceableInterface - { - get { return null; } } public void Close() @@ -108,6 +93,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcGridRouterModule get { return "XmlRpcGridRouterModule"; } } + public bool IsSharedModule + { + get { return false; } + } + public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) { if (!m_Channels.ContainsKey(itemID)) diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs index 4d39345..32659c8 100644 --- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs @@ -29,7 +29,6 @@ using System; using System.Reflection; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; @@ -40,12 +39,11 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class XmlRpcRouter : INonSharedRegionModule, IXmlRpcRouter + public class XmlRpcRouter : IRegionModule, IXmlRpcRouter { //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private bool m_enabled = false; - public void Initialise(IConfigSource config) + + public void Initialise(Scene scene, IConfigSource config) { IConfig startupConfig = config.Configs["Startup"]; if (startupConfig == null) @@ -54,25 +52,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule if (startupConfig.GetString("XmlRpcRouterModule", "XmlRpcRouterModule") == "XmlRpcRouterModule") { - m_enabled = true; + scene.RegisterModuleInterface(this); } } - public void AddRegion(Scene scene) - { - scene.RegisterModuleInterface(this); - } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - } - public Type ReplaceableInterface + public void PostInitialise() { - get { return null; } } public void Close() @@ -84,6 +69,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule get { return "XmlRpcRouterModule"; } } + public bool IsSharedModule + { + get { return false; } + } + public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) { scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] {uri}); diff --git a/OpenSim/Region/OptionalModules/ServiceConnectorsIn/Freeswitch/FreeswitchServiceInConnectorModule.cs b/OpenSim/Region/OptionalModules/ServiceConnectorsIn/Freeswitch/FreeswitchServiceInConnectorModule.cs index 801f1f8..97fa63c 100644 --- a/OpenSim/Region/OptionalModules/ServiceConnectorsIn/Freeswitch/FreeswitchServiceInConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/ServiceConnectorsIn/Freeswitch/FreeswitchServiceInConnectorModule.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Freeswitch private IConfigSource m_Config; bool m_Registered = false; - #region ISharedRegionModule interface + #region IRegionModule interface public void Initialise(IConfigSource config) { diff --git a/OpenSim/Region/OptionalModules/SvnSerialiser/SvnBackupModule.cs b/OpenSim/Region/OptionalModules/SvnSerialiser/SvnBackupModule.cs index fa5878d..3490a8b 100644 --- a/OpenSim/Region/OptionalModules/SvnSerialiser/SvnBackupModule.cs +++ b/OpenSim/Region/OptionalModules/SvnSerialiser/SvnBackupModule.cs @@ -31,7 +31,6 @@ using System.IO; using System.Reflection; using System.Timers; using log4net; -using Mono.Addins; using Nini.Config; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.CoreModules.World.Serialiser; @@ -43,8 +42,7 @@ using Slash = System.IO.Path; namespace OpenSim.Region.Modules.SvnSerialiser { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SvnBackupModule : ISharedRegionModule + public class SvnBackupModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -202,9 +200,9 @@ namespace OpenSim.Region.Modules.SvnSerialiser #endregion - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource source) + public void Initialise(Scene scene, IConfigSource source) { m_scenes = new List(); m_timer = new Timer(); @@ -227,10 +225,7 @@ namespace OpenSim.Region.Modules.SvnSerialiser catch (Exception) { } - } - public void AddRegion(Scene scene) - { lock (m_scenes) { m_scenes.Add(scene); @@ -241,18 +236,6 @@ namespace OpenSim.Region.Modules.SvnSerialiser scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; } } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - } - - public Type ReplaceableInterface - { - get { return null; } - } public void PostInitialise() { @@ -294,6 +277,11 @@ namespace OpenSim.Region.Modules.SvnSerialiser get { return "SvnBackupModule"; } } + public bool IsSharedModule + { + get { return true; } + } + #endregion private void EventManager_OnPluginConsole(string[] args) diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index 521d01a..ac39a53 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -25,11 +25,9 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; using System.Collections.Generic; using System.Threading; using OpenMetaverse; -using Mono.Addins; using Nini.Config; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -39,8 +37,7 @@ using Timer=System.Timers.Timer; namespace OpenSim.Region.OptionalModules.World.NPC { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class NPCModule : ISharedRegionModule, INPCModule + public class NPCModule : IRegionModule, INPCModule { // private const bool m_enabled = false; @@ -137,13 +134,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC } - public void Initialise(IConfigSource source) + public void Initialise(Scene scene, IConfigSource source) { m_createMutex = new Mutex(false); m_timer = new Timer(500); m_timer.Elapsed += m_timer_Elapsed; m_timer.Start(); + + scene.RegisterModuleInterface(this); } void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) @@ -174,19 +173,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC } } - public void AddRegion(Scene scene) - { - scene.RegisterModuleInterface(this); - } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - } - public void PostInitialise() { } @@ -200,9 +186,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC get { return "NPCModule"; } } - public Type ReplaceableInterface + public bool IsSharedModule { - get { return null; } - } + get { return true; } + } } } diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs index b59d07a..e3fbb6e 100644 --- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs +++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs @@ -31,7 +31,6 @@ using System.Reflection; using System.Timers; using OpenMetaverse; using log4net; -using Mono.Addins; using Nini.Config; using OpenSim.Framework; using OpenSim.Region.CoreModules.Framework.InterfaceCommander; @@ -47,8 +46,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator /// /// Version 2.02 - Still hacky /// - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule, IVegetationModule + public class TreePopulatorModule : IRegionModule, ICommandableModule, IVegetationModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private readonly Commander m_commander = new Commander("tree"); @@ -170,10 +168,15 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator #endregion - #region ISharedRegionModule Members + #region IRegionModule Members - public void Initialise(IConfigSource config) + public void Initialise(Scene scene, IConfigSource config) { + + m_scene = scene; + m_scene.RegisterModuleInterface(this); + m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; + // ini file settings try { @@ -193,18 +196,12 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator m_log.Debug("[TREES]: ini failure for update_rate - using default"); } - m_log.Debug("[TREES]: Initialised tree module"); - } - - public void AddRegion(Scene scene) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; InstallCommands(); + + m_log.Debug("[TREES]: Initialised tree module"); } - public void RegionLoaded(Scene scene) + public void PostInitialise() { ReloadCopse(); if (m_copse.Count > 0) @@ -214,17 +211,6 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator activeizeTreeze(true); } - public void RemoveRegion(Scene scene) - { - scene.UnregisterModuleInterface(this); - scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole; - } - - public Type ReplaceableInterface - { - get { return null; } - } - public void Close() { } @@ -234,6 +220,11 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator get { return "TreePopulatorModule"; } } + public bool IsSharedModule + { + get { return false; } + } + #endregion //-------------------------------------------------------------- diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index 9b53d06..a03cc4c 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -34,7 +34,6 @@ using System.Reflection; using System.Text; using System.Threading; using log4net; -using Mono.Addins; using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -53,8 +52,7 @@ using OSDMap = OpenMetaverse.StructuredData.OSDMap; namespace OpenSim.Region.UserStatistics { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class WebStatsModule : ISharedRegionModule + public class WebStatsModule : IRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -72,7 +70,7 @@ namespace OpenSim.Region.UserStatistics private string m_loglines = String.Empty; private volatile int lastHit = 12000; - public virtual void Initialise(IConfigSource config) + public virtual void Initialise(Scene scene, IConfigSource config) { IConfig cnfg; try @@ -84,17 +82,11 @@ namespace OpenSim.Region.UserStatistics { enabled = false; } - } - - public Type ReplaceableInterface - { - get { return null; } - } - - public void AddRegion(Scene scene) - { + if (!enabled) + { return; + } lock (m_scene) { @@ -138,7 +130,7 @@ namespace OpenSim.Region.UserStatistics MainServer.Instance.AddHTTPHandler("/SStats/", HandleStatsRequest); MainServer.Instance.AddHTTPHandler("/CAPS/VS/", HandleUnknownCAPSRequest); } - + m_scene.Add(scene); if (m_simstatsCounters.ContainsKey(scene.RegionInfo.RegionID)) m_simstatsCounters.Remove(scene.RegionInfo.RegionID); @@ -148,14 +140,6 @@ namespace OpenSim.Region.UserStatistics } } - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - } - public void ReceiveClassicSimStatsPacket(SimStats stats) { if (!enabled) @@ -324,6 +308,11 @@ namespace OpenSim.Region.UserStatistics get { return "ViewerStatsModule"; } } + public bool IsSharedModule + { + get { return true; } + } + public void OnRegisterCaps(UUID agentID, Caps caps) { m_log.DebugFormat("[VC]: OnRegisterCaps: agentID {0} caps {1}", agentID, caps); diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index 20f2bca..b13e8dd 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -161,11 +161,10 @@ namespace OpenSim.Tests.Common.Setup capsModule.Initialise(new IniConfigSource()); testScene.AddRegionModule(capsModule.Name, capsModule); capsModule.AddRegion(testScene); - - INonSharedRegionModule godsModule = new GodsModule(); - godsModule.Initialise(new IniConfigSource()); - testScene.AddRegionModule(godsModule.Name, godsModule); - godsModule.AddRegion(testScene); + + IRegionModule godsModule = new GodsModule(); + godsModule.Initialise(testScene, new IniConfigSource()); + testScene.AddModule(godsModule.Name, godsModule); realServices = realServices.ToLower(); // IConfigSource config = new IniConfigSource(); -- cgit v1.1 From 44c86cedcf8ddba1ca4c9e3ff4f1e39ceb59be06 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 29 Jan 2010 07:42:45 +0000 Subject: Resolve one more conflict I overlooked --- .../CoreModules/Scripting/WorldComm/WorldCommModule.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index 93aa88c..60df2e7 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -120,20 +120,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (maxlisteners < 1) maxlisteners = int.MaxValue; if (maxhandles < 1) maxhandles = int.MaxValue; -<<<<<<< HEAD:OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs - m_listenerManager = new ListenerManager(maxlisteners, maxhandles); - m_pendingQ = new Queue(); - m_pending = Queue.Synchronized(m_pendingQ); - } - - public void PostInitialise() - { - } - - public void AddRegion(Scene scene) - { -======= ->>>>>>> ec3c31e... Updates all IRegionModules to the new style region modules.:OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs m_scene = scene; m_scene.RegisterModuleInterface(this); m_listenerManager = new ListenerManager(maxlisteners, maxhandles); -- cgit v1.1 From 9e37d246240db077fe7a4e1389f5220d72d6542c Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 29 Jan 2010 11:47:45 +0000 Subject: Prevent empty ObjectProperties packets being sent --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 64e45d0..1496f5c 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3885,6 +3885,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_propertiesPacketTimer.Stop(); + if (m_propertiesBlocks.Count == 0) + return; + proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; int index = 0; -- cgit v1.1 From 0c5850237ec68158743117933d2ddd6e7df62c28 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 29 Jan 2010 16:50:00 +0000 Subject: Small fix for a spurious exception --- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs index e4296ef..1cff0eb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs +++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs @@ -76,7 +76,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (EntityBase e in m_presence.Scene.Entities) { - if (e is SceneObjectGroup) + if (e != null && e is SceneObjectGroup) m_pendingObjects.Enqueue((SceneObjectGroup)e); } } -- cgit v1.1 From 6478617c932e87bf091266dba2db4d73fcdd046f Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 2 Feb 2010 03:49:00 +0000 Subject: Revert "improve locking of m_items in SceneObjectPartInventory" This reverts commit 968b9e160d70568fbdea5b190d1386e9431316e3. --- .../Framework/Scenes/SceneObjectPartInventory.cs | 218 ++++++++------------- 1 file changed, 85 insertions(+), 133 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 87c1a95..b37e1a2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -44,8 +44,6 @@ namespace OpenSim.Region.Framework.Scenes { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - static System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - private string m_inventoryFileName = String.Empty; private int m_inventoryFileNameSerial = 0; @@ -272,12 +270,8 @@ namespace OpenSim.Region.Framework.Scenes if (stateSource == 1 && // Prim crossing m_part.ParentGroup.Scene.m_trustBinaries) { - lock (m_items) - { - m_items[item.ItemID].PermsMask = 0; - m_items[item.ItemID].PermsGranter = UUID.Zero; - } - + m_items[item.ItemID].PermsMask = 0; + m_items[item.ItemID].PermsGranter = UUID.Zero; m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); m_part.ParentGroup.AddActiveScriptCount(1); @@ -285,38 +279,33 @@ namespace OpenSim.Region.Framework.Scenes return; } - m_part.ParentGroup.Scene.AssetService.Get( - item.AssetID.ToString(), this, delegate(string id, object sender, AssetBase asset) - { - if (null == asset) - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", - item.Name, item.ItemID, m_part.AbsolutePosition, - m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); - } - else - { - if (m_part.ParentGroup.m_savedScriptState != null) - RestoreSavedScriptState(item.OldItemID, item.ItemID); - - lock (m_items) - { - m_items[item.ItemID].PermsMask = 0; - m_items[item.ItemID].PermsGranter = UUID.Zero; - } - - string script = Utils.BytesToString(asset.Data); - m_part.ParentGroup.Scene.EventManager.TriggerRezScript( - m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); - m_part.ParentGroup.AddActiveScriptCount(1); - m_part.ScheduleFullUpdate(); - } - } - ); + m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString(), this, delegate(string id, object sender, AssetBase asset) + { + if (null == asset) + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", + item.Name, item.ItemID, m_part.AbsolutePosition, + m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); + } + else + { + if (m_part.ParentGroup.m_savedScriptState != null) + RestoreSavedScriptState(item.OldItemID, item.ItemID); + m_items[item.ItemID].PermsMask = 0; + m_items[item.ItemID].PermsGranter = UUID.Zero; + string script = Utils.BytesToString(asset.Data); + m_part.ParentGroup.Scene.EventManager.TriggerRezScript( + m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); + m_part.ParentGroup.AddActiveScriptCount(1); + m_part.ScheduleFullUpdate(); + } + }); } - } + } + + static System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); private void RestoreSavedScriptState(UUID oldID, UUID newID) { @@ -408,15 +397,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) { - bool scriptPresent = false; - - lock (m_items) - { - if (m_items.ContainsKey(itemId)) - scriptPresent = true; - } - - if (scriptPresent) + if (m_items.ContainsKey(itemId)) { if (!sceneObjectBeingDeleted) m_part.RemoveScriptEvents(itemId); @@ -488,13 +469,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) { - List il; - - lock (m_items) - { - il = new List(m_items.Values); - } - + List il = new List(m_items.Values); foreach (TaskInventoryItem i in il) { if (i.Name == item.Name) @@ -576,9 +551,7 @@ namespace OpenSim.Region.Framework.Scenes public TaskInventoryItem GetInventoryItem(UUID itemId) { TaskInventoryItem item; - - lock (m_items) - m_items.TryGetValue(itemId, out item); + m_items.TryGetValue(itemId, out item); return item; } @@ -904,61 +877,54 @@ namespace OpenSim.Region.Framework.Scenes { uint mask=0x7fffffff; - lock (m_items) + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) + if (item.InvType != (int)InventoryType.Object) { - if (item.InvType != (int)InventoryType.Object) - { - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) - mask &= ~((uint)PermissionMask.Copy >> 13); - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) - mask &= ~((uint)PermissionMask.Transfer >> 13); - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) - mask &= ~((uint)PermissionMask.Modify >> 13); - } - else - { - if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) - mask &= ~((uint)PermissionMask.Copy >> 13); - if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) - mask &= ~((uint)PermissionMask.Transfer >> 13); - if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) - mask &= ~((uint)PermissionMask.Modify >> 13); - } - - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - mask &= ~(uint)PermissionMask.Copy; - if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) - mask &= ~(uint)PermissionMask.Transfer; - if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) - mask &= ~(uint)PermissionMask.Modify; + if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) + mask &= ~((uint)PermissionMask.Copy >> 13); + if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) + mask &= ~((uint)PermissionMask.Transfer >> 13); + if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) + mask &= ~((uint)PermissionMask.Modify >> 13); + } + else + { + if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) + mask &= ~((uint)PermissionMask.Copy >> 13); + if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) + mask &= ~((uint)PermissionMask.Transfer >> 13); + if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) + mask &= ~((uint)PermissionMask.Modify >> 13); } + + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + mask &= ~(uint)PermissionMask.Copy; + if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) + mask &= ~(uint)PermissionMask.Transfer; + if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) + mask &= ~(uint)PermissionMask.Modify; } - return mask; } public void ApplyNextOwnerPermissions() { - lock (m_items) + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) + if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) { - if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) - { - if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Copy; - if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; - if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Modify; - item.CurrentPermissions |= 8; - } - item.CurrentPermissions &= item.NextPermissions; - item.BasePermissions &= item.NextPermissions; - item.EveryonePermissions &= item.NextPermissions; + if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Copy; + if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; + if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Modify; + item.CurrentPermissions |= 8; } + item.CurrentPermissions &= item.NextPermissions; + item.BasePermissions &= item.NextPermissions; + item.EveryonePermissions &= item.NextPermissions; } m_part.TriggerScriptChangedEvent(Changed.OWNER); @@ -966,29 +932,22 @@ namespace OpenSim.Region.Framework.Scenes public void ApplyGodPermissions(uint perms) { - lock (m_items) + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) - { - item.CurrentPermissions = perms; - item.BasePermissions = perms; - } + item.CurrentPermissions = perms; + item.BasePermissions = perms; } } public bool ContainsScripts() { - lock (m_items) + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) + if (item.InvType == (int)InventoryType.LSL) { - if (item.InvType == (int)InventoryType.LSL) - { - return true; - } + return true; } } - return false; } @@ -996,11 +955,8 @@ namespace OpenSim.Region.Framework.Scenes { List ret = new List(); - lock (m_items) - { - foreach (TaskInventoryItem item in m_items.Values) - ret.Add(item.ItemID); - } + foreach (TaskInventoryItem item in m_items.Values) + ret.Add(item.ItemID); return ret; } @@ -1013,30 +969,26 @@ namespace OpenSim.Region.Framework.Scenes if (engines == null) // No engine at all return ret; - lock (m_items) + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) + if (item.InvType == (int)InventoryType.LSL) { - if (item.InvType == (int)InventoryType.LSL) + foreach (IScriptModule e in engines) { - foreach (IScriptModule e in engines) + if (e != null) { - if (e != null) + string n = e.GetXMLState(item.ItemID); + if (n != String.Empty) { - string n = e.GetXMLState(item.ItemID); - if (n != String.Empty) - { - if (!ret.ContainsKey(item.ItemID)) - ret[item.ItemID] = n; - break; - } + if (!ret.ContainsKey(item.ItemID)) + ret[item.ItemID] = n; + break; } } } } } - return ret; } } -} \ No newline at end of file +} -- cgit v1.1 From 8c2061029331e323b5c1c0414bbda417cb6c4674 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Tue, 2 Feb 2010 13:28:42 -0500 Subject: AngMotor update 1 --- OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs | 203 ++++++++++++++-------- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 19 +- 2 files changed, 143 insertions(+), 79 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs index 14d5caa..c03e381 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs @@ -108,13 +108,14 @@ namespace OpenSim.Region.Physics.OdePlugin //Angular properties private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - private int m_angularMotorApply = 0; // application frame counter - private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity - private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate - private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate - private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate + + private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL + private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL + private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL + + private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor +// private Vector3 m_angObjectVel = Vector3.Zero; // current body angular velocity private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body - // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body //Deflection properties // private float m_angularDeflectionEfficiency = 0; @@ -227,7 +228,7 @@ namespace OpenSim.Region.Physics.OdePlugin break; case Vehicle.ANGULAR_MOTOR_DIRECTION: m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotorApply = 10; + UpdateAngDecay(); break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); @@ -260,7 +261,7 @@ namespace OpenSim.Region.Physics.OdePlugin if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; - m_angularMotorApply = 10; + UpdateAngDecay(); break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -310,6 +311,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_linearMotorTimescale = 1000; m_linearMotorDecayTimescale = 120; m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; m_angularMotorTimescale = 1000; m_angularMotorDecayTimescale = 120; m_VhoverHeight = 0; @@ -336,6 +338,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_linearMotorTimescale = 1; m_linearMotorDecayTimescale = 60; m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; m_angularMotorTimescale = 1; m_angularMotorDecayTimescale = 0.8f; m_VhoverHeight = 0; @@ -363,6 +366,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_linearMotorTimescale = 5; m_linearMotorDecayTimescale = 60; m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; m_VhoverHeight = 0; @@ -391,6 +395,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_linearMotorTimescale = 2; m_linearMotorDecayTimescale = 60; m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; m_VhoverHeight = 0; @@ -417,6 +422,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_linearMotorTimescale = 5; m_linearMotorDecayTimescale = 60; m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; m_angularMotorTimescale = 6; m_angularMotorDecayTimescale = 10; m_VhoverHeight = 5; @@ -468,8 +474,8 @@ namespace OpenSim.Region.Physics.OdePlugin m_lLinObjectVel = Vector3.Zero; m_wLinObjectVel = Vector3.Zero; m_angularMotorDirection = Vector3.Zero; - m_angularMotorVelocity = Vector3.Zero; - m_lastAngularVelocity = Vector3.Zero; + m_lastAngularVelocity = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; } private void UpdateLinDecay() @@ -611,54 +617,62 @@ namespace OpenSim.Region.Physics.OdePlugin d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); //if(frcount == 0) Console.WriteLine("Grav {0}", grav); } // end MoveLinear() + + private void UpdateAngDecay() + { + if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X; + if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y; + if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z; + } // else let the motor decay on its own private void MoveAngular(float pTimestep) { /* - private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - private int m_angularMotorApply = 0; // application frame counter - private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) - private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate - private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate - private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate - private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body + private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor + + private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL + private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL + private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL + + private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor + private Vector3 m_angObjectVel = Vector3.Zero; // what was last applied to body */ //if(frcount == 0) Console.WriteLine("MoveAngular "); +//#### // Get what the body is doing, this includes 'external' influences - d.Vector3 angularVelocity = d.BodyGetAngularVel(Body); - // Vector3 angularVelocity = Vector3.Zero; + d.Vector3 angularObjectVel = d.BodyGetAngularVel(Body); + Vector3 angObjectVel = new Vector3(angularObjectVel.X, angularObjectVel.Y, angularObjectVel.Z); +//if(frcount == 0) Console.WriteLine("V0 = {0}", angObjectVel); +// Vector3 FrAaccel = m_lastAngularVelocity - angObjectVel; +// Vector3 initavel = angObjectVel; + // Decay Angular Motor + if (m_angularMotorDecayTimescale < 300.0f) + { + float decayfactor = m_angularMotorDecayTimescale/pTimestep; + Vector3 decayAmount = (m_angularMotorDVel/decayfactor); + m_angularMotorDVel -= decayAmount; - if (m_angularMotorApply > 0) - { - // ramp up to new value - // current velocity += error / ( time to get there / step interval ) - // requested speed - last motor speed - m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); - m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); - m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); - - m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected - // velocity may still be acheived. - } - else - { - // no motor recently applied, keep the body velocity - /* m_angularMotorVelocity.X = angularVelocity.X; - m_angularMotorVelocity.Y = angularVelocity.Y; - m_angularMotorVelocity.Z = angularVelocity.Z; */ - - // and decay the velocity - m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); - } // end motor section - + if (m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) + { + m_angularMotorDVel = Vector3.Zero; + } + else + { + if (Math.Abs(m_angularMotorDVel.X) < Math.Abs(angObjectVel.X)) angObjectVel.X = m_angularMotorDVel.X; + if (Math.Abs(m_angularMotorDVel.Y) < Math.Abs(angObjectVel.Y)) angObjectVel.Y = m_angularMotorDVel.Y; + if (Math.Abs(m_angularMotorDVel.Z) < Math.Abs(angObjectVel.Z)) angObjectVel.Z = m_angularMotorDVel.Z; + } + } // end decay angular motor +//if(frcount == 0) Console.WriteLine("MotorDvel {0} Obj {1}", m_angularMotorDVel, angObjectVel); +//if(frcount == 0) Console.WriteLine("VA = {0}", angObjectVel); // Vertical attractor section Vector3 vertattr = Vector3.Zero; if(m_verticalAttractionTimescale < 300) { - float VAservo = 0.0167f / (m_verticalAttractionTimescale * pTimestep); + float VAservo = 1.0f / (m_verticalAttractionTimescale * pTimestep); // get present body rotation d.Quaternion rot = d.BodyGetQuaternion(Body); Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); @@ -670,38 +684,88 @@ namespace OpenSim.Region.Physics.OdePlugin // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. + if (verterr.Z < 0.0f) - { + { // Defelction from vertical exceeds 90-degrees. This method will ensure stable return to + // vertical, BUT for some reason a z-rotation is imparted to the object. TBI. +//Console.WriteLine("InvertFlip"); verterr.X = 2.0f - verterr.X; verterr.Y = 2.0f - verterr.Y; } - // Error is 0 (no error) to +/- 2 (max error) - // scale it by VAservo - verterr = verterr * VAservo; + verterr *= 0.5f; + // verterror is 0 (no error) to +/- 1 (max error at 180-deg tilt) + + if ((!angObjectVel.ApproxEquals(Vector3.Zero, 0.001f)) || (verterr.Z < 0.49f)) + { +//if(frcount == 0) + // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so + // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. + vertattr.X = verterr.Y; + vertattr.Y = - verterr.X; + vertattr.Z = 0f; //if(frcount == 0) Console.WriteLine("VAerr=" + verterr); - - // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so - // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. - vertattr.X = verterr.Y; - vertattr.Y = - verterr.X; - vertattr.Z = 0f; - - // scaling appears better usingsquare-law - float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); - vertattr.X += bounce * angularVelocity.X; - vertattr.Y += bounce * angularVelocity.Y; - + + // scaling appears better usingsquare-law + float damped = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency; + float bounce = 1.0f - damped; + // 0 = crit damp, 1 = bouncy + float oavz = angObjectVel.Z; // retain z velocity + angObjectVel = (angObjectVel + (vertattr * VAservo * 0.0333f)) * bounce; // The time-scaled correction, which sums, therefore is bouncy + angObjectVel = angObjectVel + (vertattr * VAservo * 0.0667f * damped); // damped, good @ < 90. + angObjectVel.Z = oavz; +//if(frcount == 0) Console.WriteLine("VA+"); +//Console.WriteLine("VAttr {0} OAvel {1}", vertattr, angObjectVel); + } + else + { + // else error is very small + angObjectVel.X = 0f; + angObjectVel.Y = 0f; +//if(frcount == 0) Console.WriteLine("VA0"); + } } // else vertical attractor is off +//if(frcount == 0) Console.WriteLine("V1 = {0}", angObjectVel); + + if ( (! m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! angObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) + { // if motor or object have motion + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + + if (m_angularMotorTimescale < 300.0f) + { + Vector3 attack_error = m_angularMotorDVel - angObjectVel; + float angfactor = m_angularMotorTimescale/pTimestep; + Vector3 attackAmount = (attack_error/angfactor); + angObjectVel += attackAmount; +//if(frcount == 0) Console.WriteLine("Accel {0} Attk {1}",FrAaccel, attackAmount); +//if(frcount == 0) Console.WriteLine("V2+= {0}", angObjectVel); + } + + if (m_angularFrictionTimescale.X < 300.0f) + { + float fricfactor = m_angularFrictionTimescale.X / pTimestep; + angObjectVel.X -= angObjectVel.X / fricfactor; + } + if (m_angularFrictionTimescale.Y < 300.0f) + { + float fricfactor = m_angularFrictionTimescale.Y / pTimestep; + angObjectVel.Y -= angObjectVel.Y / fricfactor; + } + if (m_angularFrictionTimescale.Z < 300.0f) + { + float fricfactor = m_angularFrictionTimescale.Z / pTimestep; + angObjectVel.Z -= angObjectVel.Z / fricfactor; + Console.WriteLine("z fric"); + } + } // else no signif. motion - // m_lastVertAttractor = vertattr; - +//if(frcount == 0) Console.WriteLine("Dmotor {0} Obj {1}", m_angularMotorDVel, angObjectVel); // Bank section tba // Deflection section tba +//if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); - // Sum velocities - m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // tba: + bank + deflection - - if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) + m_lastAngularVelocity = angObjectVel; +/* + if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.0001f)) { if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); } @@ -709,13 +773,12 @@ namespace OpenSim.Region.Physics.OdePlugin { m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. } - - // apply friction - Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); - m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; - + */ // Apply to the body +// Vector3 aInc = m_lastAngularVelocity - initavel; +//if(frcount == 0) Console.WriteLine("Inc {0}", aInc); d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); +//if(frcount == 0) Console.WriteLine("V4 = {0}", m_lastAngularVelocity); } //end MoveAngular } diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 29a3dd9..8502aef 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -2593,14 +2593,14 @@ Console.WriteLine(" JointCreateFixed"); { get { - Vector3 pv = Vector3.Zero; +/* Vector3 pv = Vector3.Zero; if (_zeroFlag) return pv; m_lastUpdateSent = false; if (m_rotationalVelocity.ApproxEquals(pv, 0.2f)) return pv; - +*/ return m_rotationalVelocity; } set @@ -2827,14 +2827,15 @@ Console.WriteLine(" JointCreateFixed"); _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); - if (_velocity.ApproxEquals(pv, 0.5f)) - { - m_rotationalVelocity = pv; - } - else - { +// if (_velocity.ApproxEquals(pv, 0.5f)) ???? Disregard rotational vel if lin vel is < 0.5 ????? +// { +// m_rotationalVelocity = pv;/ + +// } +// else +// { m_rotationalVelocity = new Vector3(rotvel.X, rotvel.Y, rotvel.Z); - } +// } //m_log.Debug("ODE: " + m_rotationalVelocity.ToString()); _orientation.X = ori.X; -- cgit v1.1 From 48134af6162249885740bad80a6b1bbb618bbc6e Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Wed, 3 Feb 2010 16:20:13 -0500 Subject: Motor angular decay fix. --- OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs index c03e381..4eb3313 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs @@ -646,12 +646,15 @@ namespace OpenSim.Region.Physics.OdePlugin //if(frcount == 0) Console.WriteLine("V0 = {0}", angObjectVel); // Vector3 FrAaccel = m_lastAngularVelocity - angObjectVel; // Vector3 initavel = angObjectVel; - // Decay Angular Motor + // Decay Angular Motor 1. In SL this also depends on attack rate! decay ~= 23/Attack. + float atk_decayfactor = 23.0f / (m_angularMotorTimescale * pTimestep); + m_angularMotorDVel -= m_angularMotorDVel / atk_decayfactor; + // Decay Angular Motor 2. if (m_angularMotorDecayTimescale < 300.0f) { - float decayfactor = m_angularMotorDecayTimescale/pTimestep; - Vector3 decayAmount = (m_angularMotorDVel/decayfactor); - m_angularMotorDVel -= decayAmount; + float decayfactor = m_angularMotorDecayTimescale/pTimestep; // df = Dec / pts + Vector3 decayAmount = (m_angularMotorDVel/decayfactor); // v-da = v-Dvel / df = v-Dvel * pts / Dec + m_angularMotorDVel -= decayAmount; // v-Dvel = v-Dvel - (v-Dvel / df = v-Dvel * pts / Dec) if (m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) { -- cgit v1.1 From ae9362636e1a95c32f7bcf1225e939b44c37a4a0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 4 Feb 2010 17:00:16 +0000 Subject: Line endings cleanup --- .../Framework/Scenes/SceneCommunicationService.cs | 72 +++++++++++----------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 6a3c386..545183b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -699,42 +699,42 @@ namespace OpenSim.Region.Framework.Scenes { m_log.DebugFormat( "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation {0} within {1}", - position, m_regionInfo.RegionName); - - // Teleport within the same region - if (IsOutsideRegion(avatar.Scene, position) || position.Z < 0) - { - Vector3 emergencyPos = new Vector3(128, 128, 128); - - m_log.WarnFormat( - "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", - position, avatar.Name, avatar.UUID, emergencyPos); - position = emergencyPos; - } - - Vector3 currentPos = avatar.AbsolutePosition; - ILandObject srcLand = m_scene.LandChannel.GetLandObject(currentPos.X, currentPos.Y); - ILandObject destLand = m_scene.LandChannel.GetLandObject(position.X, position.Y); - if (srcLand != null && destLand != null && (teleportFlags & (uint)TeleportFlags.ViaLure) == 0 && (teleportFlags & (uint)TeleportFlags.ViaGodlikeLure) == 0) - { - if (srcLand.LandData.LocalID == destLand.LandData.LocalID) - { - //TPing within the same parcel. If the landing point is restricted, block the TP. - //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. - if (destLand.LandData.LandingType == (byte)1 && destLand.LandData.UserLocation != Vector3.Zero && avatar.GodLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar.UUID) && destLand.LandData.OwnerID != avatar.UUID) - { - avatar.ControllingClient.SendAgentAlertMessage("Can't TP to the destination; landing point set.", false); - position = currentPos; - } - } - else - { - //Tping to a different parcel. Respect the landing point on the destination parcel. - if (destLand.LandData.LandingType == (byte)1 && destLand.LandData.UserLocation != Vector3.Zero && avatar.GodLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar.UUID) && destLand.LandData.OwnerID != avatar.UUID) - { - position = destLand.LandData.UserLocation; - } - } + position, m_regionInfo.RegionName); + + // Teleport within the same region + if (IsOutsideRegion(avatar.Scene, position) || position.Z < 0) + { + Vector3 emergencyPos = new Vector3(128, 128, 128); + + m_log.WarnFormat( + "[SCENE COMMUNICATION SERVICE]: RequestTeleportToLocation() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", + position, avatar.Name, avatar.UUID, emergencyPos); + position = emergencyPos; + } + + Vector3 currentPos = avatar.AbsolutePosition; + ILandObject srcLand = m_scene.LandChannel.GetLandObject(currentPos.X, currentPos.Y); + ILandObject destLand = m_scene.LandChannel.GetLandObject(position.X, position.Y); + if (srcLand != null && destLand != null && (teleportFlags & (uint)TeleportFlags.ViaLure) == 0 && (teleportFlags & (uint)TeleportFlags.ViaGodlikeLure) == 0) + { + if (srcLand.LandData.LocalID == destLand.LandData.LocalID) + { + //TPing within the same parcel. If the landing point is restricted, block the TP. + //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. + if (destLand.LandData.LandingType == (byte)1 && destLand.LandData.UserLocation != Vector3.Zero && avatar.GodLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar.UUID) && destLand.LandData.OwnerID != avatar.UUID) + { + avatar.ControllingClient.SendAgentAlertMessage("Can't TP to the destination; landing point set.", false); + position = currentPos; + } + } + else + { + //Tping to a different parcel. Respect the landing point on the destination parcel. + if (destLand.LandData.LandingType == (byte)1 && destLand.LandData.UserLocation != Vector3.Zero && avatar.GodLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar.UUID) && destLand.LandData.OwnerID != avatar.UUID) + { + position = destLand.LandData.UserLocation; + } + } } // TODO: Get proper AVG Height -- cgit v1.1 From 044979066cf66e4dcd2c8f4be90337555dc0b34d Mon Sep 17 00:00:00 2001 From: CasperW Date: Fri, 5 Feb 2010 00:53:32 +0100 Subject: Fix two inconsistencies with LightShare --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs | 6 +++++- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Constants.cs | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index d4250c1..99973b4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -244,6 +244,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Types.Vector3 iV; switch (rule) { + case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: + idx++; + wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); + break; case (int)ScriptBaseClass.WL_AMBIENT: idx++; iQ = rules.GetQuaternionItem(idx); @@ -300,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: idx++; iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); break; case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: idx++; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Constants.cs index 7b67fa3..522c020 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Constants.cs @@ -70,7 +70,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int WL_CLOUD_SCROLL_Y = 32; public const int WL_CLOUD_SCROLL_Y_LOCK = 33; public const int WL_CLOUD_SCROLL_X_LOCK = 34; - public const int WL_DRAW_CLASSIC_CLOUDS = 35; + public const int WL_DRAW_CLASSIC_CLOUDS = 35; + public const int WL_SUN_MOON_POSITION = 36; } } -- cgit v1.1 From 0ad8046582354139f289f58f56b9b19a8bde7f38 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 8 Feb 2010 22:44:17 +0000 Subject: Resolve a merge issue --- OpenSim/Data/MySQL/MySQLLegacyRegionData.cs | 165 +++++++++++++++------------- 1 file changed, 86 insertions(+), 79 deletions(-) diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs index f4485df..f84beb6 100644 --- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs @@ -715,88 +715,93 @@ namespace OpenSim.Data.MySQL { RegionMeta7WindlightData nWP = new RegionMeta7WindlightData(); nWP.OnSave += StoreRegionWindlightSettings; - lock (m_Connection) + + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - + dbcon.Open(); + string command = "select * from `regionwindlight` where region_id = ?regionID"; - MySqlCommand cmd = new MySqlCommand(command); + using(MySqlCommand cmd = new MySqlCommand(command)) + { + cmd.Connection = dbcon; - cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); + cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); - IDataReader result = ExecuteReader(cmd); - if (!result.Read()) - { - //No result, so store our default windlight profile and return it - nWP.regionID = regionUUID; - StoreRegionWindlightSettings(nWP); - return nWP; - } - else - { - UUID.TryParse(result["region_id"].ToString(), out nWP.regionID); - nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); - nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); - nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); - nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); - nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); - nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); - nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); - nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); - nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); - nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); - nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); - nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); - nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); - nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); - nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); - nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); - nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); - UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); - nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); - nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); - nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); - nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); - nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); - nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); - nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); - nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); - nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); - nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); - nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); - nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); - nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); - nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); - nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); - nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); - nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); - nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); - nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); - nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); - nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); - nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); - nWP.eastAngle = Convert.ToSingle(result["east_angle"]); - nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); - nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); - nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); - nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); - nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); - nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); - nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); - nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); - nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); - nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); - nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); - nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); - nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); - nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); - nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); - nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); - nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); - nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); - nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); - nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); - nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); + IDataReader result = ExecuteReader(cmd); + if (!result.Read()) + { + //No result, so store our default windlight profile and return it + nWP.regionID = regionUUID; + StoreRegionWindlightSettings(nWP); + return nWP; + } + else + { + UUID.TryParse(result["region_id"].ToString(), out nWP.regionID); + nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); + nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); + nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); + nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); + nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); + nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); + nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); + nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); + nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); + nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); + nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); + nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); + nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); + nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); + nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); + nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); + nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); + UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); + nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); + nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); + nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); + nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); + nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); + nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); + nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); + nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); + nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); + nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); + nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); + nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); + nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); + nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); + nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); + nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); + nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); + nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); + nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); + nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); + nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); + nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); + nWP.eastAngle = Convert.ToSingle(result["east_angle"]); + nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); + nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); + nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); + nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); + nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); + nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); + nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); + nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); + nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); + nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); + nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); + nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); + nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); + nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); + nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); + nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); + nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); + nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); + nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); + nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); + nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); + } } } return nWP; @@ -842,9 +847,11 @@ namespace OpenSim.Data.MySQL public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) { - lock (m_Connection) + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - using (MySqlCommand cmd = m_Connection.CreateCommand()) + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) { cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; -- cgit v1.1 From 9568718addfd8e5d4094a456127ca469987f1f7a Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Fri, 12 Feb 2010 15:56:21 -0500 Subject: Angular motor adjustments --- OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs | 48 ++++++++++++----------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs index 4eb3313..55d6945 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs @@ -224,6 +224,8 @@ namespace OpenSim.Region.Physics.OdePlugin // These are vector properties but the engine lets you use a single float value to // set all of the components to the same value case Vehicle.ANGULAR_FRICTION_TIMESCALE: + if (pValue > 30f) pValue = 30f; + if (pValue < 0.1f) pValue = 0.1f; m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); break; case Vehicle.ANGULAR_MOTOR_DIRECTION: @@ -250,6 +252,12 @@ namespace OpenSim.Region.Physics.OdePlugin switch (pParam) { case Vehicle.ANGULAR_FRICTION_TIMESCALE: + if (pValue.X > 30f) pValue.X = 30f; + if (pValue.X < 0.1f) pValue.X = 0.1f; + if (pValue.Y > 30f) pValue.Y = 30f; + if (pValue.Y < 0.1f) pValue.Y = 0.1f; + if (pValue.Z > 30f) pValue.Z = 30f; + if (pValue.Z < 0.1f) pValue.Z = 0.1f; m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.ANGULAR_MOTOR_DIRECTION: @@ -306,7 +314,7 @@ namespace OpenSim.Region.Physics.OdePlugin { case Vehicle.TYPE_SLED: m_linearFrictionTimescale = new Vector3(30, 1, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_angularFrictionTimescale = new Vector3(30, 30, 30); // m_lLinMotorVel = Vector3.Zero; m_linearMotorTimescale = 1000; m_linearMotorDecayTimescale = 120; @@ -333,7 +341,7 @@ namespace OpenSim.Region.Physics.OdePlugin break; case Vehicle.TYPE_CAR: m_linearFrictionTimescale = new Vector3(100, 2, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); + m_angularFrictionTimescale = new Vector3(30, 30, 30); // was 1000, but sl max frict time is 30. // m_lLinMotorVel = Vector3.Zero; m_linearMotorTimescale = 1; m_linearMotorDecayTimescale = 60; @@ -548,6 +556,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_linearFrictionTimescale.Z < 300.0f) { float fricfactor = m_linearFrictionTimescale.Z / pTimestep; +//if(frcount == 0) Console.WriteLine("Zfric={0}", fricfactor); float fricZ = m_lLinObjectVel.Z / fricfactor; m_lLinObjectVel.Z -= fricZ; } @@ -639,7 +648,6 @@ namespace OpenSim.Region.Physics.OdePlugin */ //if(frcount == 0) Console.WriteLine("MoveAngular "); -//#### // Get what the body is doing, this includes 'external' influences d.Vector3 angularObjectVel = d.BodyGetAngularVel(Body); Vector3 angObjectVel = new Vector3(angularObjectVel.X, angularObjectVel.Y, angularObjectVel.Z); @@ -652,9 +660,18 @@ namespace OpenSim.Region.Physics.OdePlugin // Decay Angular Motor 2. if (m_angularMotorDecayTimescale < 300.0f) { - float decayfactor = m_angularMotorDecayTimescale/pTimestep; // df = Dec / pts - Vector3 decayAmount = (m_angularMotorDVel/decayfactor); // v-da = v-Dvel / df = v-Dvel * pts / Dec - m_angularMotorDVel -= decayAmount; // v-Dvel = v-Dvel - (v-Dvel / df = v-Dvel * pts / Dec) +//#### + if ( Vector3.Mag(m_angularMotorDVel) < 1.0f) + { + float decayfactor = (m_angularMotorDecayTimescale)/pTimestep; + Vector3 decayAmount = (m_angularMotorDVel/decayfactor); + m_angularMotorDVel -= decayAmount; + } + else + { + Vector3 decel = Vector3.Normalize(m_angularMotorDVel) * pTimestep / m_angularMotorDecayTimescale; + m_angularMotorDVel -= decel; + } if (m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) { @@ -743,22 +760,9 @@ namespace OpenSim.Region.Physics.OdePlugin //if(frcount == 0) Console.WriteLine("V2+= {0}", angObjectVel); } - if (m_angularFrictionTimescale.X < 300.0f) - { - float fricfactor = m_angularFrictionTimescale.X / pTimestep; - angObjectVel.X -= angObjectVel.X / fricfactor; - } - if (m_angularFrictionTimescale.Y < 300.0f) - { - float fricfactor = m_angularFrictionTimescale.Y / pTimestep; - angObjectVel.Y -= angObjectVel.Y / fricfactor; - } - if (m_angularFrictionTimescale.Z < 300.0f) - { - float fricfactor = m_angularFrictionTimescale.Z / pTimestep; - angObjectVel.Z -= angObjectVel.Z / fricfactor; - Console.WriteLine("z fric"); - } + angObjectVel.X -= angObjectVel.X / (m_angularFrictionTimescale.X * 0.7f / pTimestep); + angObjectVel.Y -= angObjectVel.Y / (m_angularFrictionTimescale.Y * 0.7f / pTimestep); + angObjectVel.Z -= angObjectVel.Z / (m_angularFrictionTimescale.Z * 0.7f / pTimestep); } // else no signif. motion //if(frcount == 0) Console.WriteLine("Dmotor {0} Obj {1}", m_angularMotorDVel, angObjectVel); -- cgit v1.1 From ce3e2655752fb56d9f18bf7cc0686e97c06f16da Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 14 Feb 2010 23:58:54 +0000 Subject: Plug a small hole --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 7b852a2..b2b061e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -585,6 +585,9 @@ namespace OpenSim.Region.Framework.Scenes m_log.Error("[AGENT INVENTORY]: Failed to find item " + oldItemID.ToString()); return; } + + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + return; } AssetBase asset = AssetService.Get(item.AssetID.ToString()); -- cgit v1.1 From 94c417c90c9e4d91ea0c09fc5a3ac2541e09655d Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 15 Feb 2010 06:10:04 +0100 Subject: Implement missing llGetPrimitiveParams parameters --- .../Shared/Api/Implementation/LSL_Api.cs | 170 +++++++++++++++++---- 1 file changed, 138 insertions(+), 32 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e4ccce8..9db8ca0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7674,25 +7674,96 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case (int)ScriptBaseClass.PRIM_BUMP_SHINY: - // TODO-------------- - if (remain < 1) - return res; - - face=(int)rules.GetLSLIntegerItem(idx++); - - res.Add(new LSL_Integer(0)); - res.Add(new LSL_Integer(0)); + case (int)ScriptBaseClass.PRIM_BUMP_SHINY: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + tex = part.Shape.Textures; + int shiny; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < GetNumberOfSides(part); face++) + { + Shininess shinyness = tex.GetFace((uint)face).Shiny; + if (shinyness == Shininess.High) + { + shiny = ScriptBaseClass.PRIM_SHINY_HIGH; + } + else if (shinyness == Shininess.Medium) + { + shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; + } + else if (shinyness == Shininess.Low) + { + shiny = ScriptBaseClass.PRIM_SHINY_LOW; + } + else + { + shiny = ScriptBaseClass.PRIM_SHINY_NONE; + } + res.Add(new LSL_Integer(shiny)); + res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); + } + } + else + { + Shininess shinyness = tex.GetFace((uint)face).Shiny; + if (shinyness == Shininess.High) + { + shiny = ScriptBaseClass.PRIM_SHINY_HIGH; + } + else if (shinyness == Shininess.Medium) + { + shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; + } + else if (shinyness == Shininess.Low) + { + shiny = ScriptBaseClass.PRIM_SHINY_LOW; + } + else + { + shiny = ScriptBaseClass.PRIM_SHINY_NONE; + } + res.Add(new LSL_Integer(shiny)); + res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); + } break; - case (int)ScriptBaseClass.PRIM_FULLBRIGHT: - // TODO-------------- - if (remain < 1) - return res; - - face=(int)rules.GetLSLIntegerItem(idx++); - - res.Add(new LSL_Integer(0)); + case (int)ScriptBaseClass.PRIM_FULLBRIGHT: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + tex = part.Shape.Textures; + int fullbright; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < GetNumberOfSides(part); face++) + { + if (tex.GetFace((uint)face).Fullbright == true) + { + fullbright = ScriptBaseClass.TRUE; + } + else + { + fullbright = ScriptBaseClass.FALSE; + } + res.Add(new LSL_Integer(fullbright)); + } + } + else + { + if (tex.GetFace((uint)face).Fullbright == true) + { + fullbright = ScriptBaseClass.TRUE; + } + else + { + fullbright = ScriptBaseClass.FALSE; + } + res.Add(new LSL_Integer(fullbright)); + } break; case (int)ScriptBaseClass.PRIM_FLEXIBLE: @@ -7713,14 +7784,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_TEXGEN: - // TODO-------------- - // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) - if (remain < 1) - return res; - - face=(int)rules.GetLSLIntegerItem(idx++); - - res.Add(new LSL_Integer(0)); + // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + tex = part.Shape.Textures; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < GetNumberOfSides(part); face++) + { + if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } + } + } + else + { + if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } + } break; case (int)ScriptBaseClass.PRIM_POINT_LIGHT: @@ -7738,14 +7832,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api res.Add(new LSL_Float(shape.LightFalloff)); // falloff break; - case (int)ScriptBaseClass.PRIM_GLOW: - // TODO-------------- - if (remain < 1) + case (int)ScriptBaseClass.PRIM_GLOW: + if (remain < 1) return res; - - face=(int)rules.GetLSLIntegerItem(idx++); - - res.Add(new LSL_Float(0)); + face = (int)rules.GetLSLIntegerItem(idx++); + + tex = part.Shape.Textures; + float primglow; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < GetNumberOfSides(part); face++) + { + primglow = tex.GetFace((uint)face).Glow; + res.Add(new LSL_Float(primglow)); + } + } + else + { + primglow = tex.GetFace((uint)face).Glow; + res.Add(new LSL_Float(primglow)); + } break; } } -- cgit v1.1 From af2d20c5fa0403c6cae1008eda3179acc4694d7f Mon Sep 17 00:00:00 2001 From: CasperW Date: Mon, 15 Feb 2010 22:22:36 +0100 Subject: Fix an inconsistency in llSetPayPrice between SL and OS behaviour --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 9db8ca0..824073b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8968,9 +8968,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); if (quick_pay_buttons.Data.Length < 4) - { - LSLError("List must have at least 4 elements"); - return; + { + int x; + for (x=quick_pay_buttons.Data.Length; x<= 4; x++) + { + quick_pay_buttons.Add(ScriptBaseClass.PAY_HIDE); + } } int[] nPrice = new int[5]; nPrice[0]=price; -- cgit v1.1 From d6eff8ebcffc1231ea533c83764aa3b39d4e5750 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 16 Feb 2010 23:14:57 +0000 Subject: Change a condition to actually make linden land reclaim work --- OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 28669b9..9be94ce 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -97,7 +97,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void Initialise(IConfigSource source) { IConfig cnf = source.Configs["LandManagement"]; - if (cnf == null) + if (cnf != null) { DefaultGodParcelGroup = new UUID(cnf.GetString("DefaultAdministratorGroupUUID", UUID.Zero.ToString())); DefaultGodParcelName = cnf.GetString("DefaultAdministratorParcelName", "Default Parcel"); -- cgit v1.1 From efd481085135f60d8f6d3e4615591a26ec3f05f6 Mon Sep 17 00:00:00 2001 From: CasperW Date: Thu, 25 Feb 2010 12:04:51 +0100 Subject: Disable blocking teleports within the same parcel for now; it's not implemented correctly. Will review soon. --- OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 9ceab19..5f84252 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -722,8 +722,10 @@ namespace OpenSim.Region.Framework.Scenes //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. if (destLand.LandData.LandingType == (byte)1 && destLand.LandData.UserLocation != Vector3.Zero && avatar.GodLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(avatar.UUID) && destLand.LandData.OwnerID != avatar.UUID) { - avatar.ControllingClient.SendAgentAlertMessage("Can't TP to the destination; landing point set.", false); - position = currentPos; + //Disabling this behaviour for now pending review. ~CasperW + + //avatar.ControllingClient.SendAgentAlertMessage("Can't TP to the destination; landing point set.", false); + //position = currentPos; } } else -- cgit v1.1 From e99341d7df66f73286b8a440991358cbca1a8399 Mon Sep 17 00:00:00 2001 From: CasperW Date: Thu, 25 Feb 2010 12:07:56 +0100 Subject: llDie() should not work on attachments (results in an incosistent attachment state) --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 824073b..7a6739b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1118,7 +1118,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public virtual void llDie() { m_host.AddScriptLPS(1); - throw new SelfDeleteException(); + if (!m_host.IsAttachment) throw new SelfDeleteException(); } public LSL_Float llGround(LSL_Vector offset) -- cgit v1.1 From 7f61de8f57d9f01e532dc37a5ef81153ba40fc24 Mon Sep 17 00:00:00 2001 From: CasperW Date: Thu, 25 Feb 2010 14:14:53 +0100 Subject: Allow particles and texture anims to be persisted to XML. This behaviour is expected. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 11682d9..0d19589 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -518,14 +518,12 @@ namespace OpenSim.Region.Framework.Scenes set { m_scriptAccessPin = (int)value; } } - [XmlIgnore] public Byte[] TextureAnimation { get { return m_TextureAnimation; } set { m_TextureAnimation = value; } } - [XmlIgnore] public Byte[] ParticleSystem { get { return m_particleSystem; } -- cgit v1.1 From 393a7828584a0bf8564dd351015238365e51b984 Mon Sep 17 00:00:00 2001 From: CasperW Date: Thu, 25 Feb 2010 18:05:30 +0100 Subject: Fix the crashed session notification from the userserver. --- .../Framework/Communications/Services/LoginService.cs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/OpenSim/Framework/Communications/Services/LoginService.cs b/OpenSim/Framework/Communications/Services/LoginService.cs index 71b38ed..824cc57 100644 --- a/OpenSim/Framework/Communications/Services/LoginService.cs +++ b/OpenSim/Framework/Communications/Services/LoginService.cs @@ -88,15 +88,7 @@ namespace OpenSim.Framework.Communications.Services m_welcomeMessage = welcomeMess; } } - - /// - /// If the user is already logged in, try to notify the region that the user they've got is dead. - /// - /// - public virtual void LogOffUser(UserProfileData theUser, string message) - { - } - + /// /// Called when we receive the client's initial XMLRPC login_to_simulator request message /// @@ -1056,7 +1048,13 @@ namespace OpenSim.Framework.Communications.Services protected abstract RegionInfo RequestClosestRegion(string region); protected abstract RegionInfo GetRegionInfo(ulong homeRegionHandle); - protected abstract RegionInfo GetRegionInfo(UUID homeRegionId); + protected abstract RegionInfo GetRegionInfo(UUID homeRegionId); + + /// + /// If the user is already logged in, try to notify the region that the user they've got is dead. + /// + /// + public abstract void LogOffUser(UserProfileData theUser, string message); /// /// Prepare a login to the given region. This involves both telling the region to expect a connection -- cgit v1.1 From 2f0011c605833caa131265c82e3f6340b0610183 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 3 Mar 2010 01:26:19 +0000 Subject: test --- LICENSE.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/LICENSE.txt b/LICENSE.txt index a004cad..581441e 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,7 @@ Copyright (c) Contributors, http://opensimulator.org/ See CONTRIBUTORS.TXT for a full list of copyright holders. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright -- cgit v1.1 From 01c4bb4a5e1845bb4680b3e7c8b77217d6a50ed2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 3 Mar 2010 01:29:42 +0000 Subject: Revert "test" This reverts commit 2f0011c605833caa131265c82e3f6340b0610183. --- LICENSE.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index 581441e..a004cad 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,7 +1,6 @@ Copyright (c) Contributors, http://opensimulator.org/ See CONTRIBUTORS.TXT for a full list of copyright holders. - Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright -- cgit v1.1 From 84b0a23e193b220d61b5a67e90df32138441c1e8 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 4 Mar 2010 10:38:03 +0000 Subject: Remove a superfluous array creation --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index e87b1f4..1ea52c5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -416,7 +416,6 @@ namespace OpenSim.Region.ScriptEngine.Shared public list(params object[] args) { - m_data = new object[args.Length]; m_data = args; } -- cgit v1.1 From 62dd83f473fefb3ff2a7b64728a40337ae0e395e Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 4 Mar 2010 10:38:03 +0000 Subject: Remove a superfluous array creation --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index e87b1f4..1ea52c5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -416,7 +416,6 @@ namespace OpenSim.Region.ScriptEngine.Shared public list(params object[] args) { - m_data = new object[args.Length]; m_data = args; } -- cgit v1.1 From 87590491b52e8ca0211274c17a83482534f845f3 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 4 Mar 2010 16:33:26 -0500 Subject: Fix Physics angular reference frame. --- .../Physics/ChOdePlugin/ODEDynamics.c_comments | 630 --------------------- OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs | 33 +- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 76 ++- 3 files changed, 84 insertions(+), 655 deletions(-) delete mode 100644 OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.c_comments diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.c_comments b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.c_comments deleted file mode 100644 index 1060aa6..0000000 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.c_comments +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. - * - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using log4net; -using OpenMetaverse; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.OdePlugin -{ - public class ODEDynamics - { - public Vehicle Type - { - get { return m_type; } - } - - public IntPtr Body - { - get { return m_body; } - } - - private int frcount = 0; // Used to limit dynamics debug output to - // every 100th frame - - // private OdeScene m_parentScene = null; - private IntPtr m_body = IntPtr.Zero; - private IntPtr m_jointGroup = IntPtr.Zero; - private IntPtr m_aMotor = IntPtr.Zero; - - - // Vehicle properties - private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind - // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier - private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: - // HOVER_TERRAIN_ONLY - // HOVER_GLOBAL_HEIGHT - // NO_DEFLECTION_UP - // HOVER_WATER_ONLY - // HOVER_UP_ONLY - // LIMIT_MOTOR_UP - // LIMIT_ROLL_ONLY - - // Linear properties - private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time - private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL - private Vector3 m_dir = Vector3.Zero; // velocity applied to body - private Vector3 m_linearFrictionTimescale = Vector3.Zero; - private float m_linearMotorDecayTimescale = 0; - private float m_linearMotorTimescale = 0; - private Vector3 m_lastLinearVelocityVector = Vector3.Zero; - // private bool m_LinearMotorSetLastFrame = false; - // private Vector3 m_linearMotorOffset = Vector3.Zero; - - //Angular properties - private Vector3 m_angularMotorDirection = Vector3.Zero; - private Vector3 m_angularMotorDirectionLASTSET = Vector3.Zero; - private Vector3 m_angularFrictionTimescale = Vector3.Zero; - private float m_angularMotorDecayTimescale = 0; - private float m_angularMotorTimescale = 0; - private Vector3 m_lastAngularVelocityVector = Vector3.Zero; - - //Deflection properties - // private float m_angularDeflectionEfficiency = 0; - // private float m_angularDeflectionTimescale = 0; - // private float m_linearDeflectionEfficiency = 0; - // private float m_linearDeflectionTimescale = 0; - - //Banking properties - // private float m_bankingEfficiency = 0; - // private float m_bankingMix = 0; - // private float m_bankingTimescale = 0; - - //Hover and Buoyancy properties - private float m_VhoverHeight = 0f; - private float m_VhoverEfficiency = 0f; - private float m_VhoverTimescale = 0f; - private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height - private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. - // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) - // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. - // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. - - //Attractor properties - private float m_verticalAttractionEfficiency = 0; - private float m_verticalAttractionTimescale = 0; - - - - - - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) - { - switch (pParam) - { - case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionEfficiency = pValue; - break; - case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionTimescale = pValue; - break; - case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorDecayTimescale = pValue; - break; - case Vehicle.ANGULAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorTimescale = pValue; - break; - case Vehicle.BANKING_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingEfficiency = pValue; - break; - case Vehicle.BANKING_MIX: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingMix = pValue; - break; - case Vehicle.BANKING_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingTimescale = pValue; - break; - case Vehicle.BUOYANCY: - if (pValue < -1f) pValue = -1f; - if (pValue > 1f) pValue = 1f; - m_VehicleBuoyancy = pValue; - break; - case Vehicle.HOVER_EFFICIENCY: - if (pValue < 0f) pValue = 0f; - if (pValue > 1f) pValue = 1f; - m_VhoverEfficiency = pValue; - break; - case Vehicle.HOVER_HEIGHT: - m_VhoverHeight = pValue; - break; - case Vehicle.HOVER_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_VhoverTimescale = pValue; - break; - case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionEfficiency = pValue; - break; - case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionTimescale = pValue; - break; - case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorDecayTimescale = pValue; - break; - case Vehicle.LINEAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorTimescale = pValue; - break; - case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: - if (pValue < 0.0f) pValue = 0.0f; - if (pValue > 1.0f) pValue = 1.0f; - m_verticalAttractionEfficiency = pValue; - break; - case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_verticalAttractionTimescale = pValue; - break; - - // These are vector properties but the engine lets you use a single float value to - // set all of the components to the same value - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - m_angularMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue, pValue, pValue); - m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); - break; - - } - - }//end ProcessFloatVehicleParam - - internal void ProcessVectorVehicleParam(Vehicle pParam, PhysicsVector pValue) - { - switch (pParam) - { - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_angularMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - } - - }//end ProcessVectorVehicleParam - - internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) - { - switch (pParam) - { - case Vehicle.REFERENCE_FRAME: - // m_referenceFrame = pValue; - break; - } - - }//end ProcessRotationVehicleParam - - internal void ProcessTypeChange(Vehicle pType) - { -Console.WriteLine("ProcessTypeChange to " + pType); - - // Set Defaults For Type - m_type = pType; - switch (pType) - { - case Vehicle.TYPE_SLED: - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1000; - m_linearMotorDecayTimescale = 120; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1000; - m_angularMotorDecayTimescale = 120; - m_VhoverHeight = 0; - m_VhoverEfficiency = 1; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 1; - // m_linearDeflectionTimescale = 1; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 1000; - // m_bankingEfficiency = 0; - // m_bankingMix = 1; - // m_bankingTimescale = 10; - // m_referenceFrame = Quaternion.Identity; - m_flags &= - ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_CAR: - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 1; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 1; - m_angularMotorDecayTimescale = 0.8f; - m_VhoverHeight = 0; - m_VhoverEfficiency = 0; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - // // m_linearDeflectionEfficiency = 1; - // // m_linearDeflectionTimescale = 2; - // // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 10; - m_verticalAttractionEfficiency = 1; - m_verticalAttractionTimescale = 10; - // m_bankingEfficiency = -0.2f; - // m_bankingMix = 1; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY | - VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_BOAT: - m_linearFrictionTimescale = new Vector3(10, 3, 2); - m_angularFrictionTimescale = new Vector3(10,10,10); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 2; - m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 0.5f; - // m_angularDeflectionTimescale = 5; - m_verticalAttractionEfficiency = 0.5f; - m_verticalAttractionTimescale = 5; - // m_bankingEfficiency = -0.3f; - // m_bankingMix = 0.8f; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | - VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_AIRPLANE: - m_linearFrictionTimescale = new Vector3(200, 10, 5); - m_angularFrictionTimescale = new Vector3(20, 20, 20); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 2; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 2; - m_verticalAttractionEfficiency = 0.9f; - m_verticalAttractionTimescale = 2; - // m_bankingEfficiency = 1; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 2; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - break; - case Vehicle.TYPE_BALLOON: - m_linearFrictionTimescale = new Vector3(5, 5, 5); - m_angularFrictionTimescale = new Vector3(10, 10, 10); - m_linearMotorDirection = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorTimescale = 6; - m_angularMotorDecayTimescale = 10; - m_VhoverHeight = 5; - m_VhoverEfficiency = 0.8f; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0; - // m_linearDeflectionTimescale = 5; - // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 5; - m_verticalAttractionEfficiency = 1; - m_verticalAttractionTimescale = 1000; - // m_bankingEfficiency = 0; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 5; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); - break; - - } - }//end SetDefaultsForType - - internal void Enable(IntPtr pBody, OdeScene pParentScene) - { -//Console.WriteLine("Enable m_type=" + m_type + " m_VehicleBuoyancy=" + m_VehicleBuoyancy); - if (m_type == Vehicle.TYPE_NONE) - return; - - m_body = pBody; - //KF: This used to set up the linear and angular joints - } - - internal void Step(float pTimestep, OdeScene pParentScene) - { - if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) - return; - frcount++; // used to limit debug comment output - if (frcount > 100) - frcount = 0; - - MoveLinear(pTimestep, pParentScene); - MoveAngular(pTimestep); - }// end Step - - private void MoveLinear(float pTimestep, OdeScene _pParentScene) - { - if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant - { - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); - - // add drive to body - Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); - m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? - - // This will work temporarily, but we really need to compare speed on an axis - // KF: Limit body velocity to applied velocity? - if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) - m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; - if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) - m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; - if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) - m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; - - // decay applied velocity - Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); - //Console.WriteLine("decay: " + decayfraction); - m_linearMotorDirection -= m_linearMotorDirection * decayfraction; - //Console.WriteLine("actual: " + m_linearMotorDirection); - } - else - { // requested is not significant - // if what remains of applied is small, zero it. - if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) - m_lastLinearVelocityVector = Vector3.Zero; - } - - - // convert requested object velocity to world-referenced vector - m_dir = m_lastLinearVelocityVector; - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object - m_dir *= rotq; // apply obj rotation to velocity vector - - // add Gravity andBuoyancy - // KF: So far I have found no good method to combine a script-requested - // .Z velocity and gravity. Therefore only 0g will used script-requested - // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. - Vector3 grav = Vector3.Zero; - if(m_VehicleBuoyancy < 1.0f) - { - // There is some gravity, make a gravity force vector - // that is applied after object velocity. - d.Mass objMass; - d.BodyGetMass(Body, out objMass); - // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); - // Preserve the current Z velocity - d.Vector3 vel_now = d.BodyGetLinearVel(Body); - m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity - } // else its 1.0, no gravity. - - // Check if hovering - if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) - { - // We should hover, get the target height - d.Vector3 pos = d.BodyGetPosition(Body); - if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY) - { - m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; - } - else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY) - { - m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; - } - else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT) - { - m_VhoverTargetHeight = m_VhoverHeight; - } - - if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY) - { - // If body is aready heigher, use its height as target height - if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; - } - -// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped -// m_VhoverTimescale = 0f; // time to acheive height -// pTimestep is time since last frame,in secs - float herr0 = pos.Z - m_VhoverTargetHeight; -//if(frcount == 0) Console.WriteLine("herr0=" + herr0); - // Replace Vertical speed with correction figure if significant - if(Math.Abs(herr0) > 0.01f ) - { - d.Mass objMass; - d.BodyGetMass(Body, out objMass); - m_dir.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale); - // m_VhoverEfficiency is not yet implemented - } - else - { - m_dir.Z = 0f; - } - } - - // Apply velocity - d.BodySetLinearVel(Body, m_dir.X, m_dir.Y, m_dir.Z); -//if(frcount == 0) Console.WriteLine("Move " + Body + ":"+ m_dir.X + " " + m_dir.Y + " " + m_dir.Z); - // apply gravity force - d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); -//if(frcount == 0) Console.WriteLine("Force " + Body + ":" + grav.X + " " + grav.Y + " " + grav.Z); - - - // apply friction - Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); - m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; - } // end MoveLinear() - - private void MoveAngular(float pTimestep) - { - - // m_angularMotorDirection is the latest value from the script, and is decayed here - // m_angularMotorDirectionLASTSET is the latest value from the script - // m_lastAngularVelocityVector is what is being applied to the Body, varied up and down here - - if (!m_angularMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) - { - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); - // ramp up to new value - Vector3 addAmount = m_angularMotorDirection / (m_angularMotorTimescale / pTimestep); - m_lastAngularVelocityVector += (addAmount * 10f); -//if(frcount == 0) Console.WriteLine("add: " + addAmount); - - // limit applied value to what was set by script - // This will work temporarily, but we really need to compare speed on an axis - if (Math.Abs(m_lastAngularVelocityVector.X) > Math.Abs(m_angularMotorDirectionLASTSET.X)) - m_lastAngularVelocityVector.X = m_angularMotorDirectionLASTSET.X; - if (Math.Abs(m_lastAngularVelocityVector.Y) > Math.Abs(m_angularMotorDirectionLASTSET.Y)) - m_lastAngularVelocityVector.Y = m_angularMotorDirectionLASTSET.Y; - if (Math.Abs(m_lastAngularVelocityVector.Z) > Math.Abs(m_angularMotorDirectionLASTSET.Z)) - m_lastAngularVelocityVector.Z = m_angularMotorDirectionLASTSET.Z; - - // decay the requested value - Vector3 decayfraction = ((Vector3.One / (m_angularMotorDecayTimescale / pTimestep))); - //Console.WriteLine("decay: " + decayfraction); - m_angularMotorDirection -= m_angularMotorDirection * decayfraction; - //Console.WriteLine("actual: " + m_linearMotorDirection); - } - // KF: m_lastAngularVelocityVector is rotational speed in rad/sec ? - - // Vertical attractor section - -// d.Mass objMass; -// d.BodyGetMass(Body, out objMass); -// float servo = 100f * objMass.mass * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep); - float servo = 0.1f * m_verticalAttractionEfficiency / (m_verticalAttractionTimescale * pTimestep); - // get present body rotation - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); - // make a vector pointing up - Vector3 verterr = Vector3.Zero; - verterr.Z = 1.0f; - // rotate it to Body Angle - verterr = verterr * rotq; - // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. - // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go - // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. - if (verterr.Z < 0.0f) - { - verterr.X = 2.0f - verterr.X; - verterr.Y = 2.0f - verterr.Y; - } - // Error is 0 (no error) to +/- 2 (max error) - // scale it by servo - verterr = verterr * servo; - - // rotate to object frame - // verterr = verterr * rotq; - - // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so - // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. - m_lastAngularVelocityVector.X += verterr.Y; - m_lastAngularVelocityVector.Y -= verterr.X; -/* -if(frcount == 0) - { -// Console.WriteLine("AngleMotor " + m_lastAngularVelocityVector); - Console.WriteLine(String.Format("VA Body:{0} servo:{1} err:<{2},{3},{4}> VAE:{5}", - Body, servo, verterr.X, verterr.Y, verterr.Z, m_verticalAttractionEfficiency)); - } - */ - d.BodySetAngularVel (Body, m_lastAngularVelocityVector.X, m_lastAngularVelocityVector.Y, m_lastAngularVelocityVector.Z); - // apply friction - Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); - m_lastAngularVelocityVector -= m_lastAngularVelocityVector * decayamount; - - } //end MoveAngular - } -} diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs index 55d6945..b3b09e6 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs @@ -116,6 +116,8 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor // private Vector3 m_angObjectVel = Vector3.Zero; // current body angular velocity private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body + + private Vector3 m_angularLock = Vector3.One; //Deflection properties // private float m_angularDeflectionEfficiency = 0; @@ -296,6 +298,11 @@ namespace OpenSim.Region.Physics.OdePlugin }//end ProcessRotationVehicleParam + internal void SetAngularLock(Vector3 pValue) + { + m_angularLock = pValue; + } + internal void ProcessFlagsVehicleSet(int flags) { m_flags |= (VehicleFlag)flags; @@ -649,8 +656,13 @@ namespace OpenSim.Region.Physics.OdePlugin //if(frcount == 0) Console.WriteLine("MoveAngular "); // Get what the body is doing, this includes 'external' influences + d.Quaternion rot = d.BodyGetQuaternion(Body); + Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object + Quaternion irotq = Quaternion.Inverse(rotq); d.Vector3 angularObjectVel = d.BodyGetAngularVel(Body); Vector3 angObjectVel = new Vector3(angularObjectVel.X, angularObjectVel.Y, angularObjectVel.Z); + angObjectVel = angObjectVel * irotq; // ============ Converts to LOCAL rotation + //if(frcount == 0) Console.WriteLine("V0 = {0}", angObjectVel); // Vector3 FrAaccel = m_lastAngularVelocity - angObjectVel; // Vector3 initavel = angObjectVel; @@ -694,8 +706,8 @@ namespace OpenSim.Region.Physics.OdePlugin { float VAservo = 1.0f / (m_verticalAttractionTimescale * pTimestep); // get present body rotation - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); +// d.Quaternion rot = d.BodyGetQuaternion(Body); +// Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // make a vector pointing up Vector3 verterr = Vector3.Zero; verterr.Z = 1.0f; @@ -706,7 +718,7 @@ namespace OpenSim.Region.Physics.OdePlugin // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. if (verterr.Z < 0.0f) - { // Defelction from vertical exceeds 90-degrees. This method will ensure stable return to + { // Deflection from vertical exceeds 90-degrees. This method will ensure stable return to // vertical, BUT for some reason a z-rotation is imparted to the object. TBI. //Console.WriteLine("InvertFlip"); verterr.X = 2.0f - verterr.X; @@ -781,9 +793,22 @@ namespace OpenSim.Region.Physics.OdePlugin m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. } */ +//if(frcount == 0) Console.WriteLine("angularLock {0}", m_angularLock); + + if (!m_angularLock.ApproxEquals(Vector3.One, 0.003f)) + { + if (m_angularLock.X == 0) + m_lastAngularVelocity.X = 0f; + if (m_angularLock.Y == 0) + m_lastAngularVelocity.Y = 0f; + if (m_angularLock.Z == 0) + m_lastAngularVelocity.Z = 0f; + } // Apply to the body // Vector3 aInc = m_lastAngularVelocity - initavel; -//if(frcount == 0) Console.WriteLine("Inc {0}", aInc); +//if(frcount == 0) Console.WriteLine("Inc {0}", aInc); + m_lastAngularVelocity = m_lastAngularVelocity * rotq; // ================ Converts to WORLD rotation + d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); //if(frcount == 0) Console.WriteLine("V4 = {0}", m_lastAngularVelocity); diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 8502aef..fb6cb55 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -85,8 +85,10 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 m_taintVelocity; private Vector3 m_taintTorque; private Quaternion m_taintrot; - private Vector3 m_angularlock = Vector3.One; - private Vector3 m_taintAngularLock = Vector3.One; + private Vector3 m_angularlock = Vector3.One; // Current setting + private Vector3 m_taintAngularLock = Vector3.One; // Request from LSL + + private IntPtr Amotor = IntPtr.Zero; private Vector3 m_PIDTarget; @@ -405,10 +407,10 @@ namespace OpenSim.Region.Physics.OdePlugin m_disabled = false; // The body doesn't already have a finite rotation mode set here - if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0.0f)) && _parent == null) + /* ### if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0.0f)) && _parent == null) { createAMotor(m_angularlock); - } + } */ if (m_vehicle.Type != Vehicle.TYPE_NONE) { m_vehicle.Enable(Body, _parent_scene); @@ -958,8 +960,10 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_taintCollidesWater != m_collidesWater) changefloatonwater(timestep); - + + // ##* if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) +//Console.WriteLine("ALchange req {0} is {1}", m_taintAngularLock, m_angularlock); changeAngularLock(timestep); } @@ -970,15 +974,21 @@ namespace OpenSim.Region.Physics.OdePlugin } - private void changeAngularLock(float timestep) + private void changeAngularLock(float timestep) // ##* { // do we have a Physical object? - if (Body != IntPtr.Zero) - { +// if (Body != IntPtr.Zero) +// { //Check that we have a Parent //If we have a parent then we're not authorative here if (_parent == null) { +//Console.WriteLine("Alock changed to {0}", m_taintAngularLock); + m_angularlock = m_taintAngularLock; + m_vehicle.SetAngularLock(m_angularlock); + + +/* if (!m_taintAngularLock.ApproxEquals(Vector3.One, 0f)) { //d.BodySetFiniteRotationMode(Body, 0); @@ -997,7 +1007,9 @@ namespace OpenSim.Region.Physics.OdePlugin } // Store this for later in case we get turned into a separate body m_angularlock = m_taintAngularLock; - + m_vehicle.SetAngularLock(m_angularlock); + } */ + } } private void changelink(float timestep) @@ -1140,10 +1152,10 @@ namespace OpenSim.Region.Physics.OdePlugin prm.m_disabled = false; // The body doesn't already have a finite rotation mode set here - if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) + /* ### if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) { prm.createAMotor(m_angularlock); - } + } */ prm.Body = Body; _parent_scene.addActivePrim(prm); } @@ -1183,10 +1195,10 @@ namespace OpenSim.Region.Physics.OdePlugin m_disabled = false; // The body doesn't already have a finite rotation mode set here - if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) + /* ### if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) { createAMotor(m_angularlock); - } + } */ d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); if (m_vehicle.Type != Vehicle.TYPE_NONE) m_vehicle.Enable(Body, _parent_scene); _parent_scene.addActivePrim(this); @@ -1600,14 +1612,17 @@ Console.WriteLine(" JointCreateFixed"); { if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 // NON-'VEHICLES' are dealt with here - if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f)) + // m_angularlock = <1,1,1> means no lock. a 0 on axis means locked. + +// NB this may be wrong - may lock global axis! Should be LOCAL axis! + if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.One, 0.003f)) { d.Vector3 avel2 = d.BodyGetAngularVel(Body); - if (m_angularlock.X == 1) + if (m_angularlock.X == 0) avel2.X = 0; - if (m_angularlock.Y == 1) + if (m_angularlock.Y == 0) avel2.Y = 0; - if (m_angularlock.Z == 1) + if (m_angularlock.Z == 0) avel2.Z = 0; d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); } @@ -1808,6 +1823,17 @@ Console.WriteLine(" JointCreateFixed"); // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); RLAservo = timestep / m_APIDStrength * scaler; rotforce = rotforce * RLAservo * diff_angle ; + + if (m_angularlock.X == 0) + rotforce.X = 0; + if (m_angularlock.Y == 0) + rotforce.Y = 0; + if (m_angularlock.Z == 0) + rotforce.Z = 0; + + + + d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); //Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); } @@ -1878,11 +1904,11 @@ Console.WriteLine(" JointCreateFixed"); { // KF: If this is a root prim do BodySet d.BodySetQuaternion(Body, ref myrot); - if (m_isphysical) + /* ### if (m_isphysical) { if (!m_angularlock.ApproxEquals(Vector3.One, 0f)) createAMotor(m_angularlock); - } + } */ } else { @@ -2508,7 +2534,14 @@ Console.WriteLine(" JointCreateFixed"); } } } - +/* + public Vector3 AngularLock + { + get { return m_angularlock; } + set { } + } + +*/ public override float CollisionScore { get { return m_collisionscore; } @@ -2914,8 +2947,9 @@ Console.WriteLine(" JointCreateFixed"); public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } public override float PIDHoverTau { set { m_PIDHoverTau = value; } } - private void createAMotor(Vector3 axis) + private void createAMotor(Vector3 axis) // ##* { +Console.WriteLine(" createAMotor called! ----------------------------"); if (Body == IntPtr.Zero) return; -- cgit v1.1 From 83929c69e35d156d99be46a6ee50b0d3fe5c9f25 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 6 Mar 2010 00:56:55 -0600 Subject: - implementing server 1.38 functions Signed-off-by: Melanie --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 5 ++ .../Shared/Api/Implementation/LSL_Api.cs | 99 +++++++++++++++++++--- .../ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 4 + .../Shared/Api/Runtime/LSL_Constants.cs | 1 + .../ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | 20 +++++ 5 files changed, 119 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 5c283bc..a85a4b3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4680,5 +4680,10 @@ namespace OpenSim.Region.Framework.Scenes m_log.Error("[Physics] " + ex); } } + + public Color4 GetTextColor() + { + return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A)); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index aa876ec..a373046 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5406,12 +5406,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) { m_host.AddScriptLPS(1); + + SetTextureAnim(m_host, mode, face, sizex, sizey, start, length, rate); + } + + public void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_host.AddScriptLPS(1); + + List parts = GetLinkParts(linknumber); + + foreach (var part in parts) + { + SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); + } + } + + private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); pTexAnim.Flags = (Primitive.TextureAnimMode)mode; //ALL_SIDES if (face == ScriptBaseClass.ALL_SIDES) - face = 255; + face = 255; pTexAnim.Face = (uint)face; pTexAnim.Length = (float)length; @@ -5420,9 +5439,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api pTexAnim.SizeY = (uint)sizey; pTexAnim.Start = (float)start; - m_host.AddTextureAnimation(pTexAnim); - m_host.SendFullUpdateToAllClients(); - m_host.ParentGroup.HasGroupChanged = true; + part.AddTextureAnimation(pTexAnim); + part.SendFullUpdateToAllClients(); + part.ParentGroup.HasGroupChanged = true; } public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, @@ -5819,13 +5838,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return ps; } + public void llLinkParticleSystem(int linknumber, LSL_List rules) + { + m_host.AddScriptLPS(1); + + List parts = GetLinkParts(linknumber); + + foreach (var part in parts) + { + SetParticleSystem(part, rules); + } + } + public void llParticleSystem(LSL_List rules) { m_host.AddScriptLPS(1); + SetParticleSystem(m_host, rules); + } + + private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { + + if (rules.Length == 0) { - m_host.RemoveParticleSystem(); - m_host.ParentGroup.HasGroupChanged = true; + part.RemoveParticleSystem(); + part.ParentGroup.HasGroupChanged = true; } else { @@ -5936,7 +5973,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - prules.Target = m_host.UUID; + prules.Target = part.UUID; } break; @@ -5962,10 +5999,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } prules.CRC = 1; - m_host.AddNewParticleSystem(prules); - m_host.ParentGroup.HasGroupChanged = true; + part.AddNewParticleSystem(prules); + part.ParentGroup.HasGroupChanged = true; } - m_host.SendFullUpdateToAllClients(); + part.SendFullUpdateToAllClients(); } public void llGroundRepel(double height, int water, double tau) @@ -6759,6 +6796,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api SetPrimParams(part, rules); } + public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) + { + llSetLinkPrimitiveParams(linknumber, rules); + } + protected void SetPrimParams(SceneObjectPart part, LSL_List rules) { int idx = 0; @@ -7115,6 +7157,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api int style = rules.GetLSLIntegerItem(idx++); SetTexGen(part, face, style); break; + case (int)ScriptBaseClass.PRIM_TEXT: + if (remain < 3) + return; + string primText = rules.GetLSLStringItem(idx++); + LSL_Vector primTextColor = rules.GetVector3Item(idx++); + LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); + Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), + Util.Clip((float)primTextColor.y, 0.0f, 1.0f), + Util.Clip((float)primTextColor.z, 0.0f, 1.0f)); + part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); + + break; } } } @@ -7358,6 +7412,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return GetLinkPrimitiveParams(m_host, rules); } + public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) + { + m_host.AddScriptLPS(1); + + List parts = GetLinkParts(linknumber); + + LSL_List res = new LSL_List(); + + foreach (var part in parts) + { + LSL_List partRes = GetLinkPrimitiveParams(part, rules); + res += partRes; + } + + return res; + } + public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) { LSL_List res = new LSL_List(); @@ -7635,6 +7706,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api res.Add(new LSL_Float(0)); break; + case (int)ScriptBaseClass.PRIM_TEXT: + Color4 textColor = part.GetTextColor(); + res.Add(part.Text); + res.Add(new LSL_Vector(textColor.R, + textColor.G, + textColor.B)); + res.Add(new LSL_Float(textColor.A)); + break; } } return res; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index a74e8da..7ab04a3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -135,6 +135,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Key llGetLinkKey(int linknum); LSL_String llGetLinkName(int linknum); LSL_Integer llGetLinkNumber(); + LSL_List llGetLinkPrimitiveParams(int linknum, LSL_List rules); LSL_Integer llGetListEntryType(LSL_List src, int index); LSL_Integer llGetListLength(LSL_List src); LSL_Vector llGetLocalPos(); @@ -206,6 +207,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llInstantMessage(string user, string message); LSL_String llIntegerToBase64(int number); LSL_String llKey2Name(string id); + void llLinkParticleSystem(int linknum, LSL_List rules); LSL_String llList2CSV(LSL_List src); LSL_Float llList2Float(LSL_List src, int index); LSL_Integer llList2Integer(LSL_List src, int index); @@ -322,6 +324,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llSetLinkColor(int linknumber, LSL_Vector color, int face); void llSetLinkPrimitiveParams(int linknumber, LSL_List rules); void llSetLinkTexture(int linknumber, string texture, int face); + void llSetLinkTextureAnim(int linknum, int mode, int face, int sizex, int sizey, double start, double length, double rate); void llSetLocalRot(LSL_Rotation rot); void llSetObjectDesc(string desc); void llSetObjectName(string name); @@ -330,6 +333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llSetPayPrice(int price, LSL_List quick_pay_buttons); void llSetPos(LSL_Vector pos); void llSetPrimitiveParams(LSL_List rules); + void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); void llSetPrimURL(string url); void llSetRemoteScriptAccessPin(int pin); void llSetRot(LSL_Rotation rot); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 7cf82b2..ee35fa4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -313,6 +313,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PRIM_CAST_SHADOWS = 24; // Not implemented, here for completeness sake public const int PRIM_POINT_LIGHT = 23; // Huh? public const int PRIM_GLOW = 25; + public const int PRIM_TEXT = 26; public const int PRIM_TEXGEN_DEFAULT = 0; public const int PRIM_TEXGEN_PLANAR = 1; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index a28e97b..3339995 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -674,6 +674,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_LSL_Functions.llGetPrimitiveParams(rules); } + public LSL_List llGetLinkPrimitiveParams(int linknum, LSL_List rules) + { + return m_LSL_Functions.llGetLinkPrimitiveParams(linknum, rules); + } + public LSL_Integer llGetRegionAgentCount() { return m_LSL_Functions.llGetRegionAgentCount(); @@ -889,6 +894,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_LSL_Functions.llKey2Name(id); } + public void llLinkParticleSystem(int linknum, LSL_List rules) + { + m_LSL_Functions.llLinkParticleSystem(linknum, rules); + } + public LSL_String llList2CSV(LSL_List src) { return m_LSL_Functions.llList2CSV(src); @@ -1468,6 +1478,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_LSL_Functions.llSetLinkTexture(linknumber, texture, face); } + public void llSetLinkTextureAnim(int linknum, int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_LSL_Functions.llSetLinkTextureAnim(linknum, mode, face, sizex, sizey, start, length, rate); + } + public void llSetLocalRot(LSL_Rotation rot) { m_LSL_Functions.llSetLocalRot(rot); @@ -1508,6 +1523,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_LSL_Functions.llSetPrimitiveParams(rules); } + public void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules) + { + m_LSL_Functions.llSetLinkPrimitiveParamsFast(linknum, rules); + } + public void llSetPrimURL(string url) { m_LSL_Functions.llSetPrimURL(url); -- cgit v1.1 From 3d053b194a641c64158045720e2d82735bdfaec5 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 7 Mar 2010 16:05:24 +0000 Subject: Small consistency change --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a373046..3b2c9b1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5873,7 +5873,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api for (int i = 0; i < rules.Length; i += 2) { - switch (Convert.ToInt32(rules.Data[i])) + switch (rules.GetLSLIntegerItem(i)) { case (int)ScriptBaseClass.PSYS_PART_FLAGS: prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); -- cgit v1.1 From c8c608acc8509ebc1651b4c2dd9094cbe64dcfb8 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 7 Mar 2010 16:05:24 +0000 Subject: Small consistency change --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3154f9e..180fba9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6065,7 +6065,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api for (int i = 0; i < rules.Length; i += 2) { - switch (Convert.ToInt32(rules.Data[i])) + switch (rules.GetLSLIntegerItem(i)) { case (int)ScriptBaseClass.PSYS_PART_FLAGS: prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); -- cgit v1.1 From 49baf090cd1164b11b07fb372dff1d7b8b48c264 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 7 Mar 2010 16:05:24 +0000 Subject: Small consistency change --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 4661488..aa2c8b3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6067,7 +6067,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api for (int i = 0; i < rules.Length; i += 2) { - switch (Convert.ToInt32(rules.Data[i])) + switch (rules.GetLSLIntegerItem(i)) { case (int)ScriptBaseClass.PSYS_PART_FLAGS: prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); @@ -10191,4 +10191,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } -} \ No newline at end of file +} -- cgit v1.1 From 5caae0293ab0f69cced21923c36db230698c7970 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 3 Mar 2010 22:14:06 +0000 Subject: Fix bug where approximately half the time, attachments would rez only their root prim until right clicked (or otherwise updated). The root cause of this problem was that multiple ObjectUpdates were being sent on attachment which differed enough to confuse the client. Sometimes these would eliminate each other and sometimes not, depending on whether the scheduler looked at the queued updates. The solution here is to only schedule the ObjectUpdate once the attachment code has done all it needs to do. Backport from head. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 44 ++++++++++++--- OpenSim/Region/Framework/Scenes/Scene.cs | 40 +++++++++++--- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 62 ++++++++++++++-------- .../Region/Framework/Scenes/SceneObjectGroup.cs | 35 +++++++++--- bin/OpenSim.exe.config | 2 +- 5 files changed, 139 insertions(+), 44 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index c6cee75..5b21332 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2339,9 +2339,18 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnAttach(localID, itemID, avatarID); } - public UUID RezSingleAttachment(IClientAPI remoteClient, UUID itemID, - uint AttachmentPt) + /// + /// Called when the client receives a request to rez a single attachment on to the avatar from inventory + /// (RezSingleAttachmentFromInv packet). + /// + /// + /// + /// + /// + public UUID RezSingleAttachment(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { + m_log.DebugFormat("[USER INVENTORY]: Rezzing single attachment from item {0} for {1}", itemID, remoteClient.Name); + SceneObjectGroup att = m_sceneGraph.RezSingleAttachment(remoteClient, itemID, AttachmentPt); if (att == null) @@ -2353,9 +2362,20 @@ namespace OpenSim.Region.Framework.Scenes return RezSingleAttachment(att, remoteClient, itemID, AttachmentPt); } - public UUID RezSingleAttachment(SceneObjectGroup att, - IClientAPI remoteClient, UUID itemID, uint AttachmentPt) + /// + /// Update the user inventory to reflect an attachment + /// + /// + /// + /// + /// + /// + public UUID RezSingleAttachment(SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { + m_log.DebugFormat( + "[USER INVENTORY]: Updating inventory of {0} to show attachment of {1} (item ID {2})", + remoteClient.Name, att.Name, itemID); + if (!att.IsDeleted) AttachmentPt = att.RootPart.AttachmentPoint; @@ -2394,8 +2414,19 @@ namespace OpenSim.Region.Framework.Scenes return m_sceneGraph.AttachObject(controllingClient, localID, attachPoint, rot, pos, silent); } + /// + /// This registers the item as attached in a user's inventory + /// + /// + /// + /// + /// public void AttachObject(IClientAPI remoteClient, uint AttachmentPt, UUID itemID, SceneObjectGroup att) { +// m_log.DebugFormat( +// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", +// att.Name, remoteClient.Name, AttachmentPt, itemID); + if (UUID.Zero == itemID) { m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error inventory item ID."); @@ -2423,10 +2454,7 @@ namespace OpenSim.Region.Framework.Scenes presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); if (m_AvatarFactory != null) - { m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } - } } @@ -2509,6 +2537,7 @@ namespace OpenSim.Region.Framework.Scenes { sog.SetOwnerId(ownerID); sog.SetGroup(groupID, remoteClient); + sog.ScheduleGroupForFullUpdate(); foreach (SceneObjectPart child in sog.Children.Values) child.Inventory.ChangeInventoryOwner(ownerID); @@ -2530,6 +2559,7 @@ namespace OpenSim.Region.Framework.Scenes sog.SetOwnerId(groupID); sog.ApplyNextOwnerPermissions(); } + } foreach (uint localID in localIDs) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 41fd1e1..7796b8d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1813,14 +1813,22 @@ namespace OpenSim.Region.Framework.Scenes //m_log.DebugFormat( // "[SCENE]: Scene.AddNewPrim() pcode {0} called for {1} in {2}", shape.PCode, ownerID, RegionInfo.RegionName); + SceneObjectGroup sceneObject = null; + // If an entity creator has been registered for this prim type then use that if (m_entityCreators.ContainsKey((PCode)shape.PCode)) - return m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape); + { + sceneObject = m_entityCreators[(PCode)shape.PCode].CreateEntity(ownerID, groupID, pos, rot, shape); + } + else + { + // Otherwise, use this default creation code; + sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); + AddNewSceneObject(sceneObject, true); + sceneObject.SetGroup(groupID, null); + } - // Otherwise, use this default creation code; - SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - AddNewSceneObject(sceneObject, true); - sceneObject.SetGroup(groupID, null); + sceneObject.ScheduleGroupForFullUpdate(); return sceneObject; } @@ -1848,7 +1856,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Add a newly created object to the scene + /// Add a newly created object to the scene. Updates are also sent to viewers. /// /// /// @@ -1857,8 +1865,25 @@ namespace OpenSim.Region.Framework.Scenes /// public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) { - return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup); + return AddNewSceneObject(sceneObject, attachToBackup, true); } + + /// + /// Add a newly created object to the scene + /// + /// + /// + /// If true, the object is made persistent into the scene. + /// If false, the object will not persist over server restarts + /// + /// + /// If true, updates for the new scene object are sent to all viewers in range. + /// If false, it is left to the caller to schedule the update + /// + public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) + { + return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); + } /// /// Delete every object from the scene @@ -3322,7 +3347,6 @@ namespace OpenSim.Region.Framework.Scenes } else m_log.Debug("[SCENE]: Unable to register with InterregionCommsIn"); - } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 321cc45..d31b45e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -228,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.HasGroupChanged = true; } - return AddSceneObject(sceneObject, attachToBackup); + return AddSceneObject(sceneObject, attachToBackup, true); } /// @@ -243,12 +243,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// true if the object was added, false if an object with the same uuid was already in the scene /// - protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) + protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { // Ensure that we persist this new scene object sceneObject.HasGroupChanged = true; - return AddSceneObject(sceneObject, attachToBackup); + return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); } /// @@ -260,12 +260,19 @@ namespace OpenSim.Region.Framework.Scenes /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// - /// true if the object was added, false if an object with the same uuid was already in the scene + /// + /// If true, updates for the new scene object are sent to all viewers in range. + /// If false, it is left to the caller to schedule the update + /// + /// + /// true if the object was added, false if an object with the same uuid was already in the scene /// - protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) + protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (sceneObject == null || sceneObject.RootPart == null || sceneObject.RootPart.UUID == UUID.Zero) return false; + + bool alreadyExisted = false; if (m_parentScene.m_clampPrimSize) { @@ -286,6 +293,9 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.AttachToScene(m_parentScene); + if (sendClientUpdates) + sceneObject.ScheduleGroupForFullUpdate(); + lock (sceneObject) { if (!Entities.ContainsKey(sceneObject.UUID)) @@ -309,12 +319,14 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; } } - - return true; + } + else + { + alreadyExisted = true; } } - return false; + return alreadyExisted; } /// @@ -521,26 +533,34 @@ namespace OpenSim.Region.Framework.Scenes itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, false, false, remoteClient.AgentId, true); +// m_log.DebugFormat( +// "[SCENE GRAPH]: Retrieved single object {0} for attachment to {1} on point {2}", +// objatt.Name, remoteClient.Name, AttachmentPt); + if (objatt != null) { bool tainted = false; if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) tainted = true; - if (AttachObject( - remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false)) - { - objatt.ScheduleGroupForFullUpdate(); - if (tainted) - objatt.HasGroupChanged = true; - - // Fire after attach, so we don't get messy perms dialogs - // 3 == AttachedRez - objatt.CreateScriptInstances(0, true, m_parentScene.DefaultScriptEngine, 3); + AttachObject(remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false); + //objatt.ScheduleGroupForFullUpdate(); - // Do this last so that event listeners have access to all the effects of the attachment - m_parentScene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); - } + if (tainted) + objatt.HasGroupChanged = true; + + // Fire after attach, so we don't get messy perms dialogs + // 3 == AttachedRez + objatt.CreateScriptInstances(0, true, m_parentScene.DefaultScriptEngine, 3); + + // Do this last so that event listeners have access to all the effects of the attachment + m_parentScene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); + } + else + { + m_log.WarnFormat( + "[SCENE GRAPH]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", + itemID, remoteClient.Name, AttachmentPt); } return objatt; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c5a6171..c14b39a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -567,8 +567,10 @@ namespace OpenSim.Region.Framework.Scenes } ApplyPhysics(m_scene.m_physicalPrim); - - ScheduleGroupForFullUpdate(); + + // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled + // for the same object with very different properties. The caller must schedule the update. + //ScheduleGroupForFullUpdate(); } public Vector3 GroupScale() @@ -956,10 +958,11 @@ namespace OpenSim.Region.Framework.Scenes // don't attach attachments to child agents if (avatar.IsChildAgent) return; +// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name); + DetachFromBackup(); // Remove from database and parcel prim count - // m_scene.DeleteFromStorage(UUID); m_scene.EventManager.TriggerParcelPrimCountTainted(); @@ -985,7 +988,6 @@ namespace OpenSim.Region.Framework.Scenes SetAttachmentPoint(Convert.ToByte(attachmentpoint)); avatar.AddAttachment(this); - m_log.Debug("[SOG]: Added attachment " + UUID + " to avatar " + avatar.UUID); if (!silent) { @@ -1002,6 +1004,12 @@ namespace OpenSim.Region.Framework.Scenes ScheduleGroupForFullUpdate(); } } + else + { + m_log.WarnFormat( + "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present", + UUID, agentID, Scene.RegionInfo.RegionName); + } } public byte GetAttachmentPoint() @@ -1986,6 +1994,8 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleFullUpdateToAvatar(ScenePresence presence) { +// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); + RootPart.AddFullUpdateToAvatar(presence); lock (m_parts) @@ -2000,6 +2010,8 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleTerseUpdateToAvatar(ScenePresence presence) { +// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); + lock (m_parts) { foreach (SceneObjectPart part in m_parts.Values) @@ -2014,6 +2026,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForFullUpdate() { +// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); + checkAtTargets(); RootPart.ScheduleFullUpdate(); @@ -2032,6 +2046,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForTerseUpdate() { +// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); + lock (m_parts) { foreach (SceneObjectPart part in m_parts.Values) @@ -2045,9 +2061,11 @@ namespace OpenSim.Region.Framework.Scenes /// Immediately send a full update for this scene object. /// public void SendGroupFullUpdate() - { + { if (IsDeleted) return; + +// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); RootPart.SendFullUpdateToAllClients(); @@ -2064,7 +2082,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Immediately send an update for this scene object's root prim only. /// This is for updates regarding the object as a whole, and none of its parts in particular. - /// Note: this may not be cused by opensim (it probably should) but it's used by + /// Note: this may not be used by opensim (it probably should) but it's used by /// external modules. /// public void SendGroupRootTerseUpdate() @@ -2079,6 +2097,7 @@ namespace OpenSim.Region.Framework.Scenes { if (m_scene == null) // Need to check here as it's null during object creation return; + m_scene.SceneGraph.AddToUpdateList(this); } @@ -3557,7 +3576,9 @@ namespace OpenSim.Region.Framework.Scenes HasGroupChanged = true; } - ScheduleGroupForFullUpdate(); + // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled + // for the same object with very different properties. The caller must schedule the update. + //ScheduleGroupForFullUpdate(); } public void TriggerScriptChangedEvent(Changed val) diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index 3c7adf5..4e7ef51 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -12,7 +12,7 @@ - + -- cgit v1.1 From 4423630f1e77d7bb5a2b01f7ba9ed539d0825de8 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 9 Mar 2010 18:56:32 +0000 Subject: remove milliseconds from console log again --- bin/OpenSim.exe.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index 4e7ef51..3c7adf5 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -12,7 +12,7 @@ - + -- cgit v1.1 From 06e351f1ef83217ac5f9ab479120cd23a68a6012 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 9 Mar 2010 22:28:52 +0000 Subject: Revert "Adds land ejection and freezing. Adds more checks to land banning." This reverts commit 44d523518af31075c77653eacc7489220db4abaa. --- .../CoreModules/World/Land/LandManagementModule.cs | 128 ++++----------------- 1 file changed, 25 insertions(+), 103 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index ef3e722..33d16d5 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -161,10 +161,6 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelInfoRequest += ClientOnParcelInfoRequest; client.OnParcelDwellRequest += ClientOnParcelDwellRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; - client.OnParcelGodMark += ClientOnParcelGodMark; - client.OnSimWideDeletes += ClientOnSimWideDeletes; - client.OnParcelFreezeUser += ClientOnParcelFreezeUser; - client.OnParcelEjectUser += ClientOnParcelEjectUser; EntityBase presenceEntity; if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) @@ -273,7 +269,22 @@ namespace OpenSim.Region.CoreModules.World.Land return parcelsNear; } - + public void KickUserOffOfParcel(ScenePresence avatar) + { + if (avatar.GodLevel == 0) + { + List parcelsNear = ParcelsNearPoint(avatar.AbsolutePosition); + foreach (ILandObject check in parcelsNear) + { + if (check.IsEitherBannedOrRestricted(avatar.UUID) != true) + { + Vector3 target = check.LandData.UserLocation; + avatar.TeleportWithMomentum(target); + return; + } + } + } + } public void MoveUserOutOfParcel(ScenePresence avatar) { if (avatar.GodLevel == 0) @@ -290,6 +301,7 @@ namespace OpenSim.Region.CoreModules.World.Land { Vector3 target = new Vector3(avatar.AbsolutePosition.X + x, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); avatar.TeleportWithMomentum(target); + avatar.Velocity = new Vector3(-avatar.Velocity.X - 5, avatar.Velocity.Y, avatar.Velocity.Z); return; } } @@ -303,73 +315,11 @@ namespace OpenSim.Region.CoreModules.World.Land { Vector3 target = new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y + y, avatar.AbsolutePosition.Z); avatar.TeleportWithMomentum(target); + avatar.Velocity = new Vector3(avatar.Velocity.X, -avatar.Velocity.Y - 5, avatar.Velocity.Z); return; } } } - List allParcels = new List(); - allParcels = AllParcels(); - if (allParcels.Count != 1) - { - foreach (ILandObject parcel in allParcels) - { - if (parcel.IsEitherBannedOrRestricted(avatar.UUID) != true) - { - Vector3 temptarget = parcel.LandData.UserLocation; - if (parcel.ContainsPoint((int)parcel.LandData.UserLocation.X, (int)parcel.LandData.UserLocation.Y)) - { - avatar.TeleportWithMomentum(temptarget); - return; - } - else - { - for (int x = 0; x <= Constants.RegionSize / 3; x += 3) - { - for (int y = 0; y <= Constants.RegionSize / 3; y += 3) - { - if (parcel.ContainsPoint(x, y)) - { - temptarget = new Vector3(x, y, avatar.AbsolutePosition.Z); - avatar.TeleportWithMomentum(temptarget); - return; - } - } - } - } - } - } - } - //Move to region side - if (avatar.AbsolutePosition.X > avatar.AbsolutePosition.Y) - { - if (avatar.AbsolutePosition.X > .5 * Constants.RegionSize) - { - Vector3 target = new Vector3(Constants.RegionSize, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); ; - avatar.TeleportWithMomentum(target); - return; - } - else - { - Vector3 target = new Vector3(0, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); ; - avatar.TeleportWithMomentum(target); - return; - } - } - else - { - if (avatar.AbsolutePosition.Y > .5 * Constants.RegionSize) - { - Vector3 target = new Vector3(avatar.AbsolutePosition.X, Constants.RegionSize, avatar.AbsolutePosition.Z); ; - avatar.TeleportWithMomentum(target); - return; - } - else - { - Vector3 target = new Vector3(avatar.AbsolutePosition.X, 0, avatar.AbsolutePosition.Z); ; - avatar.TeleportWithMomentum(target); - return; - } - } } } @@ -412,12 +362,12 @@ namespace OpenSim.Region.CoreModules.World.Land { if (checkBan.IsRestrictedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, true, (int)ParcelResult.Multiple, avatar.ControllingClient); + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar.ControllingClient); return; } if (checkBan.IsBannedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, true, (int)ParcelResult.Multiple, avatar.ControllingClient); + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar.ControllingClient); return; } } @@ -432,12 +382,12 @@ namespace OpenSim.Region.CoreModules.World.Land { if (checkBan.IsRestrictedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, true, (int)ParcelResult.Multiple, avatar.ControllingClient); + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar.ControllingClient); return; } if (checkBan.IsBannedFromLand(avatar.ControllingClient.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, true, (int)ParcelResult.Multiple, avatar.ControllingClient); + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar.ControllingClient); return; } } @@ -545,18 +495,6 @@ namespace OpenSim.Region.CoreModules.World.Land if (m_scene.Permissions.CanEditParcel(agentID, land)) { land.UpdateAccessList(flags, entries, remote_client); - List presences = ((Scene)remote_client.Scene).GetAvatars(); - foreach (ScenePresence presence in presences) - { - land = GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); - if (land != null) - { - if (land.IsEitherBannedOrRestricted(presence.UUID)) - { - MoveUserOutOfParcel(presence); - } - } - } } } else @@ -1122,25 +1060,7 @@ namespace OpenSim.Region.CoreModules.World.Land m_landList.TryGetValue(localID, out land); } - if (land != null) - { - land.UpdateLandProperties(args, remote_client); - if ((args.ParcelFlags & (uint)(ParcelFlags.UseBanList | ParcelFlags.UseAccessList | ParcelFlags.UseAccessGroup | ParcelFlags.UsePassList)) != 0) - { - List presences = ((Scene)remote_client.Scene).GetAvatars(); - foreach (ScenePresence presence in presences) - { - land = GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); - if (land != null) - { - if (land.IsEitherBannedOrRestricted(presence.UUID)) - { - MoveUserOutOfParcel(presence); - } - } - } - } - } + if (land != null) land.UpdateLandProperties(args, remote_client); } public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) @@ -1552,6 +1472,7 @@ namespace OpenSim.Region.CoreModules.World.Land UpdateLandObject(localID, land.LandData); } + public void ClientOnParcelGodMark(IClientAPI client, UUID god, int landID) { ILandObject land = null; @@ -1567,6 +1488,7 @@ namespace OpenSim.Region.CoreModules.World.Land land.LandData.Name = DefaultGodParcelName; land.SendLandUpdateToAvatarsOverMe(); } + private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID) { ScenePresence SP; -- cgit v1.1 From 80b5a95bb8f640efaf61eee810341f5951dfda6a Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 9 Mar 2010 22:29:02 +0000 Subject: Revert "Adds Land Banning." This reverts commit a87d7a12967b50fe83ebbaa7b57e531eb93158a2. --- .../CoreModules/World/Land/LandManagementModule.cs | 130 ++++++++------------- .../Region/CoreModules/World/Land/LandObject.cs | 48 ++------ 2 files changed, 58 insertions(+), 120 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 33d16d5..8c3d17d 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -269,57 +269,20 @@ namespace OpenSim.Region.CoreModules.World.Land return parcelsNear; } - public void KickUserOffOfParcel(ScenePresence avatar) + public void SendYouAreBannedNotice(ScenePresence avatar) { - if (avatar.GodLevel == 0) + if (AllowedForcefulBans) { - List parcelsNear = ParcelsNearPoint(avatar.AbsolutePosition); - foreach (ILandObject check in parcelsNear) - { - if (check.IsEitherBannedOrRestricted(avatar.UUID) != true) - { - Vector3 target = check.LandData.UserLocation; - avatar.TeleportWithMomentum(target); - return; - } - } + avatar.ControllingClient.SendAlertMessage( + "You are not allowed on this parcel because you are banned. Please go away."); + + avatar.PhysicsActor.Position = avatar.lastKnownAllowedPosition; + avatar.PhysicsActor.Velocity = Vector3.Zero; } - } - public void MoveUserOutOfParcel(ScenePresence avatar) - { - if (avatar.GodLevel == 0) + else { - ILandObject land = m_scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); - List parcelsNear = new List(); - - for (int x = -2; x <= 2; x += 2) - { - ILandObject check = GetLandObject(avatar.AbsolutePosition.X + x, avatar.AbsolutePosition.Y); - if (check != null) - { - if (check.IsEitherBannedOrRestricted(avatar.UUID) != true) - { - Vector3 target = new Vector3(avatar.AbsolutePosition.X + x, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); - avatar.TeleportWithMomentum(target); - avatar.Velocity = new Vector3(-avatar.Velocity.X - 5, avatar.Velocity.Y, avatar.Velocity.Z); - return; - } - } - } - for (int y = -2; y <= 2; y += 2) - { - ILandObject check = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y + y); - if (check != null) - { - if (check.IsEitherBannedOrRestricted(avatar.UUID) != true) - { - Vector3 target = new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y + y, avatar.AbsolutePosition.Z); - avatar.TeleportWithMomentum(target); - avatar.Velocity = new Vector3(avatar.Velocity.X, -avatar.Velocity.Y - 5, avatar.Velocity.Z); - return; - } - } - } + avatar.ControllingClient.SendAlertMessage( + "You are not allowed on this parcel because you are banned; however, the grid administrator has disabled ban lines globally. Please obey the land owner's requests or you can be banned from the entire sim!"); } } @@ -339,7 +302,16 @@ namespace OpenSim.Region.CoreModules.World.Land { if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID)) { - MoveUserOutOfParcel(avatar); + SendYouAreBannedNotice(avatar); + } + else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID)) + { + avatar.ControllingClient.SendAlertMessage( + "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!)."); + } + else + { + avatar.sentMessageAboutRestrictedParcelFlyingDown = true; } } else @@ -350,47 +322,28 @@ namespace OpenSim.Region.CoreModules.World.Land } } - public void SendOutNearestBanLine(ScenePresence avatar) + public void SendOutNearestBanLine(IClientAPI avatar) { - ILandObject checkBan = null; - for (int x = -2; x <= 2; x += 2) - { - checkBan = GetLandObject(avatar.AbsolutePosition.X + x, avatar.AbsolutePosition.Y); - if (checkBan != null) - { - if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) - { - if (checkBan.IsRestrictedFromLand(avatar.ControllingClient.AgentId)) - { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar.ControllingClient); - return; - } - if (checkBan.IsBannedFromLand(avatar.ControllingClient.AgentId)) - { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar.ControllingClient); - return; - } - } - } - } - for (int y = -2; y <= 2; y += 2) + List avatars = m_scene.GetAvatars(); + foreach (ScenePresence presence in avatars) { - checkBan = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y + y); - if (checkBan != null) + if (presence.UUID == avatar.AgentId) { - if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) + List checkLandParcels = ParcelsNearPoint(presence.AbsolutePosition); + foreach (ILandObject checkBan in checkLandParcels) { - if (checkBan.IsRestrictedFromLand(avatar.ControllingClient.AgentId)) + if (checkBan.IsBannedFromLand(avatar.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar.ControllingClient); - return; + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar); + return; //Only send one } - if (checkBan.IsBannedFromLand(avatar.ControllingClient.AgentId)) + if (checkBan.IsRestrictedFromLand(avatar.AgentId)) { - checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionBanned, false, (int)ParcelResult.Single, avatar.ControllingClient); - return; + checkBan.SendLandProperties((int)ParcelPropertiesStatus.CollisionNotOnAccessList, false, (int)ParcelResult.Single, avatar); + return; //Only send one } } + return; } } } @@ -437,14 +390,25 @@ namespace OpenSim.Region.CoreModules.World.Land if (clientAvatar != null) { SendLandUpdate(clientAvatar); - SendOutNearestBanLine(clientAvatar); + SendOutNearestBanLine(remote_client); ILandObject parcel = GetLandObject(clientAvatar.AbsolutePosition.X, clientAvatar.AbsolutePosition.Y); if (parcel != null) { if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && + clientAvatar.sentMessageAboutRestrictedParcelFlyingDown) + { + EventManagerOnAvatarEnteringNewParcel(clientAvatar, parcel.LandData.LocalID, + m_scene.RegionInfo.RegionID); + //They are going under the safety line! + if (!parcel.IsBannedFromLand(clientAvatar.UUID)) + { + clientAvatar.sentMessageAboutRestrictedParcelFlyingDown = false; + } + } + else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && parcel.IsBannedFromLand(clientAvatar.UUID)) { - MoveUserOutOfParcel(clientAvatar); + SendYouAreBannedNotice(clientAvatar); } } } @@ -492,7 +456,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (land != null) { - if (m_scene.Permissions.CanEditParcel(agentID, land)) + if (agentID == land.LandData.OwnerID) { land.UpdateAccessList(flags, entries, remote_client); } diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 1c65965..1fa8630 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -267,7 +267,11 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsEitherBannedOrRestricted(UUID avatar) { - if (IsRestrictedFromLand(avatar) || IsBannedFromLand(avatar)) + if (IsBannedFromLand(avatar)) + { + return true; + } + else if (IsRestrictedFromLand(avatar)) { return true; } @@ -276,8 +280,7 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsBannedFromLand(UUID avatar) { - ScenePresence SP = m_scene.GetScenePresence(avatar); - if ((LandData.Flags & (uint)ParcelFlags.UseBanList) > 0) + if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) { ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); entry.AgentID = avatar; @@ -285,22 +288,8 @@ namespace OpenSim.Region.CoreModules.World.Land entry.Time = new DateTime(); if (LandData.ParcelAccessList.Contains(entry)) { - if ((LandData.Flags & (uint)ParcelFlags.UseAccessGroup) > 0) - { - if (LandData.GroupID == SP.ControllingClient.ActiveGroupId) - { - return false; - } - else - { - //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel - return true; - } - } - else - { - return true; - } + //They are banned, so lets send them a notice about this parcel + return true; } } return false; @@ -308,8 +297,7 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsRestrictedFromLand(UUID avatar) { - ScenePresence SP = m_scene.GetScenePresence(avatar); - if ((LandData.Flags & (uint)ParcelFlags.UseAccessList) > 0) + if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) { ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); entry.AgentID = avatar; @@ -317,22 +305,8 @@ namespace OpenSim.Region.CoreModules.World.Land entry.Time = new DateTime(); if (!LandData.ParcelAccessList.Contains(entry)) { - if ((LandData.Flags & (uint)ParcelFlags.UseAccessGroup) > 0) - { - if (LandData.GroupID == SP.ControllingClient.ActiveGroupId) - { - return false; - } - else - { - //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel - return true; - } - } - else - { - return true; - } + //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel + return true; } } return false; -- cgit v1.1 From fce9e499e4682edf6db7b4f9c5546524b4a25197 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 8 Mar 2010 01:19:45 -0600 Subject: - parcel blocking, region crossing blocking, teleport blocking --- OpenSim/Client/MXP/ClientStack/MXPClientView.cs | 1 + .../Sirikata/ClientStack/SirikataClientView.cs | 1 + .../Client/VWoHTTP/ClientStack/VWHClientView.cs | 1 + OpenSim/Framework/IClientAPI.cs | 1 + .../Region/ClientStack/LindenUDP/LLClientView.cs | 4 + .../CoreModules/World/Land/LandManagementModule.cs | 93 ++++++++- .../Region/CoreModules/World/Land/LandObject.cs | 9 +- .../Region/Examples/SimpleModule/MyNpcCharacter.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.cs | 229 +++++++++++++++++++++ .../Server/IRCClientView.cs | 1 + .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 1 + OpenSim/Tests/Common/Mock/TestClient.cs | 1 + 12 files changed, 333 insertions(+), 10 deletions(-) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 7b9faa9..f8cfe44 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -598,6 +598,7 @@ namespace OpenSim.Client.MXP.ClientStack public event Action OnRegionHandShakeReply; public event GenericCall2 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; + public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index b7ead6e..3bf73d6 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -244,6 +244,7 @@ namespace OpenSim.Client.Sirikata.ClientStack public event Action OnRegionHandShakeReply; public event GenericCall2 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; + public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index d51277b..894fdac 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -247,6 +247,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack public event Action OnRegionHandShakeReply = delegate { }; public event GenericCall2 OnRequestWearables = delegate { }; public event GenericCall1 OnCompleteMovementToRegion = delegate { }; + public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate = delegate { }; public event AgentRequestSit OnAgentRequestSit = delegate { }; public event AgentSit OnAgentSit = delegate { }; diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 7219bf8..3126e57 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -881,6 +881,7 @@ namespace OpenSim.Framework event Action OnRegionHandShakeReply; event GenericCall2 OnRequestWearables; event GenericCall1 OnCompleteMovementToRegion; + event UpdateAgent OnPreAgentUpdate; event UpdateAgent OnAgentUpdate; event AgentRequestSit OnAgentRequestSit; event AgentSit OnAgentSit; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 2c8d88b..ea73abb 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -127,6 +127,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event ObjectDeselect OnObjectDetach; public event ObjectDrop OnObjectDrop; public event GenericCall1 OnCompleteMovementToRegion; + public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; @@ -4880,7 +4881,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP UpdateAgent handlerAgentUpdate = OnAgentUpdate; lastarg = arg; // save this set of arguments for nexttime if (handlerAgentUpdate != null) + { + OnPreAgentUpdate(this, arg); OnAgentUpdate(this, arg); + } handlerAgentUpdate = null; } diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 8c3d17d..e0cdb36 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Reflection; using log4net; using Nini.Config; @@ -86,6 +87,7 @@ namespace OpenSim.Region.CoreModules.World.Land // caches ExtendedLandData private Cache parcelInfoCache; + private Vector3? forcedPosition = null; #region INonSharedRegionModule Members @@ -144,6 +146,13 @@ namespace OpenSim.Region.CoreModules.World.Land { } + private bool OnVerifyUserConnection(ScenePresence scenePresence, out string reason) + { + ILandObject nearestParcel = m_scene.GetNearestAllowedParcel(scenePresence.UUID, scenePresence.AbsolutePosition.X, scenePresence.AbsolutePosition.Y); + reason = "You are not allowed to enter this sim."; + return nearestParcel != null; + } + void EventManagerOnNewClient(IClientAPI client) { //Register some client events @@ -161,6 +170,7 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelInfoRequest += ClientOnParcelInfoRequest; client.OnParcelDwellRequest += ClientOnParcelDwellRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; + client.OnPreAgentUpdate += ClientOnPreAgentUpdate; EntityBase presenceEntity; if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence) @@ -170,6 +180,40 @@ namespace OpenSim.Region.CoreModules.World.Land } } + void ClientOnPreAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) + { + //If we are forcing a position for them to go + if( forcedPosition != null ) + { + ScenePresence clientAvatar = m_scene.GetScenePresence(remoteClient.AgentId); + + //Putting the user into flying, both keeps the avatar in fligth when it bumps into something and stopped from going another direction AND + //When the avatar walks into a ban line on the ground, it prevents getting stuck + agentData.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; + + + //Make sure we stop if they get about to the right place to prevent yoyo and prevents getting stuck on banlines + if (Vector3.Distance(clientAvatar.AbsolutePosition, forcedPosition.Value) < .2) + { + Debug.WriteLine(string.Format("Stopping force position because {0} is close enough to position {1}", forcedPosition.Value, clientAvatar.AbsolutePosition)); + forcedPosition = null; + } + //if we are far away, teleport + else if(Vector3.Distance(clientAvatar.AbsolutePosition,forcedPosition.Value) > 3 ) + { + Debug.WriteLine(string.Format("Teleporting out because {0} is too far from avatar position {1}",forcedPosition.Value,clientAvatar.AbsolutePosition)); + clientAvatar.Teleport(forcedPosition.Value); + forcedPosition = null; + } + else + { + //Forces them toward the forced position we want if they aren't there yet + agentData.UseClientAgentPosition = true; + agentData.ClientAgentPosition = forcedPosition.Value; + } + } + } + public void PostInitialise() { @@ -275,9 +319,6 @@ namespace OpenSim.Region.CoreModules.World.Land { avatar.ControllingClient.SendAlertMessage( "You are not allowed on this parcel because you are banned. Please go away."); - - avatar.PhysicsActor.Position = avatar.lastKnownAllowedPosition; - avatar.PhysicsActor.Velocity = Vector3.Zero; } else { @@ -286,6 +327,24 @@ namespace OpenSim.Region.CoreModules.World.Land } } + + + private void ForceAvatarToPosition(ScenePresence avatar, Vector3? position) + { + if (m_scene.Permissions.IsGod(avatar.UUID)) return; + if (position.HasValue) + { + forcedPosition = position; + } + } + + public void SendYouAreRestrictedNotice(ScenePresence avatar) + { + avatar.ControllingClient.SendAlertMessage( + "You are not allowed on this parcel because the land owner has restricted access."); + + } + public void EventManagerOnAvatarEnteringNewParcel(ScenePresence avatar, int localLandID, UUID regionID) { if (m_scene.RegionInfo.RegionID == regionID) @@ -303,11 +362,12 @@ namespace OpenSim.Region.CoreModules.World.Land if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID)) { SendYouAreBannedNotice(avatar); + ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar)); } else if (parcelAvatarIsEntering.IsRestrictedFromLand(avatar.UUID)) { - avatar.ControllingClient.SendAlertMessage( - "You are not allowed on this parcel because the land owner has restricted access. For now, you can enter, but please respect the land owner's decisions (or he can ban you!)."); + SendYouAreRestrictedNotice(avatar); + ForceAvatarToPosition(avatar, m_scene.GetNearestAllowedPosition(avatar)); } else { @@ -408,7 +468,26 @@ namespace OpenSim.Region.CoreModules.World.Land else if (clientAvatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT && parcel.IsBannedFromLand(clientAvatar.UUID)) { - SendYouAreBannedNotice(clientAvatar); + //once we've sent the message once, keep going toward the target until we are done + if (forcedPosition == null) + { + SendYouAreBannedNotice(clientAvatar); + ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar)); + } + } + else if ( parcel.IsRestrictedFromLand(clientAvatar.UUID)) + { + //once we've sent the message once, keep going toward the target until we are done + if (forcedPosition == null) + { + SendYouAreRestrictedNotice(clientAvatar); + ForceAvatarToPosition(clientAvatar, m_scene.GetNearestAllowedPosition(clientAvatar)); + } + } + else + { + //when we are finally in a safe place, lets release the forced position lock + forcedPosition = null; } } } @@ -420,7 +499,7 @@ namespace OpenSim.Region.CoreModules.World.Land ILandObject over = GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); if (over != null) { - if (!over.IsBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT) + if (!over.IsRestrictedFromLand(avatar.UUID) && (!over.IsBannedFromLand(avatar.UUID) || avatar.AbsolutePosition.Z >= LandChannel.BAN_LINE_SAFETY_HIEGHT)) { avatar.lastKnownAllowedPosition = new Vector3(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 1fa8630..27d9fdb 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -104,7 +104,7 @@ namespace OpenSim.Region.CoreModules.World.Land /// Returns true if the piece of land contains the specified point public bool ContainsPoint(int x, int y) { - if (x >= 0 && y >= 0 && x <= Constants.RegionSize && x <= Constants.RegionSize) + if (x >= 0 && y >= 0 && x <= Constants.RegionSize && y <= Constants.RegionSize) { return (LandBitmap[x / 4, y / 4] == true); } @@ -286,7 +286,8 @@ namespace OpenSim.Region.CoreModules.World.Land entry.AgentID = avatar; entry.Flags = AccessList.Ban; entry.Time = new DateTime(); - if (LandData.ParcelAccessList.Contains(entry)) + //See if they are on the list, but make sure the owner isn't banned + if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar ) { //They are banned, so lets send them a notice about this parcel return true; @@ -303,7 +304,9 @@ namespace OpenSim.Region.CoreModules.World.Land entry.AgentID = avatar; entry.Flags = AccessList.Access; entry.Time = new DateTime(); - if (!LandData.ParcelAccessList.Contains(entry)) + + //If they are not on the access list and are not the owner + if (!LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) { //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel return true; diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 58e3de9..c2753d9 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -84,6 +84,7 @@ namespace OpenSim.Region.Examples.SimpleModule public event Action OnRegionHandShakeReply; public event GenericCall2 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; + public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 388bc99..884f13a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; @@ -3251,6 +3252,7 @@ namespace OpenSim.Region.Framework.Scenes /// also return a reason. public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason) { + TeleportFlags tp = (TeleportFlags)teleportFlags; //Teleport flags: // // TeleportFlags.ViaGodlikeLure - Border Crossing @@ -3284,6 +3286,17 @@ namespace OpenSim.Region.Framework.Scenes CapsModule.NewUserConnection(agent); + ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); + + //On login or border crossing test land permisions + if (tp != TeleportFlags.Default) + { + if (land != null && !TestLandRestrictions(agent, land, out reason)) + { + return false; + } + } + ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID); if (sp != null) { @@ -3377,6 +3390,40 @@ namespace OpenSim.Region.Framework.Scenes return true; } + private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) + { + + bool banned = land.IsBannedFromLand(agent.AgentID); + bool restricted = land.IsRestrictedFromLand(agent.AgentID); + + if (banned || restricted) + { + ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); + if (nearestParcel != null) + { + //Move agent to nearest allowed + Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); + agent.startpos.X = newPosition.X; + agent.startpos.Y = newPosition.Y; + } + else + { + if (banned) + { + reason = "Cannot regioncross into banned parcel."; + } + else + { + reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", + RegionInfo.RegionName); + } + return false; + } + } + reason = ""; + return true; + } + /// /// Verifies that the user has a presence on the Grid /// @@ -3508,6 +3555,18 @@ namespace OpenSim.Region.Framework.Scenes return true; } + private ILandObject GetParcelAtPoint(float x, float y) + { + foreach (var parcel in AllParcels()) + { + if( parcel.ContainsPoint((int)x,(int)y)) + { + return parcel; + } + } + return null; + } + /// /// Update an AgentCircuitData object with new information /// @@ -4780,5 +4839,175 @@ namespace OpenSim.Region.Framework.Scenes { get { return m_allowScriptCrossings; } } + + public Vector3? GetNearestAllowedPosition(ScenePresence avatar) + { + //simulate to make sure we have pretty up to date positions + PhysicsScene.Simulate(0); + + ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + + if (nearestParcel != null) + { + Vector3 dir = Vector3.Normalize(Vector3.Multiply(avatar.Velocity, -1)); + //Try to get a location that feels like where they came from + Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); + if (nearestPoint != null) + { + Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString()); + return nearestPoint.Value; + } + + //Sometimes velocity might be zero (local teleport), so try finding point along path from avatar to center of nearest parcel + Vector3 directionToParcelCenter = Vector3.Subtract(GetParcelCenterAtGround(nearestParcel), avatar.AbsolutePosition); + dir = Vector3.Normalize(directionToParcelCenter); + nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); + if (nearestPoint != null) + { + Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString()); + return nearestPoint.Value; + } + + //Ultimate backup if we have no idea where they are + Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString()); + return avatar.lastKnownAllowedPosition; + + } + + //Go to the edge, this happens in teleporting to a region with no available parcels + Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); + //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); + return nearestRegionEdgePoint; + return null; + } + + private Vector3 GetParcelCenterAtGround(ILandObject parcel) + { + Vector2 center = GetParcelCenter(parcel); + return GetPositionAtGround(center.X, center.Y); + } + + private Vector3? GetNearestPointInParcelAlongDirectionFromPoint(Vector3 pos, Vector3 direction, ILandObject parcel) + { + Vector3 unitDirection = Vector3.Normalize(direction); + //Making distance to search go through some sane limit of distance + for (float distance = 0; distance < Constants.RegionSize * 2; distance += .5f) + { + Vector3 testPos = Vector3.Add(pos, Vector3.Multiply(unitDirection, distance)); + if (parcel.ContainsPoint((int)testPos.X, (int)testPos.Y)) + { + return testPos; + } + } + return null; + } + + public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) + { + List all = AllParcels(); + float minParcelDistance = float.MaxValue; + ILandObject nearestParcel = null; + + foreach (var parcel in all) + { + if (!parcel.IsEitherBannedOrRestricted(avatarId)) + { + float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); + if (parcelDistance < minParcelDistance) + { + minParcelDistance = parcelDistance; + nearestParcel = parcel; + } + } + } + + return nearestParcel; + } + + private List AllParcels() + { + return LandChannel.AllParcels(); + } + + private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y) + { + return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel)); + } + + //calculate the average center point of a parcel + private Vector2 GetParcelCenter(ILandObject parcel) + { + int count = 0; + int avgx = 0; + int avgy = 0; + for (int x = 0; x < Constants.RegionSize; x++) + { + for (int y = 0; y < Constants.RegionSize; y++) + { + //Just keep a running average as we check if all the points are inside or not + if (parcel.ContainsPoint(x, y)) + { + if (count == 0) + { + avgx = x; + avgy = y; + } + else + { + avgx = (avgx * count + x) / (count + 1); + avgy = (avgy * count + y) / (count + 1); + } + count += 1; + } + } + } + return new Vector2(avgx, avgy); + } + + private Vector3 GetNearestRegionEdgePosition(ScenePresence avatar) + { + float xdistance = avatar.AbsolutePosition.X < Constants.RegionSize / 2 ? avatar.AbsolutePosition.X : Constants.RegionSize - avatar.AbsolutePosition.X; + float ydistance = avatar.AbsolutePosition.Y < Constants.RegionSize / 2 ? avatar.AbsolutePosition.Y : Constants.RegionSize - avatar.AbsolutePosition.Y; + + //find out what vertical edge to go to + if (xdistance < ydistance) + { + if (avatar.AbsolutePosition.X < Constants.RegionSize / 2) + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, 0.0f, avatar.AbsolutePosition.Y); + } + else + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, Constants.RegionSize, avatar.AbsolutePosition.Y); + } + } + //find out what horizontal edge to go to + else + { + if (avatar.AbsolutePosition.Y < Constants.RegionSize / 2) + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, 0.0f); + } + else + { + return GetPositionAtAvatarHeightOrGroundHeight(avatar, avatar.AbsolutePosition.X, Constants.RegionSize); + } + } + } + + private Vector3 GetPositionAtAvatarHeightOrGroundHeight(ScenePresence avatar, float x, float y) + { + Vector3 ground = GetPositionAtGround(x, y); + if( avatar.AbsolutePosition.Z > ground.Z) + { + ground.Z = avatar.AbsolutePosition.Z; + } + return ground; + } + + private Vector3 GetPositionAtGround(float x, float y) + { + return new Vector3(x, y, GetGroundHeight(x, y)); + } } } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 99e5b84..711052c 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -680,6 +680,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event Action OnRegionHandShakeReply; public event GenericCall2 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; + public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 15473d8..ebf9333 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -190,6 +190,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event Action OnRegionHandShakeReply; public event GenericCall2 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; + public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 0d9dcc6..715e1a4 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -96,6 +96,7 @@ namespace OpenSim.Tests.Common.Mock public event Action OnRegionHandShakeReply; public event GenericCall2 OnRequestWearables; public event GenericCall1 OnCompleteMovementToRegion; + public event UpdateAgent OnPreAgentUpdate; public event UpdateAgent OnAgentUpdate; public event AgentRequestSit OnAgentRequestSit; public event AgentSit OnAgentSit; -- cgit v1.1 From 689514a40a52d71f9cfaaedbb295a57b1d7c728a Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 9 Mar 2010 23:10:14 +0000 Subject: Cache UserLevel in ScenePresence on SP creation. Change IsAdministrator to use that stored value. --- .../World/Permissions/PermissionsModule.cs | 8 +++++++ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 28 +++++++++++++++------- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 2211f3e..845c4c2 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -490,6 +490,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_allowGridGods) { + ScenePresence sp = m_scene.GetScenePresence(user); + if (sp != null) + { + if (sp.UserLevel >= 200) + return true; + return false; + } + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, user); if (account != null) { diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 93e66e0..f1be4d8 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -150,7 +150,8 @@ namespace OpenSim.Region.Framework.Scenes private float m_sitAvatarHeight = 2.0f; - private float m_godlevel; + private int m_godLevel; + private int m_userLevel; private bool m_invulnerable = true; @@ -304,9 +305,14 @@ namespace OpenSim.Region.Framework.Scenes get { return m_invulnerable; } } - public float GodLevel + public int UserLevel { - get { return m_godlevel; } + get { return m_userLevel; } + } + + public int GodLevel + { + get { return m_godLevel; } } public ulong RegionHandle @@ -678,6 +684,10 @@ namespace OpenSim.Region.Framework.Scenes m_regionInfo = reginfo; m_localId = m_scene.AllocateLocalId(); + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); + + m_userLevel = account.UserLevel; + IGroupsModule gm = m_scene.RequestModuleInterface(); if (gm != null) m_grouptitle = gm.GetGroupTitle(m_uuid); @@ -3164,17 +3174,17 @@ namespace OpenSim.Region.Framework.Scenes if (account != null) { if (account.UserLevel > 0) - m_godlevel = account.UserLevel; + m_godLevel = account.UserLevel; else - m_godlevel = 200; + m_godLevel = 200; } } else { - m_godlevel = 0; + m_godLevel = 0; } - ControllingClient.SendAdminResponse(token, (uint)m_godlevel); + ControllingClient.SendAdminResponse(token, (uint)m_godLevel); } #region Child Agent Updates @@ -3265,7 +3275,7 @@ namespace OpenSim.Region.Framework.Scenes cAgent.ControlFlags = (uint)m_AgentControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) - cAgent.GodLevel = (byte)m_godlevel; + cAgent.GodLevel = (byte)m_godLevel; else cAgent.GodLevel = (byte) 0; @@ -3354,7 +3364,7 @@ namespace OpenSim.Region.Framework.Scenes m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) - m_godlevel = cAgent.GodLevel; + m_godLevel = cAgent.GodLevel; m_setAlwaysRun = cAgent.AlwaysRun; uint i = 0; -- cgit v1.1 From f6f6ef1532517972b973d8a500818dcd50873352 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 11 Mar 2010 19:12:38 -0500 Subject: Dynamics Integration Part 1 --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 11 +- OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs | 817 ----- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 3816 ++++++++++++-------- 3 files changed, 2266 insertions(+), 2378 deletions(-) delete mode 100644 OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 0d19589..1353518 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -747,7 +747,16 @@ namespace OpenSim.Region.Framework.Scenes /// public Vector3 Acceleration { - get { return m_acceleration; } + get + { + PhysicsActor actor = PhysActor; + if (actor != null) + { + m_acceleration = actor.Acceleration; + } + return m_acceleration; + } + set { m_acceleration = value; } } diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs deleted file mode 100644 index b3b09e6..0000000 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEDynamics.cs +++ /dev/null @@ -1,817 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. - * - */ - -/* Revised Aug, Sept 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Runtime.InteropServices; -using log4net; -using OpenMetaverse; -using Ode.NET; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.OdePlugin -{ - public class ODEDynamics - { - public Vehicle Type - { - get { return m_type; } - } - - public IntPtr Body - { - get { return m_body; } - } - - private int frcount = 0; // Used to limit dynamics debug output to - // every 100th frame - - // private OdeScene m_parentScene = null; - private IntPtr m_body = IntPtr.Zero; -// private IntPtr m_jointGroup = IntPtr.Zero; -// private IntPtr m_aMotor = IntPtr.Zero; - - // Vehicle properties - private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind - // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier - private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: - // HOVER_TERRAIN_ONLY - // HOVER_GLOBAL_HEIGHT - // NO_DEFLECTION_UP - // HOVER_WATER_ONLY - // HOVER_UP_ONLY - // LIMIT_MOTOR_UP - // LIMIT_ROLL_ONLY - - // Linear properties - private Vector3 m_linearMotorDirection = Vector3.Zero; // (was m_linearMotorDirectionLASTSET) the (local) Velocity - //requested by LSL - private float m_linearMotorTimescale = 0; // Motor Attack rate set by LSL - private float m_linearMotorDecayTimescale = 0; // Motor Decay rate set by LSL - private Vector3 m_linearFrictionTimescale = Vector3.Zero; // General Friction set by LSL - - private Vector3 m_lLinMotorDVel = Vector3.Zero; // decayed motor - private Vector3 m_lLinObjectVel = Vector3.Zero; // local frame object velocity - private Vector3 m_wLinObjectVel = Vector3.Zero; // world frame object velocity - - //Angular properties - private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - - private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL - private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL - private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL - - private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor -// private Vector3 m_angObjectVel = Vector3.Zero; // current body angular velocity - private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body - - private Vector3 m_angularLock = Vector3.One; - - //Deflection properties - // private float m_angularDeflectionEfficiency = 0; - // private float m_angularDeflectionTimescale = 0; - // private float m_linearDeflectionEfficiency = 0; - // private float m_linearDeflectionTimescale = 0; - - //Banking properties - // private float m_bankingEfficiency = 0; - // private float m_bankingMix = 0; - // private float m_bankingTimescale = 0; - - //Hover and Buoyancy properties - private float m_VhoverHeight = 0f; -// private float m_VhoverEfficiency = 0f; - private float m_VhoverTimescale = 0f; - private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height - private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle. - // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) - // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. - // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. - - //Attractor properties - private float m_verticalAttractionEfficiency = 1.0f; // damped - private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. - - - - - - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) - { - switch (pParam) - { - case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionEfficiency = pValue; - break; - case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_angularDeflectionTimescale = pValue; - break; - case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorDecayTimescale = pValue; - break; - case Vehicle.ANGULAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_angularMotorTimescale = pValue; - break; - case Vehicle.BANKING_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingEfficiency = pValue; - break; - case Vehicle.BANKING_MIX: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingMix = pValue; - break; - case Vehicle.BANKING_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_bankingTimescale = pValue; - break; - case Vehicle.BUOYANCY: - if (pValue < -1f) pValue = -1f; - if (pValue > 1f) pValue = 1f; - m_VehicleBuoyancy = pValue; - break; -// case Vehicle.HOVER_EFFICIENCY: -// if (pValue < 0f) pValue = 0f; -// if (pValue > 1f) pValue = 1f; -// m_VhoverEfficiency = pValue; -// break; - case Vehicle.HOVER_HEIGHT: - m_VhoverHeight = pValue; - break; - case Vehicle.HOVER_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_VhoverTimescale = pValue; - break; - case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionEfficiency = pValue; - break; - case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - // m_linearDeflectionTimescale = pValue; - break; - case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorDecayTimescale = pValue; - break; - case Vehicle.LINEAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_linearMotorTimescale = pValue; - break; - case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: - if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable - if (pValue > 1.0f) pValue = 1.0f; - m_verticalAttractionEfficiency = pValue; - break; - case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; - m_verticalAttractionTimescale = pValue; - break; - - // These are vector properties but the engine lets you use a single float value to - // set all of the components to the same value - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - if (pValue > 30f) pValue = 30f; - if (pValue < 0.1f) pValue = 0.1f; - m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - UpdateAngDecay(); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue, pValue, pValue); - UpdateLinDecay(); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); - break; - - } - - }//end ProcessFloatVehicleParam - - internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) - { - switch (pParam) - { - case Vehicle.ANGULAR_FRICTION_TIMESCALE: - if (pValue.X > 30f) pValue.X = 30f; - if (pValue.X < 0.1f) pValue.X = 0.1f; - if (pValue.Y > 30f) pValue.Y = 30f; - if (pValue.Y < 0.1f) pValue.Y = 0.1f; - if (pValue.Z > 30f) pValue.Z = 30f; - if (pValue.Z < 0.1f) pValue.Z = 0.1f; - m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.ANGULAR_MOTOR_DIRECTION: - m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - // Limit requested angular speed to 2 rps= 4 pi rads/sec - if(m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; - if(m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; - if(m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; - if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; - if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; - if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; - UpdateAngDecay(); - break; - case Vehicle.LINEAR_FRICTION_TIMESCALE: - m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - case Vehicle.LINEAR_MOTOR_DIRECTION: - m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, for max limiting - UpdateLinDecay(); - break; - case Vehicle.LINEAR_MOTOR_OFFSET: - // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); - break; - } - - }//end ProcessVectorVehicleParam - - internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) - { - switch (pParam) - { - case Vehicle.REFERENCE_FRAME: - // m_referenceFrame = pValue; - break; - } - - }//end ProcessRotationVehicleParam - - internal void SetAngularLock(Vector3 pValue) - { - m_angularLock = pValue; - } - - internal void ProcessFlagsVehicleSet(int flags) - { - m_flags |= (VehicleFlag)flags; - } - - internal void ProcessFlagsVehicleRemove(int flags) - { - m_flags &= ~((VehicleFlag)flags); - } - - internal void ProcessTypeChange(Vehicle pType) - { - // Set Defaults For Type - m_type = pType; - switch (pType) - { - case Vehicle.TYPE_SLED: - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - m_angularFrictionTimescale = new Vector3(30, 30, 30); -// m_lLinMotorVel = Vector3.Zero; - m_linearMotorTimescale = 1000; - m_linearMotorDecayTimescale = 120; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorDVel = Vector3.Zero; - m_angularMotorTimescale = 1000; - m_angularMotorDecayTimescale = 120; - m_VhoverHeight = 0; -// m_VhoverEfficiency = 1; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 1; - // m_linearDeflectionTimescale = 1; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 1000; - // m_bankingEfficiency = 0; - // m_bankingMix = 1; - // m_bankingTimescale = 10; - // m_referenceFrame = Quaternion.Identity; - m_flags &= - ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_CAR: - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - m_angularFrictionTimescale = new Vector3(30, 30, 30); // was 1000, but sl max frict time is 30. -// m_lLinMotorVel = Vector3.Zero; - m_linearMotorTimescale = 1; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorDVel = Vector3.Zero; - m_angularMotorTimescale = 1; - m_angularMotorDecayTimescale = 0.8f; - m_VhoverHeight = 0; -// m_VhoverEfficiency = 0; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - // // m_linearDeflectionEfficiency = 1; - // // m_linearDeflectionTimescale = 2; - // // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 10; - m_verticalAttractionEfficiency = 1f; - m_verticalAttractionTimescale = 10f; - // m_bankingEfficiency = -0.2f; - // m_bankingMix = 1; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY | - VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_BOAT: - m_linearFrictionTimescale = new Vector3(10, 3, 2); - m_angularFrictionTimescale = new Vector3(10,10,10); -// m_lLinMotorVel = Vector3.Zero; - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorDVel = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_VhoverHeight = 0; -// m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 2; - m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 0.5f; - // m_angularDeflectionTimescale = 5; - m_verticalAttractionEfficiency = 0.5f; - m_verticalAttractionTimescale = 5f; - // m_bankingEfficiency = -0.3f; - // m_bankingMix = 0.8f; - // m_bankingTimescale = 1; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | - VehicleFlag.LIMIT_MOTOR_UP); - break; - case Vehicle.TYPE_AIRPLANE: - m_linearFrictionTimescale = new Vector3(200, 10, 5); - m_angularFrictionTimescale = new Vector3(20, 20, 20); -// m_lLinMotorVel = Vector3.Zero; - m_linearMotorTimescale = 2; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorDVel = Vector3.Zero; - m_angularMotorTimescale = 4; - m_angularMotorDecayTimescale = 4; - m_VhoverHeight = 0; -// m_VhoverEfficiency = 0.5f; - m_VhoverTimescale = 1000; - m_VehicleBuoyancy = 0; - // m_linearDeflectionEfficiency = 0.5f; - // m_linearDeflectionTimescale = 3; - // m_angularDeflectionEfficiency = 1; - // m_angularDeflectionTimescale = 2; - m_verticalAttractionEfficiency = 0.9f; - m_verticalAttractionTimescale = 2f; - // m_bankingEfficiency = 1; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 2; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - break; - case Vehicle.TYPE_BALLOON: - m_linearFrictionTimescale = new Vector3(5, 5, 5); - m_angularFrictionTimescale = new Vector3(10, 10, 10); - m_linearMotorTimescale = 5; - m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; - m_angularMotorDVel = Vector3.Zero; - m_angularMotorTimescale = 6; - m_angularMotorDecayTimescale = 10; - m_VhoverHeight = 5; -// m_VhoverEfficiency = 0.8f; - m_VhoverTimescale = 10; - m_VehicleBuoyancy = 1; - // m_linearDeflectionEfficiency = 0; - // m_linearDeflectionTimescale = 5; - // m_angularDeflectionEfficiency = 0; - // m_angularDeflectionTimescale = 5; - m_verticalAttractionEfficiency = 1f; - m_verticalAttractionTimescale = 100f; - // m_bankingEfficiency = 0; - // m_bankingMix = 0.7f; - // m_bankingTimescale = 5; - // m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | - VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); - break; - - } - }//end SetDefaultsForType - - internal void Enable(IntPtr pBody, OdeScene pParentScene) - { - if (m_type == Vehicle.TYPE_NONE) - return; - - m_body = pBody; - } - - internal void Step(float pTimestep, OdeScene pParentScene) - { - if (m_body == IntPtr.Zero || m_type == Vehicle.TYPE_NONE) - return; - frcount++; // used to limit debug comment output - if (frcount > 24) - frcount = 0; - - MoveLinear(pTimestep, pParentScene); - MoveAngular(pTimestep); - }// end Step - - internal void Halt() - { // Kill all motions, when non-physical - m_linearMotorDirection = Vector3.Zero; - m_lLinMotorDVel = Vector3.Zero; - m_lLinObjectVel = Vector3.Zero; - m_wLinObjectVel = Vector3.Zero; - m_angularMotorDirection = Vector3.Zero; - m_lastAngularVelocity = Vector3.Zero; - m_angularMotorDVel = Vector3.Zero; - } - - private void UpdateLinDecay() - { - if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X; - if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y; - if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z; - } // else let the motor decay on its own - - private void MoveLinear(float pTimestep, OdeScene _pParentScene) - { - Vector3 acceleration = new Vector3(0f, 0f, 0f); - - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object - Quaternion irotq = Quaternion.Inverse(rotq); - d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame - Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z); - acceleration = vel_now - m_wLinObjectVel; - m_lLinObjectVel = vel_now * irotq; - - if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate - { - if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f) - { - float decayfactor = m_linearMotorDecayTimescale/pTimestep; - Vector3 decayAmount = (m_lLinMotorDVel/decayfactor); - m_lLinMotorDVel -= decayAmount; - } - else - { - float decayfactor = 3.0f - (0.57f * (float)Math.Log((double)(m_linearMotorDecayTimescale))); - Vector3 decel = Vector3.Normalize(m_lLinMotorDVel) * decayfactor * pTimestep; - m_lLinMotorDVel -= decel; - } - if (m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) - { - m_lLinMotorDVel = Vector3.Zero; - } - else - { - if (Math.Abs(m_lLinMotorDVel.X) < Math.Abs(m_lLinObjectVel.X)) m_lLinObjectVel.X = m_lLinMotorDVel.X; - if (Math.Abs(m_lLinMotorDVel.Y) < Math.Abs(m_lLinObjectVel.Y)) m_lLinObjectVel.Y = m_lLinMotorDVel.Y; - if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z; - } - } - - if ( (! m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! m_lLinObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) - { - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); - if (m_linearMotorTimescale < 300.0f) - { - Vector3 attack_error = m_lLinMotorDVel - m_lLinObjectVel; - float linfactor = m_linearMotorTimescale/pTimestep; - Vector3 attackAmount = (attack_error/linfactor) * 1.3f; - m_lLinObjectVel += attackAmount; - } - if (m_linearFrictionTimescale.X < 300.0f) - { - float fricfactor = m_linearFrictionTimescale.X / pTimestep; - float fricX = m_lLinObjectVel.X / fricfactor; - m_lLinObjectVel.X -= fricX; - } - if (m_linearFrictionTimescale.Y < 300.0f) - { - float fricfactor = m_linearFrictionTimescale.Y / pTimestep; - float fricY = m_lLinObjectVel.Y / fricfactor; - m_lLinObjectVel.Y -= fricY; - } - if (m_linearFrictionTimescale.Z < 300.0f) - { - float fricfactor = m_linearFrictionTimescale.Z / pTimestep; -//if(frcount == 0) Console.WriteLine("Zfric={0}", fricfactor); - float fricZ = m_lLinObjectVel.Z / fricfactor; - m_lLinObjectVel.Z -= fricZ; - } - } - m_wLinObjectVel = m_lLinObjectVel * rotq; - // Add Gravity and Buoyancy - Vector3 grav = Vector3.Zero; - if(m_VehicleBuoyancy < 1.0f) - { - // There is some gravity, make a gravity force vector - // that is applied after object velocity. - d.Mass objMass; - d.BodyGetMass(Body, out objMass); - // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - grav.Z = _pParentScene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); // Applied later as a force - } // else its 1.0, no gravity. - - // Check if hovering - if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) - { - // We should hover, get the target height - d.Vector3 pos = d.BodyGetPosition(Body); - if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY) - { - m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; - } - else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY) - { - m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; - } - else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT) - { - m_VhoverTargetHeight = m_VhoverHeight; - } - - if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY) - { - // If body is aready heigher, use its height as target height - if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; - } - -// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped -// m_VhoverTimescale = 0f; // time to acheive height -// pTimestep is time since last frame,in secs - float herr0 = pos.Z - m_VhoverTargetHeight; - // Replace Vertical speed with correction figure if significant - if(Math.Abs(herr0) > 0.01f ) - { - d.Mass objMass; - d.BodyGetMass(Body, out objMass); - m_wLinObjectVel.Z = - ( (herr0 * pTimestep * 50.0f) / m_VhoverTimescale); - //KF: m_VhoverEfficiency is not yet implemented - } - else - { - m_wLinObjectVel.Z = 0f; - } - } - else - { // not hovering, Gravity rules - m_wLinObjectVel.Z = vel_now.Z; -//if(frcount == 0) Console.WriteLine(" Z {0} a.Z {1}", m_wLinObjectVel.Z, acceleration.Z); - } - // Apply velocity - d.BodySetLinearVel(Body, m_wLinObjectVel.X, m_wLinObjectVel.Y, m_wLinObjectVel.Z); - // apply gravity force - d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); -//if(frcount == 0) Console.WriteLine("Grav {0}", grav); - } // end MoveLinear() - - private void UpdateAngDecay() - { - if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X; - if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y; - if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z; - } // else let the motor decay on its own - - private void MoveAngular(float pTimestep) - { - /* - private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - - private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL - private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL - private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL - - private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor - private Vector3 m_angObjectVel = Vector3.Zero; // what was last applied to body - */ -//if(frcount == 0) Console.WriteLine("MoveAngular "); - - // Get what the body is doing, this includes 'external' influences - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object - Quaternion irotq = Quaternion.Inverse(rotq); - d.Vector3 angularObjectVel = d.BodyGetAngularVel(Body); - Vector3 angObjectVel = new Vector3(angularObjectVel.X, angularObjectVel.Y, angularObjectVel.Z); - angObjectVel = angObjectVel * irotq; // ============ Converts to LOCAL rotation - -//if(frcount == 0) Console.WriteLine("V0 = {0}", angObjectVel); -// Vector3 FrAaccel = m_lastAngularVelocity - angObjectVel; -// Vector3 initavel = angObjectVel; - // Decay Angular Motor 1. In SL this also depends on attack rate! decay ~= 23/Attack. - float atk_decayfactor = 23.0f / (m_angularMotorTimescale * pTimestep); - m_angularMotorDVel -= m_angularMotorDVel / atk_decayfactor; - // Decay Angular Motor 2. - if (m_angularMotorDecayTimescale < 300.0f) - { -//#### - if ( Vector3.Mag(m_angularMotorDVel) < 1.0f) - { - float decayfactor = (m_angularMotorDecayTimescale)/pTimestep; - Vector3 decayAmount = (m_angularMotorDVel/decayfactor); - m_angularMotorDVel -= decayAmount; - } - else - { - Vector3 decel = Vector3.Normalize(m_angularMotorDVel) * pTimestep / m_angularMotorDecayTimescale; - m_angularMotorDVel -= decel; - } - - if (m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) - { - m_angularMotorDVel = Vector3.Zero; - } - else - { - if (Math.Abs(m_angularMotorDVel.X) < Math.Abs(angObjectVel.X)) angObjectVel.X = m_angularMotorDVel.X; - if (Math.Abs(m_angularMotorDVel.Y) < Math.Abs(angObjectVel.Y)) angObjectVel.Y = m_angularMotorDVel.Y; - if (Math.Abs(m_angularMotorDVel.Z) < Math.Abs(angObjectVel.Z)) angObjectVel.Z = m_angularMotorDVel.Z; - } - } // end decay angular motor -//if(frcount == 0) Console.WriteLine("MotorDvel {0} Obj {1}", m_angularMotorDVel, angObjectVel); - -//if(frcount == 0) Console.WriteLine("VA = {0}", angObjectVel); - // Vertical attractor section - Vector3 vertattr = Vector3.Zero; - - if(m_verticalAttractionTimescale < 300) - { - float VAservo = 1.0f / (m_verticalAttractionTimescale * pTimestep); - // get present body rotation -// d.Quaternion rot = d.BodyGetQuaternion(Body); -// Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); - // make a vector pointing up - Vector3 verterr = Vector3.Zero; - verterr.Z = 1.0f; - // rotate it to Body Angle - verterr = verterr * rotq; - // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. - // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go - // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. - - if (verterr.Z < 0.0f) - { // Deflection from vertical exceeds 90-degrees. This method will ensure stable return to - // vertical, BUT for some reason a z-rotation is imparted to the object. TBI. -//Console.WriteLine("InvertFlip"); - verterr.X = 2.0f - verterr.X; - verterr.Y = 2.0f - verterr.Y; - } - verterr *= 0.5f; - // verterror is 0 (no error) to +/- 1 (max error at 180-deg tilt) - - if ((!angObjectVel.ApproxEquals(Vector3.Zero, 0.001f)) || (verterr.Z < 0.49f)) - { -//if(frcount == 0) - // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so - // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. - vertattr.X = verterr.Y; - vertattr.Y = - verterr.X; - vertattr.Z = 0f; -//if(frcount == 0) Console.WriteLine("VAerr=" + verterr); - - // scaling appears better usingsquare-law - float damped = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency; - float bounce = 1.0f - damped; - // 0 = crit damp, 1 = bouncy - float oavz = angObjectVel.Z; // retain z velocity - angObjectVel = (angObjectVel + (vertattr * VAservo * 0.0333f)) * bounce; // The time-scaled correction, which sums, therefore is bouncy - angObjectVel = angObjectVel + (vertattr * VAservo * 0.0667f * damped); // damped, good @ < 90. - angObjectVel.Z = oavz; -//if(frcount == 0) Console.WriteLine("VA+"); -//Console.WriteLine("VAttr {0} OAvel {1}", vertattr, angObjectVel); - } - else - { - // else error is very small - angObjectVel.X = 0f; - angObjectVel.Y = 0f; -//if(frcount == 0) Console.WriteLine("VA0"); - } - } // else vertical attractor is off -//if(frcount == 0) Console.WriteLine("V1 = {0}", angObjectVel); - - if ( (! m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! angObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) - { // if motor or object have motion - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); - - if (m_angularMotorTimescale < 300.0f) - { - Vector3 attack_error = m_angularMotorDVel - angObjectVel; - float angfactor = m_angularMotorTimescale/pTimestep; - Vector3 attackAmount = (attack_error/angfactor); - angObjectVel += attackAmount; -//if(frcount == 0) Console.WriteLine("Accel {0} Attk {1}",FrAaccel, attackAmount); -//if(frcount == 0) Console.WriteLine("V2+= {0}", angObjectVel); - } - - angObjectVel.X -= angObjectVel.X / (m_angularFrictionTimescale.X * 0.7f / pTimestep); - angObjectVel.Y -= angObjectVel.Y / (m_angularFrictionTimescale.Y * 0.7f / pTimestep); - angObjectVel.Z -= angObjectVel.Z / (m_angularFrictionTimescale.Z * 0.7f / pTimestep); - } // else no signif. motion - -//if(frcount == 0) Console.WriteLine("Dmotor {0} Obj {1}", m_angularMotorDVel, angObjectVel); - // Bank section tba - // Deflection section tba -//if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); - - m_lastAngularVelocity = angObjectVel; -/* - if (!m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.0001f)) - { - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); - } - else - { - m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. - } - */ -//if(frcount == 0) Console.WriteLine("angularLock {0}", m_angularLock); - - if (!m_angularLock.ApproxEquals(Vector3.One, 0.003f)) - { - if (m_angularLock.X == 0) - m_lastAngularVelocity.X = 0f; - if (m_angularLock.Y == 0) - m_lastAngularVelocity.Y = 0f; - if (m_angularLock.Z == 0) - m_lastAngularVelocity.Z = 0f; - } - // Apply to the body -// Vector3 aInc = m_lastAngularVelocity - initavel; -//if(frcount == 0) Console.WriteLine("Inc {0}", aInc); - m_lastAngularVelocity = m_lastAngularVelocity * rotq; // ================ Converts to WORLD rotation - - d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); -//if(frcount == 0) Console.WriteLine("V4 = {0}", m_lastAngularVelocity); - - } //end MoveAngular - } -} diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index fb6cb55..5d24388 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -22,32 +22,10 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. + * Revised March 5th 2010 by Kitto Flora. ODEDynamics.cs + * rolled into ODEPrim.cs */ -/* - * Revised August 26 2009 by Kitto Flora. ODEDynamics.cs replaces - * ODEVehicleSettings.cs. It and ODEPrim.cs are re-organised: - * ODEPrim.cs contains methods dealing with Prim editing, Prim - * characteristics and Kinetic motion. - * ODEDynamics.cs contains methods dealing with Prim Physical motion - * (dynamics) and the associated settings. Old Linear and angular - * motors for dynamic motion have been replace with MoveLinear() - * and MoveAngular(); 'Physical' is used only to switch ODE dynamic - * simualtion on/off; VEHICAL_TYPE_NONE/VEHICAL_TYPE_ is to - * switch between 'VEHICLE' parameter use and general dynamics - * settings use. - */ using System; using System.Collections.Generic; using System.Reflection; @@ -59,6 +37,7 @@ using Ode.NET; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; + namespace OpenSim.Region.Physics.OdePlugin { /// @@ -102,8 +81,8 @@ namespace OpenSim.Region.Physics.OdePlugin private float m_APIDDamping = 0.5f; private bool m_useAPID = false; - // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), - // and are for non-VEHICLES only. + // These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), + // do not confuse with VEHICLE HOVER private float m_PIDHoverHeight; private float m_PIDHoverTau; @@ -112,7 +91,7 @@ namespace OpenSim.Region.Physics.OdePlugin private float m_targetHoverHeight; private float m_groundHeight; private float m_waterHeight; - private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. + private float m_buoyancy; //m_buoyancy set by llSetBuoyancy() // private float m_tensor = 5f; private int body_autodisable_frames = 20; @@ -183,7 +162,7 @@ namespace OpenSim.Region.Physics.OdePlugin public bool outofBounds; private float m_density = 10.000006836f; // Aluminum g/cm3; - public bool _zeroFlag; + public bool _zeroFlag; // if body has been stopped private bool m_lastUpdateSent; public IntPtr Body = IntPtr.Zero; @@ -198,18 +177,81 @@ namespace OpenSim.Region.Physics.OdePlugin public volatile bool childPrim; - private ODEDynamics m_vehicle; - internal int m_material = (int)Material.Wood; private int frcount = 0; // Used to limit dynamics debug output to + private IntPtr m_body = IntPtr.Zero; + + // Vehicle properties ============================================================================================ + private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind + // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier + private VehicleFlag m_flags = (VehicleFlag) 0; // Bit settings: + // HOVER_TERRAIN_ONLY + // HOVER_GLOBAL_HEIGHT + // NO_DEFLECTION_UP + // HOVER_WATER_ONLY + // HOVER_UP_ONLY + // LIMIT_MOTOR_UP + // LIMIT_ROLL_ONLY + + // Linear properties + private Vector3 m_linearMotorDirection = Vector3.Zero; // (was m_linearMotorDirectionLASTSET) the (local) Velocity + //requested by LSL + private float m_linearMotorTimescale = 0; // Motor Attack rate set by LSL + private float m_linearMotorDecayTimescale = 0; // Motor Decay rate set by LSL + private Vector3 m_linearFrictionTimescale = Vector3.Zero; // General Friction set by LSL + + private Vector3 m_lLinMotorDVel = Vector3.Zero; // decayed motor + private Vector3 m_lLinObjectVel = Vector3.Zero; // local frame object velocity + private Vector3 m_wLinObjectVel = Vector3.Zero; // world frame object velocity + + //Angular properties + private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor + + private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL + private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL + private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL + + private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor +// private Vector3 m_angObjectVel = Vector3.Zero; // current body angular velocity + private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body + + private Vector3 m_angularLock = Vector3.One; + + //Deflection properties + // private float m_angularDeflectionEfficiency = 0; + // private float m_angularDeflectionTimescale = 0; + // private float m_linearDeflectionEfficiency = 0; + // private float m_linearDeflectionTimescale = 0; + + //Banking properties + // private float m_bankingEfficiency = 0; + // private float m_bankingMix = 0; + // private float m_bankingTimescale = 0; + + //Hover and Buoyancy properties + private float m_VhoverHeight = 0f; +// private float m_VhoverEfficiency = 0f; + private float m_VhoverTimescale = 0f; + private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height + private float m_VehicleBuoyancy = 0f; // Set by VEHICLE_BUOYANCY, for a vehicle. + // Modifies gravity. Slider between -1 (double-gravity) and 1 (full anti-gravity) + // KF: So far I have found no good method to combine a script-requested .Z velocity and gravity. + // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. + + //Attractor properties + private float m_verticalAttractionEfficiency = 1.0f; // damped + private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. + + + + + public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) { - m_vehicle = new ODEDynamics(); - //gc = GCHandle.Alloc(prim_geom, GCHandleType.Pinned); ode = dode; if (!pos.IsFinite()) { @@ -302,7 +344,7 @@ namespace OpenSim.Region.Physics.OdePlugin { set { - +Console.WriteLine("Sel {0} {1} {2}", m_primName, value, m_isphysical); // This only makes the object not collidable if the object // is physical or the object is modified somehow *IN THE FUTURE* // without this, if an avatar selects prim, they can walk right @@ -322,326 +364,563 @@ namespace OpenSim.Region.Physics.OdePlugin } } - public void SetGeom(IntPtr geom) + public override bool IsPhysical { - prev_geom = prim_geom; - prim_geom = geom; -//Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName); - if (prim_geom != IntPtr.Zero) - { - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + get { return m_isphysical; } + set + { + m_isphysical = value; + if (!m_isphysical) + { // Zero the remembered last velocity + m_lastVelocity = Vector3.Zero; + if (m_type != Vehicle.TYPE_NONE) Halt(); + } } + } - if (childPrim) + public void setPrimForRemoval() + { + m_taintremove = true; + } + + public override bool Flying + { + // no flying prims for you + get { return false; } + set { } + } + + public override bool IsColliding + { + get { return iscolliding; } + set { iscolliding = value; } + } + + public override bool CollidingGround + { + get { return false; } + set { return; } + } + + public override bool CollidingObj + { + get { return false; } + set { return; } + } + + public override bool ThrottleUpdates + { + get { return m_throttleUpdates; } + set { m_throttleUpdates = value; } + } + + public override bool Stopped + { + get { return _zeroFlag; } + } + + public override Vector3 Position + { + get { return _position; } + + set { _position = value; + //m_log.Info("[PHYSICS]: " + _position.ToString()); + } + } + + public override Vector3 Size + { + get { return _size; } + set { - if (_parent != null && _parent is OdePrim) + if (value.IsFinite()) { - OdePrim parent = (OdePrim)_parent; -//Console.WriteLine("SetGeom calls ChildSetGeom"); - parent.ChildSetGeom(this); + _size = value; + } + else + { + m_log.Warn("[PHYSICS]: Got NaN Size on object"); } } - //m_log.Warn("Setting Geom to: " + prim_geom); } - + public override float Mass + { + get { return CalculateMass(); } + } - public void enableBodySoft() + public override Vector3 Force { - if (!childPrim) + //get { return Vector3.Zero; } + get { return m_force; } + set { - if (m_isphysical && Body != IntPtr.Zero) + if (value.IsFinite()) { - d.BodyEnable(Body); - if (m_vehicle.Type != Vehicle.TYPE_NONE) - m_vehicle.Enable(Body, _parent_scene); + m_force = value; + } + else + { + m_log.Warn("[PHYSICS]: NaN in Force Applied to an Object"); } - - m_disabled = false; } } - public void disableBodySoft() + public override int VehicleType { - m_disabled = true; + get { return (int)m_type; } + set { ProcessTypeChange((Vehicle)value); } + } - if (m_isphysical && Body != IntPtr.Zero) - { - d.BodyDisable(Body); - } + public override void VehicleFloatParam(int param, float value) + { + ProcessFloatVehicleParam((Vehicle) param, value); } - public void enableBody() + public override void VehicleVectorParam(int param, Vector3 value) { - // Don't enable this body if we're a child prim - // this should be taken care of in the parent function not here - if (!childPrim) + ProcessVectorVehicleParam((Vehicle) param, value); + } + + public override void VehicleRotationParam(int param, Quaternion rotation) + { + ProcessRotationVehicleParam((Vehicle) param, rotation); + } + + public override void VehicleFlagsSet(int flags) + { + ProcessFlagsVehicleSet(flags); + } + + public override void VehicleFlagsRemove(int flags) + { + ProcessFlagsVehicleRemove(flags); + } + + public override void SetVolumeDetect(int param) + { + lock (_parent_scene.OdeLock) { - // Sets the geom to a body - Body = d.BodyCreate(_parent_scene.world); + m_isVolumeDetect = (param!=0); + } + } - setMass(); - d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.X = _orientation.X; - myrot.Y = _orientation.Y; - myrot.Z = _orientation.Z; - myrot.W = _orientation.W; - d.BodySetQuaternion(Body, ref myrot); - d.GeomSetBody(prim_geom, Body); - m_collisionCategories |= CollisionCategories.Body; - m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + public override Vector3 CenterOfMass + { + get { return Vector3.Zero; } + } - d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + public override Vector3 GeometricCenter + { + get { return Vector3.Zero; } + } - d.BodySetAutoDisableFlag(Body, true); - d.BodySetAutoDisableSteps(Body, body_autodisable_frames); - - // disconnect from world gravity so we can apply buoyancy - d.BodySetGravityMode (Body, false); + public override PrimitiveBaseShape Shape + { + set + { + _pbs = value; + m_taintshape = true; + } + } - m_interpenetrationcount = 0; - m_collisionscore = 0; - m_disabled = false; + public override Vector3 Velocity + { + get + { + // Averate previous velocity with the new one so + // client object interpolation works a 'little' better + if (_zeroFlag) + return Vector3.Zero; - // The body doesn't already have a finite rotation mode set here - /* ### if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0.0f)) && _parent == null) + Vector3 returnVelocity = Vector3.Zero; + returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2; + returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2; + returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2; + return returnVelocity; + } + set + { + if (value.IsFinite()) { - createAMotor(m_angularlock); - } */ - if (m_vehicle.Type != Vehicle.TYPE_NONE) + _velocity = value; + + m_taintVelocity = value; + _parent_scene.AddPhysicsActorTaint(this); + } + else { - m_vehicle.Enable(Body, _parent_scene); + m_log.Warn("[PHYSICS]: Got NaN Velocity in Object"); } - _parent_scene.addActivePrim(this); } } - #region Mass Calculation - - private float CalculateMass() + public override Vector3 Torque { - float volume = 0; - - // No material is passed to the physics engines yet.. soo.. - // we're using the m_density constant in the class definition + get + { + if (!m_isphysical || Body == IntPtr.Zero) + return Vector3.Zero; - float returnMass = 0; + return _torque; + } - switch (_pbs.ProfileShape) + set { - case ProfileShape.Square: - // Profile Volume - - volume = _size.X*_size.Y*_size.Z; + if (value.IsFinite()) + { + m_taintTorque = value; + _parent_scene.AddPhysicsActorTaint(this); + } + else + { + m_log.Warn("[PHYSICS]: Got NaN Torque in Object"); + } + } + } - // If the user has 'hollowed out' - // ProfileHollow is one of those 0 to 50000 values :P - // we like percentages better.. so turning into a percentage + public override float CollisionScore + { + get { return m_collisionscore; } + set { m_collisionscore = value; } + } - if (((float) _pbs.ProfileHollow/50000f) > 0.0) - { - float hollowAmount = (float) _pbs.ProfileHollow/50000f; + public override bool Kinematic + { + get { return false; } + set { } + } - // calculate the hollow volume by it's shape compared to the prim shape - float hollowVolume = 0; - switch (_pbs.HollowShape) - { - case HollowShape.Square: - case HollowShape.Same: - // Cube Hollow volume calculation - float hollowsizex = _size.X*hollowAmount; - float hollowsizey = _size.Y*hollowAmount; - float hollowsizez = _size.Z*hollowAmount; - hollowVolume = hollowsizex*hollowsizey*hollowsizez; - break; + public override Quaternion Orientation + { + get { return _orientation; } + set + { + if (QuaternionIsFinite(value)) + { + _orientation = value; + } + else + m_log.Warn("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object"); - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - float hRadius = _size.X/2; - float hLength = _size.Z; + } + } + + + public override bool FloatOnWater + { + set { + m_taintCollidesWater = value; + _parent_scene.AddPhysicsActorTaint(this); + } + } - // pi * r2 * h - hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); - break; + public override void SetMomentum(Vector3 momentum) + { + } - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + public override Vector3 PIDTarget + { + set + { + if (value.IsFinite()) + { + m_PIDTarget = value; + } + else + m_log.Warn("[PHYSICS]: Got NaN PIDTarget from Scene on Object"); + } + } + public override bool PIDActive { set { m_usePID = value; } } + public override float PIDTau { set { m_PIDTau = value; } } + + // For RotLookAt + public override Quaternion APIDTarget { set { m_APIDTarget = value; } } + public override bool APIDActive { set { m_useAPID = value; } } + public override float APIDStrength { set { m_APIDStrength = value; } } + public override float APIDDamping { set { m_APIDDamping = value; } } - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); - break; + public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } + public override bool PIDHoverActive { set { m_useHoverPID = value; } } + public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } + public override float PIDHoverTau { set { m_PIDHoverTau = value; } } - default: - hollowVolume = 0; - break; - } - volume = volume - hollowVolume; - } + internal static bool QuaternionIsFinite(Quaternion q) + { + if (Single.IsNaN(q.X) || Single.IsInfinity(q.X)) + return false; + if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y)) + return false; + if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z)) + return false; + if (Single.IsNaN(q.W) || Single.IsInfinity(q.W)) + return false; + return true; + } - break; - case ProfileShape.Circle: - if (_pbs.PathCurve == (byte)Extrusion.Straight) - { - // Cylinder - float volume1 = (float)(Math.PI * Math.Pow(_size.X/2, 2) * _size.Z); - float volume2 = (float)(Math.PI * Math.Pow(_size.Y/2, 2) * _size.Z); + public override Vector3 Acceleration + { + get { return _acceleration; } + } - // Approximating the cylinder's irregularity. - if (volume1 > volume2) - { - volume = (float)volume1 - (volume1 - volume2); - } - else if (volume2 > volume1) - { - volume = (float)volume2 - (volume2 - volume1); - } - else - { - // Regular cylinder - volume = volume1; - } - } - else - { - // We don't know what the shape is yet, so use default - volume = _size.X * _size.Y * _size.Z; - } - // If the user has 'hollowed out' - // ProfileHollow is one of those 0 to 50000 values :P - // we like percentages better.. so turning into a percentage - if (((float)_pbs.ProfileHollow / 50000f) > 0.0) - { - float hollowAmount = (float)_pbs.ProfileHollow / 50000f; + public void SetAcceleration(Vector3 accel) // No one calls this, and it would not do anything. + { + _acceleration = accel; + } - // calculate the hollow volume by it's shape compared to the prim shape - float hollowVolume = 0; - switch (_pbs.HollowShape) - { - case HollowShape.Same: - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - float hRadius = _size.X / 2; - float hLength = _size.Z; + public override void AddForce(Vector3 force, bool pushforce) + { + if (force.IsFinite()) + { + lock (m_forcelist) + m_forcelist.Add(force); - // pi * r2 * h - hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount); - break; + m_taintforce = true; + } + else + { + m_log.Warn("[PHYSICS]: Got Invalid linear force vector from Scene in Object"); + } + //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString()); + } - case HollowShape.Square: - // Cube Hollow volume calculation - float hollowsizex = _size.X * hollowAmount; - float hollowsizey = _size.Y * hollowAmount; - float hollowsizez = _size.Z * hollowAmount; - hollowVolume = hollowsizex * hollowsizey * hollowsizez; - break; + public override void AddAngularForce(Vector3 force, bool pushforce) + { + if (force.IsFinite()) + { + m_angularforcelist.Add(force); + m_taintaddangularforce = true; + } + else + { + m_log.Warn("[PHYSICS]: Got Invalid Angular force vector from Scene in Object"); + } + } - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + public override Vector3 RotationalVelocity + { + get + { +/* Vector3 pv = Vector3.Zero; + if (_zeroFlag) + return pv; + m_lastUpdateSent = false; - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); - break; + if (m_rotationalVelocity.ApproxEquals(pv, 0.2f)) + return pv; +*/ + return m_rotationalVelocity; + } + set + { + if (value.IsFinite()) + { + m_rotationalVelocity = value; + } + else + { + m_log.Warn("[PHYSICS]: Got NaN RotationalVelocity in Object"); + } + } + } - default: - hollowVolume = 0; - break; - } - volume = volume - hollowVolume; - } - break; + public override void CrossingFailure() + { + m_crossingfailures++; + if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds) + { + base.RaiseOutOfBounds(_position); + return; + } + else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds) + { + m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName); + } + } - case ProfileShape.HalfCircle: - if (_pbs.PathCurve == (byte)Extrusion.Curve1) - { - if (_size.X == _size.Y && _size.Y == _size.Z) - { - // regular sphere - // v = 4/3 * pi * r^3 - float sradius3 = (float)Math.Pow((_size.X / 2), 3); - volume = (float)((4f / 3f) * Math.PI * sradius3); - } - else - { - // we treat this as a box currently - volume = _size.X * _size.Y * _size.Z; - } - } - else - { - // We don't know what the shape is yet, so use default - volume = _size.X * _size.Y * _size.Z; - } - break; + public override float Buoyancy + { + get { return m_buoyancy; } + set { m_buoyancy = value; } + } - case ProfileShape.EquilateralTriangle: - /* - v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h + public override void link(PhysicsActor obj) + { + m_taintparent = obj; + } - // seed mesh - Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); - Vertex PM = new Vertex(+0.5f, 0f, 0.0f); - Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); - */ - float xA = -0.25f * _size.X; - float yA = -0.45f * _size.Y; + public override void delink() + { + m_taintparent = null; + } - float xB = 0.5f * _size.X; - float yB = 0; + public override void LockAngularMotion(Vector3 axis) + { + // reverse the zero/non zero values for ODE. + if (axis.IsFinite()) + { + axis.X = (axis.X > 0) ? 1f : 0f; + axis.Y = (axis.Y > 0) ? 1f : 0f; + axis.Z = (axis.Z > 0) ? 1f : 0f; + m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); + m_taintAngularLock = axis; + } + else + { + m_log.Warn("[PHYSICS]: Got NaN locking axis from Scene on Object"); + } + } - float xC = -0.25f * _size.X; - float yC = 0.45f * _size.Y; - volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z); + public void SetGeom(IntPtr geom) + { + prev_geom = prim_geom; + prim_geom = geom; +//Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName); + if (prim_geom != IntPtr.Zero) + { + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + + if (childPrim) + { + if (_parent != null && _parent is OdePrim) + { + OdePrim parent = (OdePrim)_parent; +//Console.WriteLine("SetGeom calls ChildSetGeom"); + parent.ChildSetGeom(this); + } + } + //m_log.Warn("Setting Geom to: " + prim_geom); + } + + public void enableBodySoft() + { + if (!childPrim) + { + if (m_isphysical && Body != IntPtr.Zero) + { + d.BodyEnable(Body); + if (m_type != Vehicle.TYPE_NONE) + Enable(Body, _parent_scene); + } + + m_disabled = false; + } + } + + public void disableBodySoft() + { + m_disabled = true; + + if (m_isphysical && Body != IntPtr.Zero) + { + d.BodyDisable(Body); + } + } + + public void enableBody() + { + // Don't enable this body if we're a child prim + // this should be taken care of in the parent function not here + if (!childPrim) + { + // Sets the geom to a body + Body = d.BodyCreate(_parent_scene.world); + + setMass(); + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.X = _orientation.X; + myrot.Y = _orientation.Y; + myrot.Z = _orientation.Z; + myrot.W = _orientation.W; + d.BodySetQuaternion(Body, ref myrot); + d.GeomSetBody(prim_geom, Body); + m_collisionCategories |= CollisionCategories.Body; + m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); + + d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + + d.BodySetAutoDisableFlag(Body, true); + d.BodySetAutoDisableSteps(Body, body_autodisable_frames); + + // disconnect from world gravity so we can apply buoyancy + d.BodySetGravityMode (Body, false); + + m_interpenetrationcount = 0; + m_collisionscore = 0; + m_disabled = false; + + if (m_type != Vehicle.TYPE_NONE) + { + Enable(Body, _parent_scene); + } + + _parent_scene.addActivePrim(this); + } + } + + #region Mass Calculation + + private float CalculateMass() + { + float volume = 0; + + // No material is passed to the physics engines yet.. soo.. + // we're using the m_density constant in the class definition + + float returnMass = 0; + + switch (_pbs.ProfileShape) + { + case ProfileShape.Square: + // Profile Volume + + volume = _size.X*_size.Y*_size.Z; // If the user has 'hollowed out' // ProfileHollow is one of those 0 to 50000 values :P // we like percentages better.. so turning into a percentage - float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f); - if (((float)fhollowFactor / 50000f) > 0.0) + + if (((float) _pbs.ProfileHollow/50000f) > 0.0) { - float hollowAmount = (float)fhollowFactor / 50000f; + float hollowAmount = (float) _pbs.ProfileHollow/50000f; // calculate the hollow volume by it's shape compared to the prim shape float hollowVolume = 0; switch (_pbs.HollowShape) { - case HollowShape.Same: - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y - - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); - break; - case HollowShape.Square: + case HollowShape.Same: // Cube Hollow volume calculation - float hollowsizex = _size.X * hollowAmount; - float hollowsizey = _size.Y * hollowAmount; - float hollowsizez = _size.Z * hollowAmount; - hollowVolume = hollowsizex * hollowsizey * hollowsizez; + float hollowsizex = _size.X*hollowAmount; + float hollowsizey = _size.Y*hollowAmount; + float hollowsizez = _size.Z*hollowAmount; + hollowVolume = hollowsizex*hollowsizey*hollowsizez; break; case HollowShape.Circle: // Hollow shape is a perfect cyllinder in respect to the cube's scale // Cyllinder hollow volume calculation - float hRadius = _size.X / 2; + float hRadius = _size.X/2; float hLength = _size.Z; // pi * r2 * h - hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength)/2) * hollowAmount); + hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); + break; + + case HollowShape.Triangle: + // Equilateral Triangular Prism volume hollow calculation + // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + + float aLength = _size.Y; + // 1/2 abh + hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); break; default: @@ -650,28 +929,194 @@ namespace OpenSim.Region.Physics.OdePlugin } volume = volume - hollowVolume; } - break; - default: - // we don't have all of the volume formulas yet so - // use the common volume formula for all - volume = _size.X*_size.Y*_size.Z; break; - } + case ProfileShape.Circle: + if (_pbs.PathCurve == (byte)Extrusion.Straight) + { + // Cylinder + float volume1 = (float)(Math.PI * Math.Pow(_size.X/2, 2) * _size.Z); + float volume2 = (float)(Math.PI * Math.Pow(_size.Y/2, 2) * _size.Z); - // Calculate Path cut effect on volume - // Not exact, in the triangle hollow example - // They should never be zero or less then zero.. - // we'll ignore it if it's less then zero + // Approximating the cylinder's irregularity. + if (volume1 > volume2) + { + volume = (float)volume1 - (volume1 - volume2); + } + else if (volume2 > volume1) + { + volume = (float)volume2 - (volume2 - volume1); + } + else + { + // Regular cylinder + volume = volume1; + } + } + else + { + // We don't know what the shape is yet, so use default + volume = _size.X * _size.Y * _size.Z; + } + // If the user has 'hollowed out' + // ProfileHollow is one of those 0 to 50000 values :P + // we like percentages better.. so turning into a percentage - // ProfileEnd and ProfileBegin are values - // from 0 to 50000 + if (((float)_pbs.ProfileHollow / 50000f) > 0.0) + { + float hollowAmount = (float)_pbs.ProfileHollow / 50000f; - // Turning them back into percentages so that I can cut that percentage off the volume + // calculate the hollow volume by it's shape compared to the prim shape + float hollowVolume = 0; + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Circle: + // Hollow shape is a perfect cyllinder in respect to the cube's scale + // Cyllinder hollow volume calculation + float hRadius = _size.X / 2; + float hLength = _size.Z; - float PathCutEndAmount = _pbs.ProfileEnd; - float PathCutStartAmount = _pbs.ProfileBegin; - if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) + // pi * r2 * h + hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount); + break; + + case HollowShape.Square: + // Cube Hollow volume calculation + float hollowsizex = _size.X * hollowAmount; + float hollowsizey = _size.Y * hollowAmount; + float hollowsizez = _size.Z * hollowAmount; + hollowVolume = hollowsizex * hollowsizey * hollowsizez; + break; + + case HollowShape.Triangle: + // Equilateral Triangular Prism volume hollow calculation + // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + + float aLength = _size.Y; + // 1/2 abh + hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); + break; + + default: + hollowVolume = 0; + break; + } + volume = volume - hollowVolume; + } + break; + + case ProfileShape.HalfCircle: + if (_pbs.PathCurve == (byte)Extrusion.Curve1) + { + if (_size.X == _size.Y && _size.Y == _size.Z) + { + // regular sphere + // v = 4/3 * pi * r^3 + float sradius3 = (float)Math.Pow((_size.X / 2), 3); + volume = (float)((4f / 3f) * Math.PI * sradius3); + } + else + { + // we treat this as a box currently + volume = _size.X * _size.Y * _size.Z; + } + } + else + { + // We don't know what the shape is yet, so use default + volume = _size.X * _size.Y * _size.Z; + } + break; + + case ProfileShape.EquilateralTriangle: + /* + v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h + + // seed mesh + Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); + Vertex PM = new Vertex(+0.5f, 0f, 0.0f); + Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); + */ + float xA = -0.25f * _size.X; + float yA = -0.45f * _size.Y; + + float xB = 0.5f * _size.X; + float yB = 0; + + float xC = -0.25f * _size.X; + float yC = 0.45f * _size.Y; + + volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z); + + // If the user has 'hollowed out' + // ProfileHollow is one of those 0 to 50000 values :P + // we like percentages better.. so turning into a percentage + float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f); + if (((float)fhollowFactor / 50000f) > 0.0) + { + float hollowAmount = (float)fhollowFactor / 50000f; + + // calculate the hollow volume by it's shape compared to the prim shape + float hollowVolume = 0; + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Triangle: + // Equilateral Triangular Prism volume hollow calculation + // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + + float aLength = _size.Y; + // 1/2 abh + hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); + break; + + case HollowShape.Square: + // Cube Hollow volume calculation + float hollowsizex = _size.X * hollowAmount; + float hollowsizey = _size.Y * hollowAmount; + float hollowsizez = _size.Z * hollowAmount; + hollowVolume = hollowsizex * hollowsizey * hollowsizez; + break; + + case HollowShape.Circle: + // Hollow shape is a perfect cyllinder in respect to the cube's scale + // Cyllinder hollow volume calculation + float hRadius = _size.X / 2; + float hLength = _size.Z; + + // pi * r2 * h + hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength)/2) * hollowAmount); + break; + + default: + hollowVolume = 0; + break; + } + volume = volume - hollowVolume; + } + break; + + default: + // we don't have all of the volume formulas yet so + // use the common volume formula for all + volume = _size.X*_size.Y*_size.Z; + break; + } + + // Calculate Path cut effect on volume + // Not exact, in the triangle hollow example + // They should never be zero or less then zero.. + // we'll ignore it if it's less then zero + + // ProfileEnd and ProfileBegin are values + // from 0 to 50000 + + // Turning them back into percentages so that I can cut that percentage off the volume + + float PathCutEndAmount = _pbs.ProfileEnd; + float PathCutStartAmount = _pbs.ProfileBegin; + if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) { float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f); @@ -894,9 +1339,8 @@ namespace OpenSim.Region.Physics.OdePlugin // } } - public void ProcessTaints(float timestep) + public void ProcessTaints(float timestep) //============================================================================= { -//Console.WriteLine("ProcessTaints for " + m_primName ); if (m_taintadd) { changeadd(timestep); @@ -985,30 +1429,6 @@ namespace OpenSim.Region.Physics.OdePlugin { //Console.WriteLine("Alock changed to {0}", m_taintAngularLock); m_angularlock = m_taintAngularLock; - m_vehicle.SetAngularLock(m_angularlock); - - -/* - if (!m_taintAngularLock.ApproxEquals(Vector3.One, 0f)) - { - //d.BodySetFiniteRotationMode(Body, 0); - //d.BodySetFiniteRotationAxis(Body,m_taintAngularLock.X,m_taintAngularLock.Y,m_taintAngularLock.Z); - createAMotor(m_taintAngularLock); - } - else - { - if (Amotor != IntPtr.Zero) - { - d.JointDestroy(Amotor); - Amotor = IntPtr.Zero; - } - } - } - } - // Store this for later in case we get turned into a separate body - m_angularlock = m_taintAngularLock; - m_vehicle.SetAngularLock(m_angularlock); - } */ } } @@ -1151,11 +1571,6 @@ namespace OpenSim.Region.Physics.OdePlugin prm.m_collisionscore = 0; prm.m_disabled = false; - // The body doesn't already have a finite rotation mode set here - /* ### if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) - { - prm.createAMotor(m_angularlock); - } */ prm.Body = Body; _parent_scene.addActivePrim(prm); } @@ -1194,13 +1609,8 @@ namespace OpenSim.Region.Physics.OdePlugin m_collisionscore = 0; m_disabled = false; - // The body doesn't already have a finite rotation mode set here - /* ### if ((!m_angularlock.ApproxEquals(Vector3.Zero, 0f)) && _parent == null) - { - createAMotor(m_angularlock); - } */ d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); - if (m_vehicle.Type != Vehicle.TYPE_NONE) m_vehicle.Enable(Body, _parent_scene); + if (m_type != Vehicle.TYPE_NONE) Enable(Body, _parent_scene); _parent_scene.addActivePrim(this); } } @@ -1267,17 +1677,12 @@ namespace OpenSim.Region.Physics.OdePlugin //Console.WriteLine("childrenPrim.Remove " + odePrim); childrenPrim.Remove(odePrim); } - - - if (Body != IntPtr.Zero) { _parent_scene.remActivePrim(this); } - - lock (childrenPrim) { foreach (OdePrim prm in childrenPrim) @@ -1286,8 +1691,6 @@ namespace OpenSim.Region.Physics.OdePlugin ParentPrim(prm); } } - - } private void changeSelectedStatus(float timestep) @@ -1515,17 +1918,22 @@ namespace OpenSim.Region.Physics.OdePlugin public void changemove(float timestep) { +//Console.WriteLine("changemove for {0}", m_primName ); + if (m_isphysical) { - - if (!m_disabled && !m_taintremove && !childPrim) +//Console.WriteLine("phys {0} {1} {2}", m_disabled, m_taintremove, childPrim); +// if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits! + if (!m_taintremove && !childPrim) { +//Console.WriteLine("physOK"); if (Body == IntPtr.Zero) enableBody(); //Prim auto disable after 20 frames, //if you move it, re-enable the prim manually. if (_parent != null) { +//Console.WriteLine("physChild"); if (m_linkJoint != IntPtr.Zero) { d.JointDestroy(m_linkJoint); @@ -1534,6 +1942,7 @@ namespace OpenSim.Region.Physics.OdePlugin } if (Body != IntPtr.Zero) { +//Console.WriteLine("physNotIPZ"); d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); if (_parent != null) @@ -1549,9 +1958,9 @@ Console.WriteLine(" JointCreateFixed"); } } d.BodyEnable(Body); - if (m_vehicle.Type != Vehicle.TYPE_NONE) + if (m_type != Vehicle.TYPE_NONE) { - m_vehicle.Enable(Body, _parent_scene); + Enable(Body, _parent_scene); } } else @@ -1566,6 +1975,7 @@ Console.WriteLine(" JointCreateFixed"); } else { +//Console.WriteLine("NONphys"); // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); _parent_scene.waitForSpaceUnlock(m_targetSpace); @@ -1589,433 +1999,234 @@ Console.WriteLine(" JointCreateFixed"); m_taintposition = _position; } - public void Move(float timestep) - { - float fx = 0; - float fy = 0; - float fz = 0; - - frcount++; // used to limit debug comment output - if (frcount > 100) - frcount = 0; - - if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. - { -//if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_vehicle.Type + - // " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); - if (m_vehicle.Type != Vehicle.TYPE_NONE) - { - // 'VEHICLES' are dealt with in ODEDynamics.cs - m_vehicle.Step(timestep, _parent_scene); - } - else - { - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 - // NON-'VEHICLES' are dealt with here - // m_angularlock = <1,1,1> means no lock. a 0 on axis means locked. - -// NB this may be wrong - may lock global axis! Should be LOCAL axis! - if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.One, 0.003f)) - { - d.Vector3 avel2 = d.BodyGetAngularVel(Body); - if (m_angularlock.X == 0) - avel2.X = 0; - if (m_angularlock.Y == 0) - avel2.Y = 0; - if (m_angularlock.Z == 0) - avel2.Z = 0; - d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); - } - //float PID_P = 900.0f; - float m_mass = CalculateMass(); -// fz = 0f; - //m_log.Info(m_collisionFlags.ToString()); + public void rotate(float timestep) + { + d.Quaternion myrot = new d.Quaternion(); + myrot.X = _orientation.X; + myrot.Y = _orientation.Y; + myrot.Z = _orientation.Z; + myrot.W = _orientation.W; + if (Body != IntPtr.Zero) + { + // KF: If this is a root prim do BodySet + d.BodySetQuaternion(Body, ref myrot); + } + else + { + // daughter prim, do Geom set + d.GeomSetQuaternion(prim_geom, ref myrot); + } + + resetCollisionAccounting(); + m_taintrot = _orientation; + } - - //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle. - // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up - // NB Prims in ODE are no subject to global gravity - fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass + private void resetCollisionAccounting() + { + m_collisionscore = 0; + m_interpenetrationcount = 0; + m_disabled = false; + } - if (m_usePID) - { -//if(frcount == 0) Console.WriteLine("PID " + m_primName); - // KF - this is for object MoveToTarget. - - //if (!d.BodyIsEnabled(Body)) - //d.BodySetForce(Body, 0f, 0f, 0f); + public void changedisable(float timestep) + { + m_disabled = true; + if (Body != IntPtr.Zero) + { + d.BodyDisable(Body); + Body = IntPtr.Zero; + } - // no lock; for now it's only called from within Simulate() - - // If the PID Controller isn't active then we set our force - // calculating base velocity to the current position + m_taintdisable = false; + } - if ((m_PIDTau < 1) && (m_PIDTau != 0)) - { - //PID_G = PID_G / m_PIDTau; - m_PIDTau = 1; - } - - if ((PID_G - m_PIDTau) <= 0) - { - PID_G = m_PIDTau + 1; - } - //PidStatus = true; + public void changePhysicsStatus(float timestep) + { + if (m_isphysical == true) + { + if (Body == IntPtr.Zero) + { + if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) + { + changeshape(2f); + } + else + { + enableBody(); + } + } + } + else + { + if (Body != IntPtr.Zero) + { + if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) + { + - // PhysicsVector vec = new PhysicsVector(); - d.Vector3 vel = d.BodyGetLinearVel(Body); + if (prim_geom != IntPtr.Zero) + { + try + { + d.GeomDestroy(prim_geom); + prim_geom = IntPtr.Zero; + _mesh = null; + } + catch (System.AccessViolationException) + { + prim_geom = IntPtr.Zero; + m_log.Error("[PHYSICS]: PrimGeom dead"); + } + } +//Console.WriteLine("changePhysicsStatus for " + m_primName ); + changeadd(2f); + } + if (childPrim) + { + if (_parent != null) + { + OdePrim parent = (OdePrim)_parent; + parent.ChildDelink(this); + } + } + else + { + disableBody(); + } + } + } - d.Vector3 pos = d.BodyGetPosition(Body); - _target_velocity = - new Vector3( - (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep), - (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep), - (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) - ); + changeSelectedStatus(timestep); - // if velocity is zero, use position control; otherwise, velocity control + resetCollisionAccounting(); + m_taintPhysics = m_isphysical; + } - if (_target_velocity.ApproxEquals(Vector3.Zero,0.1f)) - { - // keep track of where we stopped. No more slippin' & slidin' - - // We only want to deactivate the PID Controller if we think we want to have our surrogate - // react to the physics scene by moving it's position. - // Avatar to Avatar collisions - // Prim to avatar collisions + public void changesize(float timestamp) + { + + string oldname = _parent_scene.geom_name_map[prim_geom]; - //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); - //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2); - //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; - d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); - d.BodySetLinearVel(Body, 0, 0, 0); - d.BodyAddForce(Body, 0, 0, fz); - return; - } - else - { - _zeroFlag = false; + if (_size.X <= 0) _size.X = 0.01f; + if (_size.Y <= 0) _size.Y = 0.01f; + if (_size.Z <= 0) _size.Z = 0.01f; - // We're flying and colliding with something - fx = ((_target_velocity.X) - vel.X) * (PID_D); - fy = ((_target_velocity.Y) - vel.Y) * (PID_D); - - // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; + // Cleanup of old prim geometry + if (_mesh != null) + { + // Cleanup meshing here + } + //kill body to rebuild + if (IsPhysical && Body != IntPtr.Zero) + { + if (childPrim) + { + if (_parent != null) + { + OdePrim parent = (OdePrim)_parent; + parent.ChildDelink(this); + } + } + else + { + disableBody(); + } + } + if (d.SpaceQuery(m_targetSpace, prim_geom)) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + d.SpaceRemove(m_targetSpace, prim_geom); + } + d.GeomDestroy(prim_geom); + prim_geom = IntPtr.Zero; + // we don't need to do space calculation because the client sends a position update also. - fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); - } - } // end if (m_usePID) + // Construction of new prim + if (_parent_scene.needsMeshing(_pbs)) + { + float meshlod = _parent_scene.meshSculptLOD; - // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller - if (m_useHoverPID && !m_usePID) - { -//Console.WriteLine("Hover " + m_primName); - - // If we're using the PID controller, then we have no gravity - fz = (-1 * _parent_scene.gravityz) * m_mass; + if (IsPhysical) + meshlod = _parent_scene.MeshSculptphysicalLOD; + // Don't need to re-enable body.. it's done in SetMesh - // no lock; for now it's only called from within Simulate() + IMesh mesh = null; - // If the PID Controller isn't active then we set our force - // calculating base velocity to the current position + if (_parent_scene.needsMeshing(_pbs)) + mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); - if ((m_PIDTau < 1)) - { - PID_G = PID_G / m_PIDTau; - } + //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); +//Console.WriteLine("changesize 1"); + CreateGeom(m_targetSpace, mesh); - if ((PID_G - m_PIDTau) <= 0) - { - PID_G = m_PIDTau + 1; - } - + + } + else + { + _mesh = null; +//Console.WriteLine("changesize 2"); + CreateGeom(m_targetSpace, _mesh); + } - // Where are we, and where are we headed? - d.Vector3 pos = d.BodyGetPosition(Body); - d.Vector3 vel = d.BodyGetLinearVel(Body); + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + d.Quaternion myrot = new d.Quaternion(); + myrot.X = _orientation.X; + myrot.Y = _orientation.Y; + myrot.Z = _orientation.Z; + myrot.W = _orientation.W; + d.GeomSetQuaternion(prim_geom, ref myrot); + //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); + if (IsPhysical && Body == IntPtr.Zero && !childPrim) + { + // Re creates body on size. + // EnableBody also does setMass() + enableBody(); + d.BodyEnable(Body); + } - // Non-Vehicles have a limited set of Hover options. - // determine what our target height really is based on HoverType - switch (m_PIDHoverType) - { - case PIDHoverType.Ground: - m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); - m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; - break; - case PIDHoverType.GroundAndWater: - m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); - m_waterHeight = _parent_scene.GetWaterLevel(); - if (m_groundHeight > m_waterHeight) - { - m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; - } - else - { - m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight; - } - break; + _parent_scene.geom_name_map[prim_geom] = oldname; - } // end switch (m_PIDHoverType) + changeSelectedStatus(timestamp); + if (childPrim) + { + if (_parent is OdePrim) + { + OdePrim parent = (OdePrim)_parent; + parent.ChildSetGeom(this); + } + } + resetCollisionAccounting(); + m_taintsize = _size; + } + - _target_velocity = - new Vector3(0.0f, 0.0f, - (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep) - ); + public void changefloatonwater(float timestep) + { + m_collidesWater = m_taintCollidesWater; - // if velocity is zero, use position control; otherwise, velocity control + if (prim_geom != IntPtr.Zero) + { + if (m_collidesWater) + { + m_collisionFlags |= CollisionCategories.Water; + } + else + { + m_collisionFlags &= ~CollisionCategories.Water; + } + d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); + } + } - if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) - { - // keep track of where we stopped. No more slippin' & slidin' - - // We only want to deactivate the PID Controller if we think we want to have our surrogate - // react to the physics scene by moving it's position. - // Avatar to Avatar collisions - // Prim to avatar collisions + public void changeshape(float timestamp) + { + string oldname = _parent_scene.geom_name_map[prim_geom]; - d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); - d.BodySetLinearVel(Body, vel.X, vel.Y, 0); - d.BodyAddForce(Body, 0, 0, fz); - //KF this prevents furthur motions return; - } - else - { - _zeroFlag = false; - - // We're flying and colliding with something - fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); - } - } // end m_useHoverPID && !m_usePID - - if (m_useAPID) - { - // RotLookAt, apparently overrides all other rotation sources. Inputs: - // Quaternion m_APIDTarget - // float m_APIDStrength // From SL experiments, this is the time to get there - // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly - // Also in SL the mass of the object has no effect on time to get there. - // Factors: -//if(frcount == 0) Console.WriteLine("APID "); - // get present body rotation - float limit = 1.0f; - float scaler = 50f; // adjusts damping time - float RLAservo = 0f; - - d.Quaternion rot = d.BodyGetQuaternion(Body); - Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); - Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget; - float diff_angle; - Vector3 diff_axis; - rot_diff.GetAxisAngle(out diff_axis, out diff_angle); - diff_axis.Normalize(); - if(diff_angle > 0.01f) // diff_angle is always +ve - { -// PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z); - Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z); - rotforce = rotforce * rotq; - if(diff_angle > limit) diff_angle = limit; // cap the rotate rate -// RLAservo = timestep / m_APIDStrength * m_mass * scaler; - // rotforce = rotforce * RLAservo * diff_angle ; - // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); - RLAservo = timestep / m_APIDStrength * scaler; - rotforce = rotforce * RLAservo * diff_angle ; - - if (m_angularlock.X == 0) - rotforce.X = 0; - if (m_angularlock.Y == 0) - rotforce.Y = 0; - if (m_angularlock.Z == 0) - rotforce.Z = 0; - - - - - d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); -//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); - } -//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); - } // end m_useAPID - - fx *= m_mass; - fy *= m_mass; - //fz *= m_mass; - - fx += m_force.X; - fy += m_force.Y; - fz += m_force.Z; - - //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString()); - if (fx != 0 || fy != 0 || fz != 0) - { - //m_taintdisable = true; - //base.RaiseOutOfBounds(Position); - //d.BodySetLinearVel(Body, fx, fy, 0f); - if (!d.BodyIsEnabled(Body)) - { - // A physical body at rest on a surface will auto-disable after a while, - // this appears to re-enable it incase the surface it is upon vanishes, - // and the body should fall again. - d.BodySetLinearVel(Body, 0f, 0f, 0f); - d.BodySetForce(Body, 0, 0, 0); - enableBodySoft(); - } - - // 35x10 = 350n times the mass per second applied maximum. - float nmax = 35f * m_mass; - float nmin = -35f * m_mass; - - - if (fx > nmax) - fx = nmax; - if (fx < nmin) - fx = nmin; - if (fy > nmax) - fy = nmax; - if (fy < nmin) - fy = nmin; - d.BodyAddForce(Body, fx, fy, fz); -//Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); - } - } - } - else - { // is not physical, or is not a body or is selected - // _zeroPosition = d.BodyGetPosition(Body); - return; -//Console.WriteLine("Nothing " + m_primName); - - } - } - - - - public void rotate(float timestep) - { - d.Quaternion myrot = new d.Quaternion(); - myrot.X = _orientation.X; - myrot.Y = _orientation.Y; - myrot.Z = _orientation.Z; - myrot.W = _orientation.W; - if (Body != IntPtr.Zero) - { - // KF: If this is a root prim do BodySet - d.BodySetQuaternion(Body, ref myrot); - /* ### if (m_isphysical) - { - if (!m_angularlock.ApproxEquals(Vector3.One, 0f)) - createAMotor(m_angularlock); - } */ - } - else - { - // daughter prim, do Geom set - d.GeomSetQuaternion(prim_geom, ref myrot); - } - - resetCollisionAccounting(); - m_taintrot = _orientation; - } - - private void resetCollisionAccounting() - { - m_collisionscore = 0; - m_interpenetrationcount = 0; - m_disabled = false; - } - - public void changedisable(float timestep) - { - m_disabled = true; - if (Body != IntPtr.Zero) - { - d.BodyDisable(Body); - Body = IntPtr.Zero; - } - - m_taintdisable = false; - } - - public void changePhysicsStatus(float timestep) - { - if (m_isphysical == true) - { - if (Body == IntPtr.Zero) - { - if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) - { - changeshape(2f); - } - else - { - enableBody(); - } - } - } - else - { - if (Body != IntPtr.Zero) - { - if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) - { - - - if (prim_geom != IntPtr.Zero) - { - try - { - d.GeomDestroy(prim_geom); - prim_geom = IntPtr.Zero; - _mesh = null; - } - catch (System.AccessViolationException) - { - prim_geom = IntPtr.Zero; - m_log.Error("[PHYSICS]: PrimGeom dead"); - } - } -//Console.WriteLine("changePhysicsStatus for " + m_primName ); - changeadd(2f); - } - if (childPrim) - { - if (_parent != null) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildDelink(this); - } - } - else - { - disableBody(); - } - } - } - - changeSelectedStatus(timestep); - - resetCollisionAccounting(); - m_taintPhysics = m_isphysical; - } - - public void changesize(float timestamp) - { - - string oldname = _parent_scene.geom_name_map[prim_geom]; - - if (_size.X <= 0) _size.X = 0.01f; - if (_size.Y <= 0) _size.Y = 0.01f; - if (_size.Z <= 0) _size.Z = 0.01f; - - // Cleanup of old prim geometry - if (_mesh != null) - { - // Cleanup meshing here - } - //kill body to rebuild + // Cleanup of old prim geometry and Bodies if (IsPhysical && Body != IntPtr.Zero) { if (childPrim) @@ -2031,133 +2242,25 @@ Console.WriteLine(" JointCreateFixed"); disableBody(); } } - if (d.SpaceQuery(m_targetSpace, prim_geom)) + try { - _parent_scene.waitForSpaceUnlock(m_targetSpace); - d.SpaceRemove(m_targetSpace, prim_geom); + d.GeomDestroy(prim_geom); + } + catch (System.AccessViolationException) + { + prim_geom = IntPtr.Zero; + m_log.Error("[PHYSICS]: PrimGeom dead"); } - d.GeomDestroy(prim_geom); prim_geom = IntPtr.Zero; // we don't need to do space calculation because the client sends a position update also. - + if (_size.X <= 0) _size.X = 0.01f; + if (_size.Y <= 0) _size.Y = 0.01f; + if (_size.Z <= 0) _size.Z = 0.01f; // Construction of new prim + if (_parent_scene.needsMeshing(_pbs)) { - float meshlod = _parent_scene.meshSculptLOD; - - if (IsPhysical) - meshlod = _parent_scene.MeshSculptphysicalLOD; - // Don't need to re-enable body.. it's done in SetMesh - - IMesh mesh = null; - - if (_parent_scene.needsMeshing(_pbs)) - mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); - - //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); -//Console.WriteLine("changesize 1"); - CreateGeom(m_targetSpace, mesh); - - - } - else - { - _mesh = null; -//Console.WriteLine("changesize 2"); - CreateGeom(m_targetSpace, _mesh); - } - - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.Quaternion myrot = new d.Quaternion(); - myrot.X = _orientation.X; - myrot.Y = _orientation.Y; - myrot.Z = _orientation.Z; - myrot.W = _orientation.W; - d.GeomSetQuaternion(prim_geom, ref myrot); - - //d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z); - if (IsPhysical && Body == IntPtr.Zero && !childPrim) - { - // Re creates body on size. - // EnableBody also does setMass() - enableBody(); - d.BodyEnable(Body); - } - - _parent_scene.geom_name_map[prim_geom] = oldname; - - changeSelectedStatus(timestamp); - if (childPrim) - { - if (_parent is OdePrim) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildSetGeom(this); - } - } - resetCollisionAccounting(); - m_taintsize = _size; - } - - - - public void changefloatonwater(float timestep) - { - m_collidesWater = m_taintCollidesWater; - - if (prim_geom != IntPtr.Zero) - { - if (m_collidesWater) - { - m_collisionFlags |= CollisionCategories.Water; - } - else - { - m_collisionFlags &= ~CollisionCategories.Water; - } - d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); - } - } - - public void changeshape(float timestamp) - { - string oldname = _parent_scene.geom_name_map[prim_geom]; - - // Cleanup of old prim geometry and Bodies - if (IsPhysical && Body != IntPtr.Zero) - { - if (childPrim) - { - if (_parent != null) - { - OdePrim parent = (OdePrim)_parent; - parent.ChildDelink(this); - } - } - else - { - disableBody(); - } - } - try - { - d.GeomDestroy(prim_geom); - } - catch (System.AccessViolationException) - { - prim_geom = IntPtr.Zero; - m_log.Error("[PHYSICS]: PrimGeom dead"); - } - prim_geom = IntPtr.Zero; - // we don't need to do space calculation because the client sends a position update also. - if (_size.X <= 0) _size.X = 0.01f; - if (_size.Y <= 0) _size.Y = 0.01f; - if (_size.Z <= 0) _size.Z = 0.01f; - // Construction of new prim - - if (_parent_scene.needsMeshing(_pbs)) - { - // Don't need to re-enable body.. it's done in SetMesh + // Don't need to re-enable body.. it's done in SetMesh float meshlod = _parent_scene.meshSculptLOD; if (IsPhysical) @@ -2319,392 +2422,834 @@ Console.WriteLine(" JointCreateFixed"); m_taintVelocity = Vector3.Zero; } - public override bool IsPhysical + public void UpdatePositionAndVelocity() { - get { return m_isphysical; } - set - { - m_isphysical = value; - if (!m_isphysical) - { // Zero the remembered last velocity - m_lastVelocity = Vector3.Zero; - if (m_vehicle.Type != Vehicle.TYPE_NONE) m_vehicle.Halt(); - } - } - } + return; // moved to the MOVE() method + // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! + if (_parent == null) + { + Vector3 pv = Vector3.Zero; + bool lastZeroFlag = _zeroFlag; + if (Body != (IntPtr)0) // FIXME -> or if it is a joint + { + d.Vector3 vec = d.BodyGetPosition(Body); + d.Quaternion ori = d.BodyGetQuaternion(Body); + d.Vector3 vel = d.BodyGetLinearVel(Body); + d.Vector3 rotvel = d.BodyGetAngularVel(Body); + d.Vector3 torque = d.BodyGetTorque(Body); + _torque = new Vector3(torque.X, torque.Y, torque.Z); + Vector3 l_position = Vector3.Zero; + Quaternion l_orientation = Quaternion.Identity; - public void setPrimForRemoval() - { - m_taintremove = true; - } + // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) + //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } + //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - public override bool Flying - { - // no flying prims for you - get { return false; } - set { } - } + m_lastposition = _position; + m_lastorientation = _orientation; + + l_position.X = vec.X; + l_position.Y = vec.Y; + l_position.Z = vec.Z; + l_orientation.X = ori.X; + l_orientation.Y = ori.Y; + l_orientation.Z = ori.Z; + l_orientation.W = ori.W; + +// if(l_position.Y != m_lastposition.Y){ +// Console.WriteLine("UP&V {0} {1}", m_primName, l_position); +// } - public override bool IsColliding - { - get { return iscolliding; } - set { iscolliding = value; } - } + if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f) + { + //base.RaiseOutOfBounds(l_position); - public override bool CollidingGround - { - get { return false; } - set { return; } - } + if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds) + { + _position = l_position; + //_parent_scene.remActivePrim(this); + if (_parent == null) + base.RequestPhysicsterseUpdate(); + return; + } + else + { + if (_parent == null) + base.RaiseOutOfBounds(l_position); + return; + } + } - public override bool CollidingObj - { - get { return false; } - set { return; } - } + if (l_position.Z < 0) + { + // This is so prim that get lost underground don't fall forever and suck up + // + // Sim resources and memory. + // Disables the prim's movement physics.... + // It's a hack and will generate a console message if it fails. - public override bool ThrottleUpdates - { - get { return m_throttleUpdates; } - set { m_throttleUpdates = value; } - } + //IsPhysical = false; + if (_parent == null) + base.RaiseOutOfBounds(_position); - public override bool Stopped - { - get { return _zeroFlag; } - } + _acceleration.X = 0; + _acceleration.Y = 0; + _acceleration.Z = 0; - public override Vector3 Position - { - get { return _position; } + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; - set { _position = value; - //m_log.Info("[PHYSICS]: " + _position.ToString()); - } - } + if (_parent == null) + base.RequestPhysicsterseUpdate(); - public override Vector3 Size - { - get { return _size; } - set - { - if (value.IsFinite()) - { - _size = value; - } - else - { - m_log.Warn("[PHYSICS]: Got NaN Size on object"); - } - } - } + m_throttleUpdates = false; + throttleCounter = 0; + _zeroFlag = true; + //outofBounds = true; + } - public override float Mass - { - get { return CalculateMass(); } - } + //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)); +//Console.WriteLine("Adiff " + m_primName + " = " + Adiff); + if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) + && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) + && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) +// && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01)) + && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large + { + _zeroFlag = true; +//Console.WriteLine("ZFT 2"); + m_throttleUpdates = false; + } + else + { + //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString()); + _zeroFlag = false; + m_lastUpdateSent = false; + //m_throttleUpdates = false; + } - public override Vector3 Force - { - //get { return Vector3.Zero; } - get { return m_force; } - set - { - if (value.IsFinite()) - { - m_force = value; + if (_zeroFlag) + { + _velocity.X = 0.0f; + _velocity.Y = 0.0f; + _velocity.Z = 0.0f; + + _acceleration.X = 0; + _acceleration.Y = 0; + _acceleration.Z = 0; + + //_orientation.w = 0f; + //_orientation.X = 0f; + //_orientation.Y = 0f; + //_orientation.Z = 0f; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + if (!m_lastUpdateSent) + { + m_throttleUpdates = false; + throttleCounter = 0; + m_rotationalVelocity = pv; + + if (_parent == null) + { + base.RequestPhysicsterseUpdate(); + } + + m_lastUpdateSent = true; + } + } + else + { + if (lastZeroFlag != _zeroFlag) + { + if (_parent == null) + { + base.RequestPhysicsterseUpdate(); + } + } + + m_lastVelocity = _velocity; + + _position = l_position; + + _velocity.X = vel.X; + _velocity.Y = vel.Y; + _velocity.Z = vel.Z; + + _acceleration = ((_velocity - m_lastVelocity) / 0.1f); + _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); + //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); + +// if (_velocity.ApproxEquals(pv, 0.5f)) ???? Disregard rotational vel if lin vel is < 0.5 ????? +// { +// m_rotationalVelocity = pv;/ + +// } +// else +// { + m_rotationalVelocity = new Vector3(rotvel.X, rotvel.Y, rotvel.Z); +// } + + //m_log.Debug("ODE: " + m_rotationalVelocity.ToString()); + _orientation.X = ori.X; + _orientation.Y = ori.Y; + _orientation.Z = ori.Z; + _orientation.W = ori.W; + m_lastUpdateSent = false; + if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) + { + if (_parent == null) + { + base.RequestPhysicsterseUpdate(); + } + } + else + { + throttleCounter++; + } + } + m_lastposition = l_position; } else { - m_log.Warn("[PHYSICS]: NaN in Force Applied to an Object"); + // Not a body.. so Make sure the client isn't interpolating + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + + _acceleration.X = 0; + _acceleration.Y = 0; + _acceleration.Z = 0; + + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + _zeroFlag = true; } } } - public override int VehicleType + public Matrix4 FromDMass(d.Mass pMass) { - get { return (int)m_vehicle.Type; } - set { m_vehicle.ProcessTypeChange((Vehicle)value); } + Matrix4 obj; + obj.M11 = pMass.I.M00; + obj.M12 = pMass.I.M01; + obj.M13 = pMass.I.M02; + obj.M14 = 0; + obj.M21 = pMass.I.M10; + obj.M22 = pMass.I.M11; + obj.M23 = pMass.I.M12; + obj.M24 = 0; + obj.M31 = pMass.I.M20; + obj.M32 = pMass.I.M21; + obj.M33 = pMass.I.M22; + obj.M34 = 0; + obj.M41 = 0; + obj.M42 = 0; + obj.M43 = 0; + obj.M44 = 1; + return obj; } - public override void VehicleFloatParam(int param, float value) + public d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj) { - m_vehicle.ProcessFloatVehicleParam((Vehicle) param, value); + obj.I.M00 = pMat[0, 0]; + obj.I.M01 = pMat[0, 1]; + obj.I.M02 = pMat[0, 2]; + obj.I.M10 = pMat[1, 0]; + obj.I.M11 = pMat[1, 1]; + obj.I.M12 = pMat[1, 2]; + obj.I.M20 = pMat[2, 0]; + obj.I.M21 = pMat[2, 1]; + obj.I.M22 = pMat[2, 2]; + return obj; } - public override void VehicleVectorParam(int param, Vector3 value) + public override void SubscribeEvents(int ms) { - m_vehicle.ProcessVectorVehicleParam((Vehicle) param, value); + m_eventsubscription = ms; + _parent_scene.addCollisionEventReporting(this); } - public override void VehicleRotationParam(int param, Quaternion rotation) - { - m_vehicle.ProcessRotationVehicleParam((Vehicle) param, rotation); - } - - public override void VehicleFlagsSet(int flags) - { - m_vehicle.ProcessFlagsVehicleSet(flags); - } - - public override void VehicleFlagsRemove(int flags) + public override void UnSubscribeEvents() { - m_vehicle.ProcessFlagsVehicleRemove(flags); + _parent_scene.remCollisionEventReporting(this); + m_eventsubscription = 0; } - - public override void SetVolumeDetect(int param) + + public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { - lock (_parent_scene.OdeLock) - { - m_isVolumeDetect = (param!=0); - } + if (CollisionEventsThisFrame == null) + CollisionEventsThisFrame = new CollisionEventUpdate(); + CollisionEventsThisFrame.addCollider(CollidedWith, contact); } - public override Vector3 CenterOfMass + public void SendCollisions() { - get { return Vector3.Zero; } + if (CollisionEventsThisFrame == null) + return; + + base.SendCollisionUpdate(CollisionEventsThisFrame); + + if (CollisionEventsThisFrame.m_objCollisionList.Count == 0) + CollisionEventsThisFrame = null; + else + CollisionEventsThisFrame = new CollisionEventUpdate(); } - public override Vector3 GeometricCenter + public override bool SubscribedEvents() { - get { return Vector3.Zero; } + if (m_eventsubscription > 0) + return true; + return false; } - public override PrimitiveBaseShape Shape + public static Matrix4 Inverse(Matrix4 pMat) { - set + if (determinant3x3(pMat) == 0) { - _pbs = value; - m_taintshape = true; + return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible } + + + + return (Adjoint(pMat) / determinant3x3(pMat)); } - public override Vector3 Velocity + public static Matrix4 Adjoint(Matrix4 pMat) { - get - { - // Averate previous velocity with the new one so - // client object interpolation works a 'little' better - if (_zeroFlag) - return Vector3.Zero; - - Vector3 returnVelocity = Vector3.Zero; - returnVelocity.X = (m_lastVelocity.X + _velocity.X)/2; - returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y)/2; - returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z)/2; - return returnVelocity; - } - set + Matrix4 adjointMatrix = new Matrix4(); + for (int i=0; i<4; i++) { - if (value.IsFinite()) - { - _velocity = value; - - m_taintVelocity = value; - _parent_scene.AddPhysicsActorTaint(this); - } - else + for (int j=0; j<4; j++) { - m_log.Warn("[PHYSICS]: Got NaN Velocity in Object"); + Matrix4SetValue(ref adjointMatrix, i, j, (float)(Math.Pow(-1, i + j) * (determinant3x3(Minor(pMat, i, j))))); } - } + + adjointMatrix = Transpose(adjointMatrix); + return adjointMatrix; } - public override Vector3 Torque + public static Matrix4 Minor(Matrix4 matrix, int iRow, int iCol) { - get + Matrix4 minor = new Matrix4(); + int m = 0, n = 0; + for (int i = 0; i < 4; i++) { - if (!m_isphysical || Body == IntPtr.Zero) - return Vector3.Zero; - - return _torque; - } - - set - { - if (value.IsFinite()) - { - m_taintTorque = value; - _parent_scene.AddPhysicsActorTaint(this); - } - else + if (i == iRow) + continue; + n = 0; + for (int j = 0; j < 4; j++) { - m_log.Warn("[PHYSICS]: Got NaN Torque in Object"); + if (j == iCol) + continue; + Matrix4SetValue(ref minor, m,n, matrix[i, j]); + n++; } + m++; } - } -/* - public Vector3 AngularLock - { - get { return m_angularlock; } - set { } - } - -*/ - public override float CollisionScore - { - get { return m_collisionscore; } - set { m_collisionscore = value; } + return minor; } - public override bool Kinematic + public static Matrix4 Transpose(Matrix4 pMat) { - get { return false; } - set { } + Matrix4 transposeMatrix = new Matrix4(); + for (int i = 0; i < 4; i++) + for (int j = 0; j < 4; j++) + Matrix4SetValue(ref transposeMatrix, i, j, pMat[j, i]); + return transposeMatrix; } - public override Quaternion Orientation + public static void Matrix4SetValue(ref Matrix4 pMat, int r, int c, float val) { - get { return _orientation; } - set + switch (r) { - if (QuaternionIsFinite(value)) - { - _orientation = value; - } - else - m_log.Warn("[PHYSICS]: Got NaN quaternion Orientation from Scene in Object"); + case 0: + switch (c) + { + case 0: + pMat.M11 = val; + break; + case 1: + pMat.M12 = val; + break; + case 2: + pMat.M13 = val; + break; + case 3: + pMat.M14 = val; + break; + } + + break; + case 1: + switch (c) + { + case 0: + pMat.M21 = val; + break; + case 1: + pMat.M22 = val; + break; + case 2: + pMat.M23 = val; + break; + case 3: + pMat.M24 = val; + break; + } + + break; + case 2: + switch (c) + { + case 0: + pMat.M31 = val; + break; + case 1: + pMat.M32 = val; + break; + case 2: + pMat.M33 = val; + break; + case 3: + pMat.M34 = val; + break; + } + + break; + case 3: + switch (c) + { + case 0: + pMat.M41 = val; + break; + case 1: + pMat.M42 = val; + break; + case 2: + pMat.M43 = val; + break; + case 3: + pMat.M44 = val; + break; + } + break; } } + private static float determinant3x3(Matrix4 pMat) + { + float det = 0; + float diag1 = pMat[0, 0]*pMat[1, 1]*pMat[2, 2]; + float diag2 = pMat[0, 1]*pMat[2, 1]*pMat[2, 0]; + float diag3 = pMat[0, 2]*pMat[1, 0]*pMat[2, 1]; + float diag4 = pMat[2, 0]*pMat[1, 1]*pMat[0, 2]; + float diag5 = pMat[2, 1]*pMat[1, 2]*pMat[0, 0]; + float diag6 = pMat[2, 2]*pMat[1, 0]*pMat[0, 1]; - internal static bool QuaternionIsFinite(Quaternion q) + det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6); + return det; + + } + + private static void DMassCopy(ref d.Mass src, ref d.Mass dst) { - if (Single.IsNaN(q.X) || Single.IsInfinity(q.X)) - return false; - if (Single.IsNaN(q.Y) || Single.IsInfinity(q.Y)) - return false; - if (Single.IsNaN(q.Z) || Single.IsInfinity(q.Z)) - return false; - if (Single.IsNaN(q.W) || Single.IsInfinity(q.W)) - return false; - return true; + dst.c.W = src.c.W; + dst.c.X = src.c.X; + dst.c.Y = src.c.Y; + dst.c.Z = src.c.Z; + dst.mass = src.mass; + dst.I.M00 = src.I.M00; + dst.I.M01 = src.I.M01; + dst.I.M02 = src.I.M02; + dst.I.M10 = src.I.M10; + dst.I.M11 = src.I.M11; + dst.I.M12 = src.I.M12; + dst.I.M20 = src.I.M20; + dst.I.M21 = src.I.M21; + dst.I.M22 = src.I.M22; } - public override Vector3 Acceleration + public override void SetMaterial(int pMaterial) { - get { return _acceleration; } + m_material = pMaterial; } + + - public void SetAcceleration(Vector3 accel) - { - _acceleration = accel; - } - public override void AddForce(Vector3 force, bool pushforce) + + internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) { - if (force.IsFinite()) + switch (pParam) { - lock (m_forcelist) - m_forcelist.Add(force); + case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionEfficiency = pValue; + break; + case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionTimescale = pValue; + break; + case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorDecayTimescale = pValue; + break; + case Vehicle.ANGULAR_MOTOR_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorTimescale = pValue; + break; + case Vehicle.BANKING_EFFICIENCY: + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingEfficiency = pValue; + break; + case Vehicle.BANKING_MIX: + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingMix = pValue; + break; + case Vehicle.BANKING_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingTimescale = pValue; + break; + case Vehicle.BUOYANCY: + if (pValue < -1f) pValue = -1f; + if (pValue > 1f) pValue = 1f; + m_VehicleBuoyancy = pValue; + break; +// case Vehicle.HOVER_EFFICIENCY: +// if (pValue < 0f) pValue = 0f; +// if (pValue > 1f) pValue = 1f; +// m_VhoverEfficiency = pValue; +// break; + case Vehicle.HOVER_HEIGHT: + m_VhoverHeight = pValue; + break; + case Vehicle.HOVER_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_VhoverTimescale = pValue; + break; + case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionEfficiency = pValue; + break; + case Vehicle.LINEAR_DEFLECTION_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionTimescale = pValue; + break; + case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorDecayTimescale = pValue; + break; + case Vehicle.LINEAR_MOTOR_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorTimescale = pValue; + break; + case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: + if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable + if (pValue > 1.0f) pValue = 1.0f; + m_verticalAttractionEfficiency = pValue; + break; + case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: + if (pValue < 0.01f) pValue = 0.01f; + m_verticalAttractionTimescale = pValue; + break; + + // These are vector properties but the engine lets you use a single float value to + // set all of the components to the same value + case Vehicle.ANGULAR_FRICTION_TIMESCALE: + if (pValue > 30f) pValue = 30f; + if (pValue < 0.1f) pValue = 0.1f; + m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); + break; + case Vehicle.ANGULAR_MOTOR_DIRECTION: + m_angularMotorDirection = new Vector3(pValue, pValue, pValue); + UpdateAngDecay(); + break; + case Vehicle.LINEAR_FRICTION_TIMESCALE: + m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); + break; + case Vehicle.LINEAR_MOTOR_DIRECTION: + m_linearMotorDirection = new Vector3(pValue, pValue, pValue); + UpdateLinDecay(); + break; + case Vehicle.LINEAR_MOTOR_OFFSET: + // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); + break; - m_taintforce = true; - } - else - { - m_log.Warn("[PHYSICS]: Got Invalid linear force vector from Scene in Object"); } - //m_log.Info("[PHYSICS]: Added Force:" + force.ToString() + " to prim at " + Position.ToString()); - } + + }//end ProcessFloatVehicleParam - public override void AddAngularForce(Vector3 force, bool pushforce) + internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) { - if (force.IsFinite()) - { - m_angularforcelist.Add(force); - m_taintaddangularforce = true; - } - else + switch (pParam) { - m_log.Warn("[PHYSICS]: Got Invalid Angular force vector from Scene in Object"); + case Vehicle.ANGULAR_FRICTION_TIMESCALE: + if (pValue.X > 30f) pValue.X = 30f; + if (pValue.X < 0.1f) pValue.X = 0.1f; + if (pValue.Y > 30f) pValue.Y = 30f; + if (pValue.Y < 0.1f) pValue.Y = 0.1f; + if (pValue.Z > 30f) pValue.Z = 30f; + if (pValue.Z < 0.1f) pValue.Z = 0.1f; + m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + case Vehicle.ANGULAR_MOTOR_DIRECTION: + m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); + // Limit requested angular speed to 2 rps= 4 pi rads/sec + if(m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; + if(m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; + if(m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; + if(m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; + if(m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; + if(m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; + UpdateAngDecay(); + break; + case Vehicle.LINEAR_FRICTION_TIMESCALE: + m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; + case Vehicle.LINEAR_MOTOR_DIRECTION: + m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); // velocity requested by LSL, for max limiting + UpdateLinDecay(); + break; + case Vehicle.LINEAR_MOTOR_OFFSET: + // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); + break; } - } + + }//end ProcessVectorVehicleParam - public override Vector3 RotationalVelocity + internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) { - get - { -/* Vector3 pv = Vector3.Zero; - if (_zeroFlag) - return pv; - m_lastUpdateSent = false; - - if (m_rotationalVelocity.ApproxEquals(pv, 0.2f)) - return pv; -*/ - return m_rotationalVelocity; - } - set + switch (pParam) { - if (value.IsFinite()) - { - m_rotationalVelocity = value; - } - else - { - m_log.Warn("[PHYSICS]: Got NaN RotationalVelocity in Object"); - } + case Vehicle.REFERENCE_FRAME: + // m_referenceFrame = pValue; + break; } - } + + }//end ProcessRotationVehicleParam - public override void CrossingFailure() + internal void ProcessFlagsVehicleSet(int flags) { - m_crossingfailures++; - if (m_crossingfailures > _parent_scene.geomCrossingFailuresBeforeOutofbounds) - { - base.RaiseOutOfBounds(_position); - return; - } - else if (m_crossingfailures == _parent_scene.geomCrossingFailuresBeforeOutofbounds) - { - m_log.Warn("[PHYSICS]: Too many crossing failures for: " + m_primName); - } + m_flags |= (VehicleFlag)flags; } - public override float Buoyancy + internal void ProcessFlagsVehicleRemove(int flags) { - get { return m_buoyancy; } - set { m_buoyancy = value; } + m_flags &= ~((VehicleFlag)flags); } + + internal void ProcessTypeChange(Vehicle pType) + { + // Set Defaults For Type + m_type = pType; + switch (pType) + { + case Vehicle.TYPE_SLED: + m_linearFrictionTimescale = new Vector3(30, 1, 1000); + m_angularFrictionTimescale = new Vector3(30, 30, 30); +// m_lLinMotorVel = Vector3.Zero; + m_linearMotorTimescale = 1000; + m_linearMotorDecayTimescale = 120; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; + m_angularMotorTimescale = 1000; + m_angularMotorDecayTimescale = 120; + m_VhoverHeight = 0; +// m_VhoverEfficiency = 1; + m_VhoverTimescale = 10; + m_VehicleBuoyancy = 0; + // m_linearDeflectionEfficiency = 1; + // m_linearDeflectionTimescale = 1; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 1000; + // m_bankingEfficiency = 0; + // m_bankingMix = 1; + // m_bankingTimescale = 10; + // m_referenceFrame = Quaternion.Identity; + m_flags &= + ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + break; + case Vehicle.TYPE_CAR: + m_linearFrictionTimescale = new Vector3(100, 2, 1000); + m_angularFrictionTimescale = new Vector3(30, 30, 30); // was 1000, but sl max frict time is 30. +// m_lLinMotorVel = Vector3.Zero; + m_linearMotorTimescale = 1; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; + m_angularMotorTimescale = 1; + m_angularMotorDecayTimescale = 0.8f; + m_VhoverHeight = 0; +// m_VhoverEfficiency = 0; + m_VhoverTimescale = 1000; + m_VehicleBuoyancy = 0; + // // m_linearDeflectionEfficiency = 1; + // // m_linearDeflectionTimescale = 2; + // // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 10; + m_verticalAttractionEfficiency = 1f; + m_verticalAttractionTimescale = 10f; + // m_bankingEfficiency = -0.2f; + // m_bankingMix = 1; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_UP_ONLY | + VehicleFlag.LIMIT_MOTOR_UP); + break; + case Vehicle.TYPE_BOAT: + m_linearFrictionTimescale = new Vector3(10, 3, 2); + m_angularFrictionTimescale = new Vector3(10,10,10); +// m_lLinMotorVel = Vector3.Zero; + m_linearMotorTimescale = 5; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; + m_angularMotorTimescale = 4; + m_angularMotorDecayTimescale = 4; + m_VhoverHeight = 0; +// m_VhoverEfficiency = 0.5f; + m_VhoverTimescale = 2; + m_VehicleBuoyancy = 1; + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 0.5f; + // m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 0.5f; + m_verticalAttractionTimescale = 5f; + // m_bankingEfficiency = -0.3f; + // m_bankingMix = 0.8f; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.LIMIT_ROLL_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | + VehicleFlag.LIMIT_MOTOR_UP); + break; + case Vehicle.TYPE_AIRPLANE: + m_linearFrictionTimescale = new Vector3(200, 10, 5); + m_angularFrictionTimescale = new Vector3(20, 20, 20); +// m_lLinMotorVel = Vector3.Zero; + m_linearMotorTimescale = 2; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; + m_angularMotorTimescale = 4; + m_angularMotorDecayTimescale = 4; + m_VhoverHeight = 0; +// m_VhoverEfficiency = 0.5f; + m_VhoverTimescale = 1000; + m_VehicleBuoyancy = 0; + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 2; + m_verticalAttractionEfficiency = 0.9f; + m_verticalAttractionTimescale = 2f; + // m_bankingEfficiency = 1; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 2; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); + break; + case Vehicle.TYPE_BALLOON: + m_linearFrictionTimescale = new Vector3(5, 5, 5); + m_angularFrictionTimescale = new Vector3(10, 10, 10); + m_linearMotorTimescale = 5; + m_linearMotorDecayTimescale = 60; + m_angularMotorDirection = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; + m_angularMotorTimescale = 6; + m_angularMotorDecayTimescale = 10; + m_VhoverHeight = 5; +// m_VhoverEfficiency = 0.8f; + m_VhoverTimescale = 10; + m_VehicleBuoyancy = 1; + // m_linearDeflectionEfficiency = 0; + // m_linearDeflectionTimescale = 5; + // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 5; + m_verticalAttractionEfficiency = 1f; + m_verticalAttractionTimescale = 100f; + // m_bankingEfficiency = 0; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 5; + // m_referenceFrame = Quaternion.Identity; + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_UP_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + break; - public override void link(PhysicsActor obj) - { - m_taintparent = obj; - } + } + }//end SetDefaultsForType - public override void delink() + internal void Enable(IntPtr pBody, OdeScene pParentScene) { - m_taintparent = null; - } + if (m_type == Vehicle.TYPE_NONE) + return; - public override void LockAngularMotion(Vector3 axis) + m_body = pBody; + } + + + internal void Halt() + { // Kill all motions, when non-physical + m_linearMotorDirection = Vector3.Zero; + m_lLinMotorDVel = Vector3.Zero; + m_lLinObjectVel = Vector3.Zero; + m_wLinObjectVel = Vector3.Zero; + m_angularMotorDirection = Vector3.Zero; + m_lastAngularVelocity = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; + } + + private void UpdateLinDecay() + { + if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X; + if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y; + if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z; + } // else let the motor decay on its own + + private void UpdateAngDecay() + { + if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X; + if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y; + if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z; + } // else let the motor decay on its own + + public void Move(float timestep) { - // reverse the zero/non zero values for ODE. - if (axis.IsFinite()) - { - axis.X = (axis.X > 0) ? 1f : 0f; - axis.Y = (axis.Y > 0) ? 1f : 0f; - axis.Z = (axis.Z > 0) ? 1f : 0f; - m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); - m_taintAngularLock = axis; - } - else - { - m_log.Warn("[PHYSICS]: Got NaN locking axis from Scene on Object"); - } - } + float fx = 0; + float fy = 0; + float fz = 0; - public void UpdatePositionAndVelocity() - { - // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! - if (_parent == null) + frcount++; // used to limit debug comment output + if (frcount > 100) + frcount = 0; + + if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. { - Vector3 pv = Vector3.Zero; - bool lastZeroFlag = _zeroFlag; - if (Body != (IntPtr)0) // FIXME -> or if it is a joint - { + +// Old public void UpdatePositionAndVelocity(), more accuratley calculated here + // Vector3 pv = Vector3.Zero; // what was this for? + bool lastZeroFlag = _zeroFlag; // was it stopped + // if (Body != (IntPtr)0) // FIXME -> or if it is a joint + // { d.Vector3 vec = d.BodyGetPosition(Body); d.Quaternion ori = d.BodyGetQuaternion(Body); d.Vector3 vel = d.BodyGetLinearVel(Body); @@ -2730,12 +3275,13 @@ Console.WriteLine(" JointCreateFixed"); l_orientation.Y = ori.Y; l_orientation.Z = ori.Z; l_orientation.W = ori.W; +//Console.WriteLine("Move {0} at {1}", m_primName, l_position); -// if(l_position.Y != m_lastposition.Y){ -// Console.WriteLine("UP&V {0} {1}", m_primName, l_position); -// } - if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f) + if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || + l_position.X < 0f || + l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || + l_position.Y < 0f) { //base.RaiseOutOfBounds(l_position); @@ -2808,7 +3354,7 @@ Console.WriteLine(" JointCreateFixed"); } if (_zeroFlag) - { + { // Its stopped _velocity.X = 0.0f; _velocity.Y = 0.0f; _velocity.Z = 0.0f; @@ -2828,7 +3374,7 @@ Console.WriteLine(" JointCreateFixed"); { m_throttleUpdates = false; throttleCounter = 0; - m_rotationalVelocity = pv; + // m_rotationalVelocity = pv; What was this for? if (_parent == null) { @@ -2839,7 +3385,7 @@ Console.WriteLine(" JointCreateFixed"); } } else - { + { // Its moving if (lastZeroFlag != _zeroFlag) { if (_parent == null) @@ -2855,22 +3401,14 @@ Console.WriteLine(" JointCreateFixed"); _velocity.X = vel.X; _velocity.Y = vel.Y; _velocity.Z = vel.Z; - - _acceleration = ((_velocity - m_lastVelocity) / 0.1f); - _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); - //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); - -// if (_velocity.ApproxEquals(pv, 0.5f)) ???? Disregard rotational vel if lin vel is < 0.5 ????? -// { -// m_rotationalVelocity = pv;/ - -// } -// else -// { - m_rotationalVelocity = new Vector3(rotvel.X, rotvel.Y, rotvel.Z); -// } - - //m_log.Debug("ODE: " + m_rotationalVelocity.ToString()); +// Why 2 calcs??? +// _acceleration = ((_velocity - m_lastVelocity) / 0.1f); +// _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, +// _velocity.Y - m_lastVelocity.Y / 0.1f, +// _velocity.Z - m_lastVelocity.Z / 0.1f); + + _acceleration = ((_velocity - m_lastVelocity) / timestep); + _orientation.X = ori.X; _orientation.Y = ori.Y; _orientation.Z = ori.Z; @@ -2889,434 +3427,592 @@ Console.WriteLine(" JointCreateFixed"); } } m_lastposition = l_position; - } - else - { - // Not a body.. so Make sure the client isn't interpolating - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; + + /// End of old UpdatePositionAndVelocity insert + +//if (!Acceleration.ApproxEquals(Vector3.Zero, 0.01f)) Console.WriteLine("Move " + m_primName + " Accel=" + Acceleration); +//if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_type + + // " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); + if (m_type != Vehicle.TYPE_NONE) + { + // get body attitude + d.Quaternion rot = d.BodyGetQuaternion(Body); + Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object + Quaternion irotq = Quaternion.Inverse(rotq); + + // VEHICLE Linear Motion + d.Vector3 velnow = d.BodyGetLinearVel(Body); // this is in world frame + Vector3 vel_now = new Vector3(velnow.X, velnow.Y, velnow.Z); + m_lLinObjectVel = vel_now * irotq; + + if (m_linearMotorDecayTimescale < 300.0f) //setting of 300 or more disables decay rate + { + if ( Vector3.Mag(m_lLinMotorDVel) < 1.0f) + { + float decayfactor = m_linearMotorDecayTimescale/timestep; + Vector3 decayAmount = (m_lLinMotorDVel/decayfactor); + m_lLinMotorDVel -= decayAmount; + } + else + { + float decayfactor = 3.0f - (0.57f * (float)Math.Log((double)(m_linearMotorDecayTimescale))); + Vector3 decel = Vector3.Normalize(m_lLinMotorDVel) * decayfactor * timestep; + m_lLinMotorDVel -= decel; + } + if (m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) + { + m_lLinMotorDVel = Vector3.Zero; + } + else + { + if (Math.Abs(m_lLinMotorDVel.X) < Math.Abs(m_lLinObjectVel.X)) m_lLinObjectVel.X = m_lLinMotorDVel.X; + if (Math.Abs(m_lLinMotorDVel.Y) < Math.Abs(m_lLinObjectVel.Y)) m_lLinObjectVel.Y = m_lLinMotorDVel.Y; + if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z; + } + } // end linear motor decay + + if ( (! m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! m_lLinObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) + { + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + if (m_linearMotorTimescale < 300.0f) + { + Vector3 attack_error = m_lLinMotorDVel - m_lLinObjectVel; + float linfactor = m_linearMotorTimescale/timestep; + Vector3 attackAmount = (attack_error/linfactor) * 1.3f; + m_lLinObjectVel += attackAmount; + } + if (m_linearFrictionTimescale.X < 300.0f) + { + float fricfactor = m_linearFrictionTimescale.X / timestep; + float fricX = m_lLinObjectVel.X / fricfactor; + m_lLinObjectVel.X -= fricX; + } + if (m_linearFrictionTimescale.Y < 300.0f) + { + float fricfactor = m_linearFrictionTimescale.Y / timestep; + float fricY = m_lLinObjectVel.Y / fricfactor; + m_lLinObjectVel.Y -= fricY; + } + if (m_linearFrictionTimescale.Z < 300.0f) + { + float fricfactor = m_linearFrictionTimescale.Z / timestep; +//if(frcount == 0) Console.WriteLine("Zfric={0}", fricfactor); + float fricZ = m_lLinObjectVel.Z / fricfactor; + m_lLinObjectVel.Z -= fricZ; + } + } + m_wLinObjectVel = m_lLinObjectVel * rotq; + + // Gravity and Buoyancy + Vector3 grav = Vector3.Zero; + if(m_VehicleBuoyancy < 1.0f) + { + // There is some gravity, make a gravity force vector + // that is applied after object velocity. + d.Mass objMass; + d.BodyGetMass(Body, out objMass); + // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; + grav.Z = _parent_scene.gravityz * objMass.mass * (1f - m_VehicleBuoyancy); // Applied later as a force + } // else its 1.0, no gravity. + + // Hovering + if( (m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) + { + // We should hover, get the target height + d.Vector3 pos = d.BodyGetPosition(Body); + if((m_flags & VehicleFlag.HOVER_WATER_ONLY) == VehicleFlag.HOVER_WATER_ONLY) + { + m_VhoverTargetHeight = _parent_scene.GetWaterLevel() + m_VhoverHeight; + } + else if((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) == VehicleFlag.HOVER_TERRAIN_ONLY) + { + m_VhoverTargetHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; + } + else if((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) == VehicleFlag.HOVER_GLOBAL_HEIGHT) + { + m_VhoverTargetHeight = m_VhoverHeight; + } + + if((m_flags & VehicleFlag.HOVER_UP_ONLY) == VehicleFlag.HOVER_UP_ONLY) + { + // If body is aready heigher, use its height as target height + if(pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; + } + +// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped +// m_VhoverTimescale = 0f; // time to acheive height +// timestep is time since last frame,in secs + float herr0 = pos.Z - m_VhoverTargetHeight; + // Replace Vertical speed with correction figure if significant + if(Math.Abs(herr0) > 0.01f ) + { + //? d.Mass objMass; + //? d.BodyGetMass(Body, out objMass); + m_wLinObjectVel.Z = - ( (herr0 * timestep * 50.0f) / m_VhoverTimescale); + //KF: m_VhoverEfficiency is not yet implemented + } + else + { + m_wLinObjectVel.Z = 0f; + } + } + else + { // not hovering, Gravity rules + m_wLinObjectVel.Z = vel_now.Z; + } + + + // Vehicle Linear Motion done ======================================= + // Apply velocity + d.BodySetLinearVel(Body, m_wLinObjectVel.X, m_wLinObjectVel.Y, m_wLinObjectVel.Z); + // apply gravity force + d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); +//if(frcount == 0) Console.WriteLine("Grav {0}", grav); + // end MoveLinear() + + + // MoveAngular + /* + private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor + + private float m_angularMotorTimescale = 0; // motor angular Attack rate set by LSL + private float m_angularMotorDecayTimescale = 0; // motor angular Decay rate set by LSL + private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular Friction set by LSL + + private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor + private Vector3 m_angObjectVel = Vector3.Zero; // what was last applied to body + */ +//if(frcount == 0) Console.WriteLine("MoveAngular "); + + d.Vector3 angularObjectVel = d.BodyGetAngularVel(Body); + Vector3 angObjectVel = new Vector3(angularObjectVel.X, angularObjectVel.Y, angularObjectVel.Z); + angObjectVel = angObjectVel * irotq; // ============ Converts to LOCAL rotation + +//if(frcount == 0) Console.WriteLine("V0 = {0}", angObjectVel); + + // Decay Angular Motor 1. In SL this also depends on attack rate! decay ~= 23/Attack. + float atk_decayfactor = 23.0f / (m_angularMotorTimescale * timestep); + m_angularMotorDVel -= m_angularMotorDVel / atk_decayfactor; + // Decay Angular Motor 2. + if (m_angularMotorDecayTimescale < 300.0f) + { + if ( Vector3.Mag(m_angularMotorDVel) < 1.0f) + { + float decayfactor = (m_angularMotorDecayTimescale)/timestep; + Vector3 decayAmount = (m_angularMotorDVel/decayfactor); + m_angularMotorDVel -= decayAmount; + } + else + { + Vector3 decel = Vector3.Normalize(m_angularMotorDVel) * timestep / m_angularMotorDecayTimescale; + m_angularMotorDVel -= decel; + } + + if (m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) + { + m_angularMotorDVel = Vector3.Zero; + } + else + { + if (Math.Abs(m_angularMotorDVel.X) < Math.Abs(angObjectVel.X)) angObjectVel.X = m_angularMotorDVel.X; + if (Math.Abs(m_angularMotorDVel.Y) < Math.Abs(angObjectVel.Y)) angObjectVel.Y = m_angularMotorDVel.Y; + if (Math.Abs(m_angularMotorDVel.Z) < Math.Abs(angObjectVel.Z)) angObjectVel.Z = m_angularMotorDVel.Z; + } + } // end decay angular motor +//if(frcount == 0) Console.WriteLine("MotorDvel {0} Obj {1}", m_angularMotorDVel, angObjectVel); + +//if(frcount == 0) Console.WriteLine("VA = {0}", angObjectVel); + + // Vertical attractor section + Vector3 vertattr = Vector3.Zero; + + if(m_verticalAttractionTimescale < 300) + { + float VAservo = 1.0f / (m_verticalAttractionTimescale * timestep); + // make a vector pointing up + Vector3 verterr = Vector3.Zero; + verterr.Z = 1.0f; + // rotate it to Body Angle + verterr = verterr * rotq; + // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. + // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go + // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. + + if (verterr.Z < 0.0f) + { // Deflection from vertical exceeds 90-degrees. This method will ensure stable return to + // vertical, BUT for some reason a z-rotation is imparted to the object. TBI. +//Console.WriteLine("InvertFlip"); + verterr.X = 2.0f - verterr.X; + verterr.Y = 2.0f - verterr.Y; + } + verterr *= 0.5f; + // verterror is 0 (no error) to +/- 1 (max error at 180-deg tilt) + + if ((!angObjectVel.ApproxEquals(Vector3.Zero, 0.001f)) || (verterr.Z < 0.49f)) + { + // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so + // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. + vertattr.X = verterr.Y; + vertattr.Y = - verterr.X; + vertattr.Z = 0f; +//if(frcount == 0) Console.WriteLine("VAerr=" + verterr); + + // scaling appears better usingsquare-law + float damped = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency; + float bounce = 1.0f - damped; + // 0 = crit damp, 1 = bouncy + float oavz = angObjectVel.Z; // retain z velocity + // time-scaled correction, which sums, therefore is bouncy: + angObjectVel = (angObjectVel + (vertattr * VAservo * 0.0333f)) * bounce; + // damped, good @ < 90: + angObjectVel = angObjectVel + (vertattr * VAservo * 0.0667f * damped); + angObjectVel.Z = oavz; +//if(frcount == 0) Console.WriteLine("VA+"); +//Console.WriteLine("VAttr {0} OAvel {1}", vertattr, angObjectVel); + } + else + { + // else error is very small + angObjectVel.X = 0f; + angObjectVel.Y = 0f; +//if(frcount == 0) Console.WriteLine("VA0"); + } + } // else vertical attractor is off +//if(frcount == 0) Console.WriteLine("V1 = {0}", angObjectVel); + + if ( (! m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! angObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) + { // if motor or object have motion + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + + if (m_angularMotorTimescale < 300.0f) + { + Vector3 attack_error = m_angularMotorDVel - angObjectVel; + float angfactor = m_angularMotorTimescale/timestep; + Vector3 attackAmount = (attack_error/angfactor); + angObjectVel += attackAmount; +//if(frcount == 0) Console.WriteLine("Accel {0} Attk {1}",FrAaccel, attackAmount); +//if(frcount == 0) Console.WriteLine("V2+= {0}", angObjectVel); + } + + angObjectVel.X -= angObjectVel.X / (m_angularFrictionTimescale.X * 0.7f / timestep); + angObjectVel.Y -= angObjectVel.Y / (m_angularFrictionTimescale.Y * 0.7f / timestep); + angObjectVel.Z -= angObjectVel.Z / (m_angularFrictionTimescale.Z * 0.7f / timestep); + } // else no signif. motion + +//if(frcount == 0) Console.WriteLine("Dmotor {0} Obj {1}", m_angularMotorDVel, angObjectVel); + // Bank section tba + // Deflection section tba +//if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); + + m_lastAngularVelocity = angObjectVel; +//if(frcount == 0) Console.WriteLine("angularLock {0}", m_angularLock); + + if (!m_angularLock.ApproxEquals(Vector3.One, 0.003f)) + { + if (m_angularLock.X == 0) + m_lastAngularVelocity.X = 0f; + if (m_angularLock.Y == 0) + m_lastAngularVelocity.Y = 0f; + if (m_angularLock.Z == 0) + m_lastAngularVelocity.Z = 0f; + } + // Apply to the body +// Vector3 aInc = m_lastAngularVelocity - initavel; +//if(frcount == 0) Console.WriteLine("Inc {0}", aInc); + m_lastAngularVelocity = m_lastAngularVelocity * rotq; // ================ Converts to WORLD rotation + + d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); +//if(frcount == 0) Console.WriteLine("V4 = {0}", m_lastAngularVelocity); + + } // end VEHICLES #### + else + { + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 + // NON-'VEHICLES' are dealt with here + // m_angularlock = <1,1,1> means no lock. a 0 on axis means locked. + +// NB this may be wrong - may lock global axis! Should be LOCAL axis! + /// Dynamics Angular Lock ======================================================================== + if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.One, 0.003f)) + { + d.Vector3 avel2 = d.BodyGetAngularVel(Body); + if (m_angularlock.X == 0) + avel2.X = 0; + if (m_angularlock.Y == 0) + avel2.Y = 0; + if (m_angularlock.Z == 0) + avel2.Z = 0; + d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); + } - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - _zeroFlag = true; - } - } - } + /// Dynamics Buoyancy =============================================================================== + //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle. + // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up + // NB Prims in ODE are no subject to global gravity + float m_mass = CalculateMass(); + fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass - public override bool FloatOnWater - { - set { - m_taintCollidesWater = value; - _parent_scene.AddPhysicsActorTaint(this); - } - } + if (m_usePID) + { +//if(frcount == 0) Console.WriteLine("PID " + m_primName); + // KF - this is for object MoveToTarget. + + //if (!d.BodyIsEnabled(Body)) + //d.BodySetForce(Body, 0f, 0f, 0f); - public override void SetMomentum(Vector3 momentum) - { - } + // no lock; for now it's only called from within Simulate() + + // If the PID Controller isn't active then we set our force + // calculating base velocity to the current position - public override Vector3 PIDTarget - { - set - { - if (value.IsFinite()) - { - m_PIDTarget = value; - } - else - m_log.Warn("[PHYSICS]: Got NaN PIDTarget from Scene on Object"); - } - } - public override bool PIDActive { set { m_usePID = value; } } - public override float PIDTau { set { m_PIDTau = value; } } - - // For RotLookAt - public override Quaternion APIDTarget { set { m_APIDTarget = value; } } - public override bool APIDActive { set { m_useAPID = value; } } - public override float APIDStrength { set { m_APIDStrength = value; } } - public override float APIDDamping { set { m_APIDDamping = value; } } + if ((m_PIDTau < 1) && (m_PIDTau != 0)) + { + //PID_G = PID_G / m_PIDTau; + m_PIDTau = 1; + } + + if ((PID_G - m_PIDTau) <= 0) + { + PID_G = m_PIDTau + 1; + } + //PidStatus = true; - public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } - public override bool PIDHoverActive { set { m_useHoverPID = value; } } - public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } - public override float PIDHoverTau { set { m_PIDHoverTau = value; } } + // PhysicsVector vec = new PhysicsVector(); +// d.Vector3 vel = d.BodyGetLinearVel(Body); - private void createAMotor(Vector3 axis) // ##* - { -Console.WriteLine(" createAMotor called! ----------------------------"); - if (Body == IntPtr.Zero) - return; + d.Vector3 pos = d.BodyGetPosition(Body); + _target_velocity = + new Vector3( + (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep), + (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep), + (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) + ); - if (Amotor != IntPtr.Zero) - { - d.JointDestroy(Amotor); - Amotor = IntPtr.Zero; - } + // if velocity is zero, use position control; otherwise, velocity control - float axisnum = 3; + if (_target_velocity.ApproxEquals(Vector3.Zero,0.1f)) + { + // keep track of where we stopped. No more slippin' & slidin' + + // We only want to deactivate the PID Controller if we think we want to have our surrogate + // react to the physics scene by moving it's position. + // Avatar to Avatar collisions + // Prim to avatar collisions - axisnum = (axisnum - (axis.X + axis.Y + axis.Z)); + //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); + //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2); + //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; + d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); + d.BodySetLinearVel(Body, 0, 0, 0); + d.BodyAddForce(Body, 0, 0, fz); + return; + } + else + { + _zeroFlag = false; - // PhysicsVector totalSize = new PhysicsVector(_size.X, _size.Y, _size.Z); + // We're flying and colliding with something + fx = ((_target_velocity.X) - vel.X) * (PID_D); + fy = ((_target_velocity.Y) - vel.Y) * (PID_D); + + // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; - - // Inverse Inertia Matrix, set the X, Y, and/r Z inertia to 0 then invert it again. - d.Mass objMass; - d.MassSetZero(out objMass); - DMassCopy(ref pMass, ref objMass); + fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); + } + } // end if (m_usePID) + + /// Dynamics Hover =================================================================================== + // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller + if (m_useHoverPID && !m_usePID) + { +//Console.WriteLine("Hover " + m_primName); + + // If we're using the PID controller, then we have no gravity + fz = (-1 * _parent_scene.gravityz) * m_mass; - //m_log.DebugFormat("1-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); + // no lock; for now it's only called from within Simulate() - Matrix4 dMassMat = FromDMass(objMass); + // If the PID Controller isn't active then we set our force + // calculating base velocity to the current position - Matrix4 mathmat = Inverse(dMassMat); + if ((m_PIDTau < 1)) + { + PID_G = PID_G / m_PIDTau; + } - /* - //m_log.DebugFormat("2-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", mathmat[0, 0], mathmat[0, 1], mathmat[0, 2], mathmat[1, 0], mathmat[1, 1], mathmat[1, 2], mathmat[2, 0], mathmat[2, 1], mathmat[2, 2]); + if ((PID_G - m_PIDTau) <= 0) + { + PID_G = m_PIDTau + 1; + } + - mathmat = Inverse(mathmat); - - - objMass = FromMatrix4(mathmat, ref objMass); - //m_log.DebugFormat("3-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); - - mathmat = Inverse(mathmat); - */ - if (axis.X == 0) - { - mathmat.M33 = 50.0000001f; - //objMass.I.M22 = 0; - } - if (axis.Y == 0) - { - mathmat.M22 = 50.0000001f; - //objMass.I.M11 = 0; - } - if (axis.Z == 0) - { - mathmat.M11 = 50.0000001f; - //objMass.I.M00 = 0; - } - - - - mathmat = Inverse(mathmat); - objMass = FromMatrix4(mathmat, ref objMass); - //m_log.DebugFormat("4-{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, ", objMass.I.M00, objMass.I.M01, objMass.I.M02, objMass.I.M10, objMass.I.M11, objMass.I.M12, objMass.I.M20, objMass.I.M21, objMass.I.M22); - - //return; - if (d.MassCheck(ref objMass)) - { - d.BodySetMass(Body, ref objMass); - } - else - { - //m_log.Debug("[PHYSICS]: Mass invalid, ignoring"); - } - - if (axisnum <= 0) - return; - // int dAMotorEuler = 1; - - Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); - d.JointAttach(Amotor, Body, IntPtr.Zero); - d.JointSetAMotorMode(Amotor, 0); - - d.JointSetAMotorNumAxes(Amotor,(int)axisnum); - int i = 0; - - if (axis.X == 0) - { - d.JointSetAMotorAxis(Amotor, i, 0, 1, 0, 0); - i++; - } - - if (axis.Y == 0) - { - d.JointSetAMotorAxis(Amotor, i, 0, 0, 1, 0); - i++; - } - - if (axis.Z == 0) - { - d.JointSetAMotorAxis(Amotor, i, 0, 0, 0, 1); - i++; - } - - for (int j = 0; j < (int)axisnum; j++) - { - //d.JointSetAMotorAngle(Amotor, j, 0); - } - - //d.JointSetAMotorAngle(Amotor, 1, 0); - //d.JointSetAMotorAngle(Amotor, 2, 0); - - // These lowstops and high stops are effectively (no wiggle room) - d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0f); - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f); - d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); - d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0f); - //d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 9000f); - d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f); - d.JointSetAMotorParam(Amotor, (int)dParam.FMax, Mass * 50f);// - - } - - public Matrix4 FromDMass(d.Mass pMass) - { - Matrix4 obj; - obj.M11 = pMass.I.M00; - obj.M12 = pMass.I.M01; - obj.M13 = pMass.I.M02; - obj.M14 = 0; - obj.M21 = pMass.I.M10; - obj.M22 = pMass.I.M11; - obj.M23 = pMass.I.M12; - obj.M24 = 0; - obj.M31 = pMass.I.M20; - obj.M32 = pMass.I.M21; - obj.M33 = pMass.I.M22; - obj.M34 = 0; - obj.M41 = 0; - obj.M42 = 0; - obj.M43 = 0; - obj.M44 = 1; - return obj; - } - - public d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj) - { - obj.I.M00 = pMat[0, 0]; - obj.I.M01 = pMat[0, 1]; - obj.I.M02 = pMat[0, 2]; - obj.I.M10 = pMat[1, 0]; - obj.I.M11 = pMat[1, 1]; - obj.I.M12 = pMat[1, 2]; - obj.I.M20 = pMat[2, 0]; - obj.I.M21 = pMat[2, 1]; - obj.I.M22 = pMat[2, 2]; - return obj; - } - - public override void SubscribeEvents(int ms) - { - m_eventsubscription = ms; - _parent_scene.addCollisionEventReporting(this); - } - - public override void UnSubscribeEvents() - { - _parent_scene.remCollisionEventReporting(this); - m_eventsubscription = 0; - } - - public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) - { - if (CollisionEventsThisFrame == null) - CollisionEventsThisFrame = new CollisionEventUpdate(); - CollisionEventsThisFrame.addCollider(CollidedWith, contact); - } - - public void SendCollisions() - { - if (CollisionEventsThisFrame == null) - return; - - base.SendCollisionUpdate(CollisionEventsThisFrame); - - if (CollisionEventsThisFrame.m_objCollisionList.Count == 0) - CollisionEventsThisFrame = null; - else - CollisionEventsThisFrame = new CollisionEventUpdate(); - } - - public override bool SubscribedEvents() - { - if (m_eventsubscription > 0) - return true; - return false; - } + // Where are we, and where are we headed? + d.Vector3 pos = d.BodyGetPosition(Body); +// d.Vector3 vel = d.BodyGetLinearVel(Body); - public static Matrix4 Inverse(Matrix4 pMat) - { - if (determinant3x3(pMat) == 0) - { - return Matrix4.Identity; // should probably throw an error. singluar matrix inverse not possible - } + // Non-Vehicles have a limited set of Hover options. + // determine what our target height really is based on HoverType + switch (m_PIDHoverType) + { + case PIDHoverType.Ground: + m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); + m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; + break; + case PIDHoverType.GroundAndWater: + m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y); + m_waterHeight = _parent_scene.GetWaterLevel(); + if (m_groundHeight > m_waterHeight) + { + m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight; + } + else + { + m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight; + } + break; + } // end switch (m_PIDHoverType) - return (Adjoint(pMat) / determinant3x3(pMat)); - } - public static Matrix4 Adjoint(Matrix4 pMat) - { - Matrix4 adjointMatrix = new Matrix4(); - for (int i=0; i<4; i++) - { - for (int j=0; j<4; j++) - { - Matrix4SetValue(ref adjointMatrix, i, j, (float)(Math.Pow(-1, i + j) * (determinant3x3(Minor(pMat, i, j))))); - } - } + _target_velocity = + new Vector3(0.0f, 0.0f, + (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep) + ); - adjointMatrix = Transpose(adjointMatrix); - return adjointMatrix; - } + // if velocity is zero, use position control; otherwise, velocity control - public static Matrix4 Minor(Matrix4 matrix, int iRow, int iCol) - { - Matrix4 minor = new Matrix4(); - int m = 0, n = 0; - for (int i = 0; i < 4; i++) - { - if (i == iRow) - continue; - n = 0; - for (int j = 0; j < 4; j++) - { - if (j == iCol) - continue; - Matrix4SetValue(ref minor, m,n, matrix[i, j]); - n++; - } - m++; - } - return minor; - } + if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) + { + // keep track of where we stopped. No more slippin' & slidin' + + // We only want to deactivate the PID Controller if we think we want to have our surrogate + // react to the physics scene by moving it's position. + // Avatar to Avatar collisions + // Prim to avatar collisions - public static Matrix4 Transpose(Matrix4 pMat) - { - Matrix4 transposeMatrix = new Matrix4(); - for (int i = 0; i < 4; i++) - for (int j = 0; j < 4; j++) - Matrix4SetValue(ref transposeMatrix, i, j, pMat[j, i]); - return transposeMatrix; - } + d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); + d.BodySetLinearVel(Body, vel.X, vel.Y, 0); + d.BodyAddForce(Body, 0, 0, fz); + //KF this prevents furthur motions return; + } + else + { + _zeroFlag = false; - public static void Matrix4SetValue(ref Matrix4 pMat, int r, int c, float val) - { - switch (r) - { - case 0: - switch (c) - { - case 0: - pMat.M11 = val; - break; - case 1: - pMat.M12 = val; - break; - case 2: - pMat.M13 = val; - break; - case 3: - pMat.M14 = val; - break; - } + // We're flying and colliding with something + fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); + } + } // end m_useHoverPID && !m_usePID + + /// Dynamics RotLookAt ================================================================================= + if (m_useAPID) + { + // RotLookAt, apparently overrides all other rotation sources. Inputs: + // Quaternion m_APIDTarget + // float m_APIDStrength // From SL experiments, this is the time to get there + // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly + // Also in SL the mass of the object has no effect on time to get there. + // Factors: +//if(frcount == 0) Console.WriteLine("APID "); + // get present body rotation + float limit = 1.0f; + float scaler = 50f; // adjusts damping time + float RLAservo = 0f; + + d.Quaternion rot = d.BodyGetQuaternion(Body); + Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); + Quaternion rot_diff = Quaternion.Inverse(rotq) * m_APIDTarget; + float diff_angle; + Vector3 diff_axis; + rot_diff.GetAxisAngle(out diff_axis, out diff_angle); + diff_axis.Normalize(); + if(diff_angle > 0.01f) // diff_angle is always +ve + { +// PhysicsVector rotforce = new PhysicsVector(diff_axis.X, diff_axis.Y, diff_axis.Z); + Vector3 rotforce = new Vector3(diff_axis.X, diff_axis.Y, diff_axis.Z); + rotforce = rotforce * rotq; + if(diff_angle > limit) diff_angle = limit; // cap the rotate rate +// RLAservo = timestep / m_APIDStrength * m_mass * scaler; + // rotforce = rotforce * RLAservo * diff_angle ; + // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); + RLAservo = timestep / m_APIDStrength * scaler; + rotforce = rotforce * RLAservo * diff_angle ; + + if (m_angularlock.X == 0) + rotforce.X = 0; + if (m_angularlock.Y == 0) + rotforce.Y = 0; + if (m_angularlock.Z == 0) + rotforce.Z = 0; + + d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); +//Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); + } +//if(frcount == 0) Console.WriteLine("mass= " + m_mass + " servo= " + RLAservo + " angle= " + diff_angle); + } // end m_useAPID + + /// Dynamics Apply Forces =================================================================================== + fx *= m_mass; + fy *= m_mass; + //fz *= m_mass; - break; - case 1: - switch (c) - { - case 0: - pMat.M21 = val; - break; - case 1: - pMat.M22 = val; - break; - case 2: - pMat.M23 = val; - break; - case 3: - pMat.M24 = val; - break; - } + fx += m_force.X; + fy += m_force.Y; + fz += m_force.Z; - break; - case 2: - switch (c) - { - case 0: - pMat.M31 = val; - break; - case 1: - pMat.M32 = val; - break; - case 2: - pMat.M33 = val; - break; - case 3: - pMat.M34 = val; - break; - } + //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString()); + if (fx != 0 || fy != 0 || fz != 0) + { + //m_taintdisable = true; + //base.RaiseOutOfBounds(Position); + //d.BodySetLinearVel(Body, fx, fy, 0f); + if (!d.BodyIsEnabled(Body)) + { + // A physical body at rest on a surface will auto-disable after a while, + // this appears to re-enable it incase the surface it is upon vanishes, + // and the body should fall again. + d.BodySetLinearVel(Body, 0f, 0f, 0f); + d.BodySetForce(Body, 0, 0, 0); + enableBodySoft(); + } - break; - case 3: - switch (c) - { - case 0: - pMat.M41 = val; - break; - case 1: - pMat.M42 = val; - break; - case 2: - pMat.M43 = val; - break; - case 3: - pMat.M44 = val; - break; - } + // 35x10 = 350n times the mass per second applied maximum. + float nmax = 35f * m_mass; + float nmin = -35f * m_mass; - break; + + if (fx > nmax) + fx = nmax; + if (fx < nmin) + fx = nmin; + if (fy > nmax) + fy = nmax; + if (fy < nmin) + fy = nmin; + d.BodyAddForce(Body, fx, fy, fz); +//Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); + } + } } - } - private static float determinant3x3(Matrix4 pMat) - { - float det = 0; - float diag1 = pMat[0, 0]*pMat[1, 1]*pMat[2, 2]; - float diag2 = pMat[0, 1]*pMat[2, 1]*pMat[2, 0]; - float diag3 = pMat[0, 2]*pMat[1, 0]*pMat[2, 1]; - float diag4 = pMat[2, 0]*pMat[1, 1]*pMat[0, 2]; - float diag5 = pMat[2, 1]*pMat[1, 2]*pMat[0, 0]; - float diag6 = pMat[2, 2]*pMat[1, 0]*pMat[0, 1]; - - det = diag1 + diag2 + diag3 - (diag4 + diag5 + diag6); - return det; - - } - - private static void DMassCopy(ref d.Mass src, ref d.Mass dst) - { - dst.c.W = src.c.W; - dst.c.X = src.c.X; - dst.c.Y = src.c.Y; - dst.c.Z = src.c.Z; - dst.mass = src.mass; - dst.I.M00 = src.I.M00; - dst.I.M01 = src.I.M01; - dst.I.M02 = src.I.M02; - dst.I.M10 = src.I.M10; - dst.I.M11 = src.I.M11; - dst.I.M12 = src.I.M12; - dst.I.M20 = src.I.M20; - dst.I.M21 = src.I.M21; - dst.I.M22 = src.I.M22; - } + else + { // is not physical, or is not a body or is selected + // from old UpdatePositionAndVelocity, ... Not a body.. so Make sure the client isn't interpolating + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; - public override void SetMaterial(int pMaterial) - { - m_material = pMaterial; - } + _acceleration.X = 0; + _acceleration.Y = 0; + _acceleration.Z = 0; - } + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + _zeroFlag = true; + return; + } + } // end Move() + } // end class } -- cgit v1.1 From 1379ae4310b94afd1a7a1d9964db26146ca5c7b2 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Fri, 12 Mar 2010 16:13:52 -0500 Subject: Fix Rotation Lock. NOTE: This version had poor border crossing control --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 38 ++++++++++++------------- OpenSim/Region/Physics/PhysXPlugin/PhysXPrim.cs | 4 --- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index e51ef5b..367927d 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -64,7 +64,7 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 m_taintVelocity; private Vector3 m_taintTorque; private Quaternion m_taintrot; - private Vector3 m_angularlock = Vector3.One; // Current setting + private Vector3 m_angularEnable = Vector3.One; // Current setting private Vector3 m_taintAngularLock = Vector3.One; // Request from LSL @@ -216,8 +216,6 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 m_angularMotorDVel = Vector3.Zero; // decayed angular motor // private Vector3 m_angObjectVel = Vector3.Zero; // current body angular velocity private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body - - private Vector3 m_angularLock = Vector3.One; //Deflection properties // private float m_angularDeflectionEfficiency = 0; @@ -1401,8 +1399,8 @@ namespace OpenSim.Region.Physics.OdePlugin changefloatonwater(timestep); // ##* - if (!m_angularlock.ApproxEquals(m_taintAngularLock,0f)) -//Console.WriteLine("ALchange req {0} is {1}", m_taintAngularLock, m_angularlock); + if (!m_angularEnable.ApproxEquals(m_taintAngularLock,0f)) +Console.WriteLine("ALchange req {0} is {1}", m_taintAngularLock, m_angularEnable); changeAngularLock(timestep); } @@ -1422,8 +1420,8 @@ namespace OpenSim.Region.Physics.OdePlugin //If we have a parent then we're not authorative here if (_parent == null) { -//Console.WriteLine("Alock changed to {0}", m_taintAngularLock); - m_angularlock = m_taintAngularLock; +Console.WriteLine("Alock changed to {0}", m_taintAngularLock); + m_angularEnable = m_taintAngularLock; } } @@ -3703,15 +3701,15 @@ Console.WriteLine(" JointCreateFixed"); //if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); m_lastAngularVelocity = angObjectVel; -//if(frcount == 0) Console.WriteLine("angularLock {0}", m_angularLock); +if(frcount == 0) Console.WriteLine("angularEnable {0}", m_angularEnable); - if (!m_angularLock.ApproxEquals(Vector3.One, 0.003f)) + if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) { - if (m_angularLock.X == 0) + if (m_angularEnable.X == 0) m_lastAngularVelocity.X = 0f; - if (m_angularLock.Y == 0) + if (m_angularEnable.Y == 0) m_lastAngularVelocity.Y = 0f; - if (m_angularLock.Z == 0) + if (m_angularEnable.Z == 0) m_lastAngularVelocity.Z = 0f; } // Apply to the body @@ -3727,18 +3725,18 @@ Console.WriteLine(" JointCreateFixed"); { if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 // NON-'VEHICLES' are dealt with here - // m_angularlock = <1,1,1> means no lock. a 0 on axis means locked. + // m_angularEnable = <1,1,1> means no lock. a 0 on axis means locked. // NB this may be wrong - may lock global axis! Should be LOCAL axis! /// Dynamics Angular Lock ======================================================================== - if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.One, 0.003f)) + if (d.BodyIsEnabled(Body) && !m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) { d.Vector3 avel2 = d.BodyGetAngularVel(Body); - if (m_angularlock.X == 0) + if (m_angularEnable.X == 0) avel2.X = 0; - if (m_angularlock.Y == 0) + if (m_angularEnable.Y == 0) avel2.Y = 0; - if (m_angularlock.Z == 0) + if (m_angularEnable.Z == 0) avel2.Z = 0; d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); } @@ -3938,11 +3936,11 @@ Console.WriteLine(" JointCreateFixed"); RLAservo = timestep / m_APIDStrength * scaler; rotforce = rotforce * RLAservo * diff_angle ; - if (m_angularlock.X == 0) + if (m_angularEnable.X == 0) rotforce.X = 0; - if (m_angularlock.Y == 0) + if (m_angularEnable.Y == 0) rotforce.Y = 0; - if (m_angularlock.Z == 0) + if (m_angularEnable.Z == 0) rotforce.Z = 0; d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); diff --git a/OpenSim/Region/Physics/PhysXPlugin/PhysXPrim.cs b/OpenSim/Region/Physics/PhysXPlugin/PhysXPrim.cs index d1b5b7e..c0e24fd 100644 --- a/OpenSim/Region/Physics/PhysXPlugin/PhysXPrim.cs +++ b/OpenSim/Region/Physics/PhysXPlugin/PhysXPrim.cs @@ -279,10 +279,6 @@ namespace OpenSim.Region.Physics.PhysXPlugin public override void VehicleFlags(int param, bool remove) { } - public override void VehicleFlagsSet(int param) { } - - public override void VehicleFlagsRemove(int param) { } - public override void SetVolumeDetect(int param) { -- cgit v1.1 From 80e4068b3e85625234270cd7f3735cfd1b4e83dc Mon Sep 17 00:00:00 2001 From: CasperW Date: Sat, 13 Mar 2010 15:13:19 +0100 Subject: Fix the delay in llGiveInventory so that it only takes effect when giving inventory to an avatar (this now replicates SL behaviour) --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 180fba9..0117fa0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4014,14 +4014,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api bucket); if (m_TransferModule != null) - m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); + m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); + + //This delay should only occur when giving inventory to avatars. + ScriptSleep(3000); } else { // destination is an object World.MoveTaskInventoryItem(destId, m_host, objId); } - ScriptSleep(3000); + } [DebuggerNonUserCode] -- cgit v1.1 From 819806261026cccd68dee649f11938ae5bf10029 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Sun, 14 Mar 2010 16:22:13 -0400 Subject: RotLookAt repaired; debug msg cleanup. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 4 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 35 +- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 552 ++++++--------------- .../Shared/Api/Implementation/LSL_Api.cs | 4 +- 4 files changed, 151 insertions(+), 444 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f35a7c5..5443c28 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1955,7 +1955,7 @@ namespace OpenSim.Region.Framework.Scenes else { if (rootpart.PhysActor != null) - { + { // APID must be implemented in your physics system for this to function. rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); rootpart.PhysActor.APIDStrength = strength; rootpart.PhysActor.APIDDamping = damping; @@ -1971,7 +1971,7 @@ namespace OpenSim.Region.Framework.Scenes if (rootpart != null) { if (rootpart.PhysActor != null) - { + { // APID must be implemented in your physics system for this to function. rootpart.PhysActor.APIDActive = false; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 31ea502..548a64f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2705,38 +2705,7 @@ namespace OpenSim.Region.Framework.Scenes public void RotLookAt(Quaternion target, float strength, float damping) { - rotLookAt(target, strength, damping); - } - - public void rotLookAt(Quaternion target, float strength, float damping) - { - if (IsAttachment) - { - /* - ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); - if (avatar != null) - { - Rotate the Av? - } */ - } - else - { - APIDDamp = damping; - APIDStrength = strength; - APIDTarget = target; - } - } - - public void startLookAt(Quaternion rot, float damp, float strength) - { - APIDDamp = damp; - APIDStrength = strength; - APIDTarget = rot; - } - - public void stopLookAt() - { - APIDTarget = Quaternion.Identity; + m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup. } /// @@ -3460,7 +3429,7 @@ namespace OpenSim.Region.Framework.Scenes public void StopLookAt() { - m_parentGroup.stopLookAt(); + m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup. m_parentGroup.ScheduleGroupForTerseUpdate(); } diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 367927d..5e6696e 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -652,7 +652,7 @@ namespace OpenSim.Region.Physics.OdePlugin return true; } - public override Vector3 Acceleration + public override Vector3 Acceleration // client updates read data via here { get { return _acceleration; } } @@ -696,14 +696,6 @@ namespace OpenSim.Region.Physics.OdePlugin { get { -/* Vector3 pv = Vector3.Zero; - if (_zeroFlag) - return pv; - m_lastUpdateSent = false; - - if (m_rotationalVelocity.ApproxEquals(pv, 0.2f)) - return pv; -*/ return m_rotationalVelocity; } set @@ -1398,9 +1390,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_taintCollidesWater != m_collidesWater) changefloatonwater(timestep); - // ##* if (!m_angularEnable.ApproxEquals(m_taintAngularLock,0f)) -Console.WriteLine("ALchange req {0} is {1}", m_taintAngularLock, m_angularEnable); changeAngularLock(timestep); } @@ -1411,17 +1401,11 @@ Console.WriteLine("ALchange req {0} is {1}", m_taintAngularLock, m_angularEna } - private void changeAngularLock(float timestep) // ##* + private void changeAngularLock(float timestep) { - // do we have a Physical object? -// if (Body != IntPtr.Zero) -// { - //Check that we have a Parent - //If we have a parent then we're not authorative here - if (_parent == null) - { -Console.WriteLine("Alock changed to {0}", m_taintAngularLock); - m_angularEnable = m_taintAngularLock; + if (_parent == null) + { + m_angularEnable = m_taintAngularLock; } } @@ -1435,7 +1419,6 @@ Console.WriteLine("Alock changed to {0}", m_taintAngularLock); { OdePrim obj = (OdePrim)m_taintparent; //obj.disableBody(); -//Console.WriteLine("changelink calls ParentPrim"); obj.ParentPrim(this); /* @@ -1453,8 +1436,6 @@ Console.WriteLine("Alock changed to {0}", m_taintAngularLock); // destroy link else if (_parent != null && m_taintparent == null) { -//Console.WriteLine(" changelink B"); - if (_parent is OdePrim) { OdePrim obj = (OdePrim)_parent; @@ -1480,7 +1461,6 @@ Console.WriteLine("Alock changed to {0}", m_taintAngularLock); // prim is the child public void ParentPrim(OdePrim prim) { -//Console.WriteLine("ParentPrim " + m_primName); if (this.m_localID != prim.m_localID) { if (Body == IntPtr.Zero) @@ -1494,7 +1474,6 @@ Console.WriteLine("Alock changed to {0}", m_taintAngularLock); { if (!childrenPrim.Contains(prim)) { -//Console.WriteLine("childrenPrim.Add " + prim); childrenPrim.Add(prim); foreach (OdePrim prm in childrenPrim) @@ -1640,7 +1619,6 @@ Console.WriteLine("Alock changed to {0}", m_taintAngularLock); { foreach (OdePrim prm in childrenPrim) { -//Console.WriteLine("ChildSetGeom calls ParentPrim"); ParentPrim(prm); } } @@ -1667,7 +1645,6 @@ Console.WriteLine("Alock changed to {0}", m_taintAngularLock); lock (childrenPrim) { - //Console.WriteLine("childrenPrim.Remove " + odePrim); childrenPrim.Remove(odePrim); } @@ -1680,7 +1657,6 @@ Console.WriteLine("Alock changed to {0}", m_taintAngularLock); { foreach (OdePrim prm in childrenPrim) { -//Console.WriteLine("ChildDelink calls ParentPrim"); ParentPrim(prm); } } @@ -2417,219 +2393,9 @@ Console.WriteLine(" JointCreateFixed"); public void UpdatePositionAndVelocity() { - return; // moved to the MOVE() method + return; // moved to the Move() method } - // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! -/* if (_parent == null) - { - Vector3 pv = Vector3.Zero; - bool lastZeroFlag = _zeroFlag; - if (Body != (IntPtr)0) // FIXME -> or if it is a joint - { - d.Vector3 vec = d.BodyGetPosition(Body); - d.Quaternion ori = d.BodyGetQuaternion(Body); - d.Vector3 vel = d.BodyGetLinearVel(Body); - d.Vector3 rotvel = d.BodyGetAngularVel(Body); - d.Vector3 torque = d.BodyGetTorque(Body); - _torque = new Vector3(torque.X, torque.Y, torque.Z); - Vector3 l_position = Vector3.Zero; - Quaternion l_orientation = Quaternion.Identity; - - // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) - //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - - m_lastposition = _position; - m_lastorientation = _orientation; - - l_position.X = vec.X; - l_position.Y = vec.Y; - l_position.Z = vec.Z; - l_orientation.X = ori.X; - l_orientation.Y = ori.Y; - l_orientation.Z = ori.Z; - l_orientation.W = ori.W; - -// if(l_position.Y != m_lastposition.Y){ -// Console.WriteLine("UP&V {0} {1}", m_primName, l_position); -// } - - if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || l_position.X < 0f || l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || l_position.Y < 0f) - { - //base.RaiseOutOfBounds(l_position); - - if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds) - { - _position = l_position; - //_parent_scene.remActivePrim(this); - if (_parent == null) - base.RequestPhysicsterseUpdate(); - return; - } - else - { - if (_parent == null) - base.RaiseOutOfBounds(l_position); - return; - } - } - - if (l_position.Z < 0) - { - // This is so prim that get lost underground don't fall forever and suck up - // - // Sim resources and memory. - // Disables the prim's movement physics.... - // It's a hack and will generate a console message if it fails. - - //IsPhysical = false; - if (_parent == null) - base.RaiseOutOfBounds(_position); - - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; - - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - - if (_parent == null) - base.RequestPhysicsterseUpdate(); - - m_throttleUpdates = false; - throttleCounter = 0; - _zeroFlag = true; - //outofBounds = true; - } - - //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)); -//Console.WriteLine("Adiff " + m_primName + " = " + Adiff); - if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) - && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) - && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) -// && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01)) - && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large - { - _zeroFlag = true; -//Console.WriteLine("ZFT 2"); - m_throttleUpdates = false; - } - else - { - //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString()); - _zeroFlag = false; - m_lastUpdateSent = false; - //m_throttleUpdates = false; - } - - if (_zeroFlag) - { - _velocity.X = 0.0f; - _velocity.Y = 0.0f; - _velocity.Z = 0.0f; - - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; - - //_orientation.w = 0f; - //_orientation.X = 0f; - //_orientation.Y = 0f; - //_orientation.Z = 0f; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - if (!m_lastUpdateSent) - { - m_throttleUpdates = false; - throttleCounter = 0; - m_rotationalVelocity = pv; - - if (_parent == null) - { - base.RequestPhysicsterseUpdate(); - } - - m_lastUpdateSent = true; - } - } - else - { - if (lastZeroFlag != _zeroFlag) - { - if (_parent == null) - { - base.RequestPhysicsterseUpdate(); - } - } - - m_lastVelocity = _velocity; - - _position = l_position; - - _velocity.X = vel.X; - _velocity.Y = vel.Y; - _velocity.Z = vel.Z; - - _acceleration = ((_velocity - m_lastVelocity) / 0.1f); - _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, _velocity.Y - m_lastVelocity.Y / 0.1f, _velocity.Z - m_lastVelocity.Z / 0.1f); - //m_log.Info("[PHYSICS]: V1: " + _velocity + " V2: " + m_lastVelocity + " Acceleration: " + _acceleration.ToString()); - -// if (_velocity.ApproxEquals(pv, 0.5f)) ???? Disregard rotational vel if lin vel is < 0.5 ????? -// { -// m_rotationalVelocity = pv;/ - -// } -// else -// { - m_rotationalVelocity = new Vector3(rotvel.X, rotvel.Y, rotvel.Z); -// } - - //m_log.Debug("ODE: " + m_rotationalVelocity.ToString()); - _orientation.X = ori.X; - _orientation.Y = ori.Y; - _orientation.Z = ori.Z; - _orientation.W = ori.W; - m_lastUpdateSent = false; - if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) - { - if (_parent == null) - { - base.RequestPhysicsterseUpdate(); - } - } - else - { - throttleCounter++; - } - } - m_lastposition = l_position; - } - else - { - // Not a body.. so Make sure the client isn't interpolating - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; - - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; - - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - _zeroFlag = true; - } - } - } -*/ +/* No one uses this? public Matrix4 FromDMass(d.Mass pMass) { Matrix4 obj; @@ -2651,7 +2417,7 @@ Console.WriteLine(" JointCreateFixed"); obj.M44 = 1; return obj; } - +*/ public d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj) { obj.I.M00 = pMat[0, 0]; @@ -2878,11 +2644,6 @@ Console.WriteLine(" JointCreateFixed"); m_material = pMaterial; } - - - - - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) { switch (pParam) @@ -3242,193 +3003,173 @@ Console.WriteLine(" JointCreateFixed"); { // Old public void UpdatePositionAndVelocity(), more accuratley calculated here - // Vector3 pv = Vector3.Zero; // what was this for? - bool lastZeroFlag = _zeroFlag; // was it stopped - // if (Body != (IntPtr)0) // FIXME -> or if it is a joint - // { - d.Vector3 vec = d.BodyGetPosition(Body); - d.Quaternion ori = d.BodyGetQuaternion(Body); - d.Vector3 vel = d.BodyGetLinearVel(Body); + bool lastZeroFlag = _zeroFlag; // was it stopped + d.Vector3 vec = d.BodyGetPosition(Body); + d.Quaternion ori = d.BodyGetQuaternion(Body); + d.Vector3 vel = d.BodyGetLinearVel(Body); // d.Vector3 rotvel = d.BodyGetAngularVel(Body); - d.Vector3 torque = d.BodyGetTorque(Body); - _torque = new Vector3(torque.X, torque.Y, torque.Z); - Vector3 l_position = Vector3.Zero; - Quaternion l_orientation = Quaternion.Identity; - - // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) - //if (vec.X < 0.0f) { vec.X = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - //if (vec.Y < 0.0f) { vec.Y = 0.0f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - //if (vec.X > 255.95f) { vec.X = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - //if (vec.Y > 255.95f) { vec.Y = 255.95f; if (Body != (IntPtr)0) d.BodySetAngularVel(Body, 0, 0, 0); } - - m_lastposition = _position; - m_lastorientation = _orientation; + d.Vector3 torque = d.BodyGetTorque(Body); + _torque = new Vector3(torque.X, torque.Y, torque.Z); + Vector3 l_position = Vector3.Zero; + Quaternion l_orientation = Quaternion.Identity; + + m_lastposition = _position; + m_lastorientation = _orientation; - l_position.X = vec.X; - l_position.Y = vec.Y; - l_position.Z = vec.Z; - l_orientation.X = ori.X; - l_orientation.Y = ori.Y; - l_orientation.Z = ori.Z; - l_orientation.W = ori.W; + l_position.X = vec.X; + l_position.Y = vec.Y; + l_position.Z = vec.Z; + l_orientation.X = ori.X; + l_orientation.Y = ori.Y; + l_orientation.Z = ori.Z; + l_orientation.W = ori.W; //Console.WriteLine("Move {0} at {1}", m_primName, l_position); + // Check if outside region horizontally + if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || + l_position.X < 0f || + l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || + l_position.Y < 0f) + { + if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds) + { // keep trying to cross? + _position = l_position; + //_parent_scene.remActivePrim(this); + if (_parent == null) base.RequestPhysicsterseUpdate(); + return; // Dont process any other motion? + } + else + { // Too many tries + if (_parent == null) base.RaiseOutOfBounds(l_position); + return; // Dont process any other motion? + } + } // end outside region horizontally - if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || - l_position.X < 0f || - l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || - l_position.Y < 0f) - { - //base.RaiseOutOfBounds(l_position); + if (l_position.Z < 0) + { + // This is so prim that get lost underground don't fall forever and suck up + // + // Sim resources and memory. + // Disables the prim's movement physics.... + // It's a hack and will generate a console message if it fails. - if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds) - { - _position = l_position; - //_parent_scene.remActivePrim(this); - if (_parent == null) - base.RequestPhysicsterseUpdate(); - return; - } - else - { - if (_parent == null) - base.RaiseOutOfBounds(l_position); - return; - } - } + //IsPhysical = false; + if (_parent == null) base.RaiseOutOfBounds(_position); + + _acceleration.X = 0; // This stuff may stop client display but it has no + _acceleration.Y = 0; // effect on the object in phys engine! + _acceleration.Z = 0; - if (l_position.Z < 0) - { - // This is so prim that get lost underground don't fall forever and suck up - // - // Sim resources and memory. - // Disables the prim's movement physics.... - // It's a hack and will generate a console message if it fails. + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; - //IsPhysical = false; - if (_parent == null) - base.RaiseOutOfBounds(_position); + if (_parent == null) base.RequestPhysicsterseUpdate(); - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; + m_throttleUpdates = false; + throttleCounter = 0; + _zeroFlag = true; + //outofBounds = true; + } // end neg Z check - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; + // Is it moving? + if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) + && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) + && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) + && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large + { + _zeroFlag = true; +//Console.WriteLine("ZFT 2"); + m_throttleUpdates = false; + } + else + { + //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString()); + _zeroFlag = false; + m_lastUpdateSent = false; + //m_throttleUpdates = false; + } - if (_parent == null) - base.RequestPhysicsterseUpdate(); + if (_zeroFlag) + { // Its stopped + _velocity.X = 0.0f; + _velocity.Y = 0.0f; + _velocity.Z = 0.0f; + _acceleration.X = 0; + _acceleration.Y = 0; + _acceleration.Z = 0; + //_orientation.w = 0f; + //_orientation.X = 0f; + //_orientation.Y = 0f; + //_orientation.Z = 0f; + m_rotationalVelocity.X = 0; + m_rotationalVelocity.Y = 0; + m_rotationalVelocity.Z = 0; + if (!m_lastUpdateSent) + { m_throttleUpdates = false; throttleCounter = 0; - _zeroFlag = true; - //outofBounds = true; - } + if (_parent == null) + { + base.RequestPhysicsterseUpdate(); + } - //float Adiff = 1.0f - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)); -//Console.WriteLine("Adiff " + m_primName + " = " + Adiff); - if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) - && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) - && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) -// && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.01)) - && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large - { - _zeroFlag = true; -//Console.WriteLine("ZFT 2"); - m_throttleUpdates = false; + m_lastUpdateSent = true; } - else + } + else + { // Its moving + if (lastZeroFlag != _zeroFlag) { - //m_log.Debug(Math.Abs(m_lastposition.X - l_position.X).ToString()); - _zeroFlag = false; - m_lastUpdateSent = false; - //m_throttleUpdates = false; - } - - if (_zeroFlag) - { // Its stopped - _velocity.X = 0.0f; - _velocity.Y = 0.0f; - _velocity.Z = 0.0f; - - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; - - //_orientation.w = 0f; - //_orientation.X = 0f; - //_orientation.Y = 0f; - //_orientation.Z = 0f; - m_rotationalVelocity.X = 0; - m_rotationalVelocity.Y = 0; - m_rotationalVelocity.Z = 0; - if (!m_lastUpdateSent) + if (_parent == null) { - m_throttleUpdates = false; - throttleCounter = 0; - // m_rotationalVelocity = pv; What was this for? - - if (_parent == null) - { - base.RequestPhysicsterseUpdate(); - } - - m_lastUpdateSent = true; + base.RequestPhysicsterseUpdate(); } } - else - { // Its moving - if (lastZeroFlag != _zeroFlag) - { - if (_parent == null) - { - base.RequestPhysicsterseUpdate(); - } - } - m_lastVelocity = _velocity; + m_lastVelocity = _velocity; - _position = l_position; + _position = l_position; - _velocity.X = vel.X; - _velocity.Y = vel.Y; - _velocity.Z = vel.Z; + _velocity.X = vel.X; + _velocity.Y = vel.Y; + _velocity.Z = vel.Z; // Why 2 calcs??? -// _acceleration = ((_velocity - m_lastVelocity) / 0.1f); -// _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, -// _velocity.Y - m_lastVelocity.Y / 0.1f, +// _acceleration = ((_velocity - m_lastVelocity) / 0.1f); +// _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, +// _velocity.Y - m_lastVelocity.Y / 0.1f, // _velocity.Z - m_lastVelocity.Z / 0.1f); - _acceleration = ((_velocity - m_lastVelocity) / timestep); + _acceleration = ((_velocity - m_lastVelocity) / timestep); - _orientation.X = ori.X; - _orientation.Y = ori.Y; - _orientation.Z = ori.Z; - _orientation.W = ori.W; - m_lastUpdateSent = false; - if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) - { - if (_parent == null) - { - base.RequestPhysicsterseUpdate(); - } - } - else + _orientation.X = ori.X; + _orientation.Y = ori.Y; + _orientation.Z = ori.Z; + _orientation.W = ori.W; + m_lastUpdateSent = false; + if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) + { + if (_parent == null) { - throttleCounter++; + base.RequestPhysicsterseUpdate(); } } - m_lastposition = l_position; - + else + { + throttleCounter++; + } + } + m_lastposition = l_position; + /// End of old UpdatePositionAndVelocity insert //if (!Acceleration.ApproxEquals(Vector3.Zero, 0.01f)) Console.WriteLine("Move " + m_primName + " Accel=" + Acceleration); -//if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_type + - // " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); +// if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_type + +// " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); if (m_type != Vehicle.TYPE_NONE) { // get body attitude @@ -3701,7 +3442,6 @@ Console.WriteLine(" JointCreateFixed"); //if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); m_lastAngularVelocity = angObjectVel; -if(frcount == 0) Console.WriteLine("angularEnable {0}", m_angularEnable); if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) { @@ -3720,14 +3460,11 @@ if(frcount == 0) Console.WriteLine("angularEnable {0}", m_angularEnable); d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); //if(frcount == 0) Console.WriteLine("V4 = {0}", m_lastAngularVelocity); - } // end VEHICLES #### + } // end VEHICLES else { if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 // NON-'VEHICLES' are dealt with here - // m_angularEnable = <1,1,1> means no lock. a 0 on axis means locked. - -// NB this may be wrong - may lock global axis! Should be LOCAL axis! /// Dynamics Angular Lock ======================================================================== if (d.BodyIsEnabled(Body) && !m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) { @@ -3802,7 +3539,7 @@ if(frcount == 0) Console.WriteLine("angularEnable {0}", m_angularEnable); d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); d.BodySetLinearVel(Body, 0, 0, 0); d.BodyAddForce(Body, 0, 0, fz); - return; + // return; } else { @@ -3911,7 +3648,6 @@ if(frcount == 0) Console.WriteLine("angularEnable {0}", m_angularEnable); // float m_APIDDamping // From SL experiments, this is damping, 1.0 = damped, 0.1 = wobbly // Also in SL the mass of the object has no effect on time to get there. // Factors: -//if(frcount == 0) Console.WriteLine("APID "); // get present body rotation float limit = 1.0f; float scaler = 50f; // adjusts damping time diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 180fba9..83f7db0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2899,10 +2899,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // the angles of rotation in radians into rotation value LSL_Types.Quaternion rot = llEuler2Rot(angle); + /* Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); m_host.startLookAt(rotation, (float)damping, (float)strength); + This would only work if your physics system contains an APID controller */ // Orient the object to the angle calculated - //llSetRot(rot); + llSetRot(rot); } public void llRotLookAt(LSL_Rotation target, double strength, double damping) -- cgit v1.1 From a1cd3b5b88cc2cc3fcd552085dc9ab46f9d9b10f Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 15 Mar 2010 17:54:39 +0000 Subject: Change GodLevel to UserLevel so gods can teleport freely without having to enter god mode first --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 24179a9..2661dc3 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -879,7 +879,7 @@ namespace OpenSim.Region.Framework.Scenes if (land != null) { //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. - if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) + if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) { pos = land.LandData.UserLocation; } -- cgit v1.1 From 37815f34029d7fe4404b6733764892a9a2fe9086 Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Tue, 16 Mar 2010 18:13:00 +0100 Subject: Debugger tags for VS2010 --- .../Shared/Api/Implementation/LSL_Api.cs | 387 +++++++++++---------- .../ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | 2 + 2 files changed, 196 insertions(+), 193 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8e5c203..485a3b5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -221,8 +221,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public List GetLinkParts(int linkType) { - List ret = new List(); - if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) + List ret = new List(); + if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) return ret; ret.Add(m_host); @@ -1115,6 +1115,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return detectedParams.TouchUV; } + [DebuggerNonUserCode] public virtual void llDie() { m_host.AddScriptLPS(1); @@ -1190,8 +1191,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void llSetStatus(int status, int value) - { - if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) + { + if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) return; m_host.AddScriptLPS(1); @@ -1367,7 +1368,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetScale(SceneObjectPart part, LSL_Vector scale) - { + { // TODO: this needs to trigger a persistance save as well if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; @@ -1426,8 +1427,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetColor(SceneObjectPart part, LSL_Vector color, int face) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; Primitive.TextureEntry tex = part.Shape.Textures; @@ -1471,8 +1472,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void SetTexGen(SceneObjectPart part, int face,int style) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; Primitive.TextureEntry tex = part.Shape.Textures; @@ -1504,8 +1505,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void SetGlow(SceneObjectPart part, int face, float glow) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; Primitive.TextureEntry tex = part.Shape.Textures; @@ -1532,8 +1533,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; Shininess sval = new Shininess(); @@ -1584,8 +1585,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void SetFullBright(SceneObjectPart part, int face, bool bright) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; Primitive.TextureEntry tex = part.Shape.Textures; @@ -1654,8 +1655,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetAlpha(SceneObjectPart part, double alpha, int face) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; Primitive.TextureEntry tex = part.Shape.Textures; @@ -1702,8 +1703,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, float wind, float tension, LSL_Vector Force) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; if (flexi) @@ -1737,8 +1738,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; if (light) @@ -1823,8 +1824,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetTexture(SceneObjectPart part, string texture, int face) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; UUID textureID=new UUID(); @@ -1871,8 +1872,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; Primitive.TextureEntry tex = part.Shape.Textures; @@ -1910,8 +1911,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; Primitive.TextureEntry tex = part.Shape.Textures; @@ -1949,8 +1950,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void RotateTexture(SceneObjectPart part, double rotation, int face) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; Primitive.TextureEntry tex = part.Shape.Textures; @@ -2022,8 +2023,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPos(SceneObjectPart part, LSL_Vector targetPos) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) @@ -2119,8 +2120,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetRot(SceneObjectPart part, Quaternion rot) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; part.UpdateRotation(rot); @@ -4016,7 +4017,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api bucket); if (m_TransferModule != null) - m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); + m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); //This delay should only occur when giving inventory to avatars. ScriptSleep(3000); @@ -6662,9 +6663,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist) - { - ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return shapeBlock; if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && @@ -6735,8 +6736,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; ObjectShapePacket.ObjectDataBlock shapeBlock; @@ -6787,8 +6788,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; ObjectShapePacket.ObjectDataBlock shapeBlock; @@ -6832,8 +6833,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } 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 fudge) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; ObjectShapePacket.ObjectDataBlock shapeBlock; @@ -6956,8 +6957,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); @@ -6993,13 +6994,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void llSetPrimitiveParams(LSL_List rules) - { + { m_host.AddScriptLPS(1); SetPrimParams(m_host, rules); } public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) - { + { m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); @@ -7014,8 +7015,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } protected void SetPrimParams(SceneObjectPart part, LSL_List rules) - { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return; int idx = 0; @@ -7848,96 +7849,96 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case (int)ScriptBaseClass.PRIM_BUMP_SHINY: - if (remain < 1) - return res; - face = (int)rules.GetLSLIntegerItem(idx++); - - tex = part.Shape.Textures; - int shiny; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < GetNumberOfSides(part); face++) - { - Shininess shinyness = tex.GetFace((uint)face).Shiny; - if (shinyness == Shininess.High) - { - shiny = ScriptBaseClass.PRIM_SHINY_HIGH; - } - else if (shinyness == Shininess.Medium) - { - shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; - } - else if (shinyness == Shininess.Low) - { - shiny = ScriptBaseClass.PRIM_SHINY_LOW; - } - else - { - shiny = ScriptBaseClass.PRIM_SHINY_NONE; - } - res.Add(new LSL_Integer(shiny)); - res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); - } - } - else - { - Shininess shinyness = tex.GetFace((uint)face).Shiny; - if (shinyness == Shininess.High) - { - shiny = ScriptBaseClass.PRIM_SHINY_HIGH; - } - else if (shinyness == Shininess.Medium) - { - shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; - } - else if (shinyness == Shininess.Low) - { - shiny = ScriptBaseClass.PRIM_SHINY_LOW; - } - else - { - shiny = ScriptBaseClass.PRIM_SHINY_NONE; - } - res.Add(new LSL_Integer(shiny)); - res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); - } + case (int)ScriptBaseClass.PRIM_BUMP_SHINY: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + tex = part.Shape.Textures; + int shiny; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < GetNumberOfSides(part); face++) + { + Shininess shinyness = tex.GetFace((uint)face).Shiny; + if (shinyness == Shininess.High) + { + shiny = ScriptBaseClass.PRIM_SHINY_HIGH; + } + else if (shinyness == Shininess.Medium) + { + shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; + } + else if (shinyness == Shininess.Low) + { + shiny = ScriptBaseClass.PRIM_SHINY_LOW; + } + else + { + shiny = ScriptBaseClass.PRIM_SHINY_NONE; + } + res.Add(new LSL_Integer(shiny)); + res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); + } + } + else + { + Shininess shinyness = tex.GetFace((uint)face).Shiny; + if (shinyness == Shininess.High) + { + shiny = ScriptBaseClass.PRIM_SHINY_HIGH; + } + else if (shinyness == Shininess.Medium) + { + shiny = ScriptBaseClass.PRIM_SHINY_MEDIUM; + } + else if (shinyness == Shininess.Low) + { + shiny = ScriptBaseClass.PRIM_SHINY_LOW; + } + else + { + shiny = ScriptBaseClass.PRIM_SHINY_NONE; + } + res.Add(new LSL_Integer(shiny)); + res.Add(new LSL_Integer((int)tex.GetFace((uint)face).Bump)); + } break; - case (int)ScriptBaseClass.PRIM_FULLBRIGHT: - if (remain < 1) - return res; - face = (int)rules.GetLSLIntegerItem(idx++); - - tex = part.Shape.Textures; - int fullbright; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < GetNumberOfSides(part); face++) - { - if (tex.GetFace((uint)face).Fullbright == true) - { - fullbright = ScriptBaseClass.TRUE; - } - else - { - fullbright = ScriptBaseClass.FALSE; - } - res.Add(new LSL_Integer(fullbright)); - } - } - else - { - if (tex.GetFace((uint)face).Fullbright == true) - { - fullbright = ScriptBaseClass.TRUE; - } - else - { - fullbright = ScriptBaseClass.FALSE; - } - res.Add(new LSL_Integer(fullbright)); - } + case (int)ScriptBaseClass.PRIM_FULLBRIGHT: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + tex = part.Shape.Textures; + int fullbright; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < GetNumberOfSides(part); face++) + { + if (tex.GetFace((uint)face).Fullbright == true) + { + fullbright = ScriptBaseClass.TRUE; + } + else + { + fullbright = ScriptBaseClass.FALSE; + } + res.Add(new LSL_Integer(fullbright)); + } + } + else + { + if (tex.GetFace((uint)face).Fullbright == true) + { + fullbright = ScriptBaseClass.TRUE; + } + else + { + fullbright = ScriptBaseClass.FALSE; + } + res.Add(new LSL_Integer(fullbright)); + } break; case (int)ScriptBaseClass.PRIM_FLEXIBLE: @@ -7958,37 +7959,37 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_TEXGEN: - // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) - if (remain < 1) - return res; - face = (int)rules.GetLSLIntegerItem(idx++); - - tex = part.Shape.Textures; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < GetNumberOfSides(part); face++) - { - if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); - } - } - } - else - { - if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); - } - } + // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + tex = part.Shape.Textures; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < GetNumberOfSides(part); face++) + { + if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } + } + } + else + { + if (tex.GetFace((uint)face).TexMapType == MappingType.Planar) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_PLANAR)); + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } + } break; case (int)ScriptBaseClass.PRIM_POINT_LIGHT: @@ -8006,26 +8007,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api res.Add(new LSL_Float(shape.LightFalloff)); // falloff break; - case (int)ScriptBaseClass.PRIM_GLOW: - if (remain < 1) + case (int)ScriptBaseClass.PRIM_GLOW: + if (remain < 1) return res; - face = (int)rules.GetLSLIntegerItem(idx++); - - tex = part.Shape.Textures; - float primglow; - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < GetNumberOfSides(part); face++) - { - primglow = tex.GetFace((uint)face).Glow; - res.Add(new LSL_Float(primglow)); - } - } - else - { - primglow = tex.GetFace((uint)face).Glow; - res.Add(new LSL_Float(primglow)); - } + face = (int)rules.GetLSLIntegerItem(idx++); + + tex = part.Shape.Textures; + float primglow; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < GetNumberOfSides(part); face++) + { + primglow = tex.GetFace((uint)face).Glow; + res.Add(new LSL_Float(primglow)); + } + } + else + { + primglow = tex.GetFace((uint)face).Glow; + res.Add(new LSL_Float(primglow)); + } break; case (int)ScriptBaseClass.PRIM_TEXT: Color4 textColor = part.GetTextColor(); @@ -9187,7 +9188,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); if (quick_pay_buttons.Data.Length < 4) - { + { int x; for (x=quick_pay_buttons.Data.Length; x<= 4; x++) { @@ -9195,12 +9196,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } int[] nPrice = new int[5]; - nPrice[0]=price; - nPrice[1] = (LSL_Integer)quick_pay_buttons.Data[0]; - nPrice[2] = (LSL_Integer)quick_pay_buttons.Data[1]; - nPrice[3] = (LSL_Integer)quick_pay_buttons.Data[2]; + nPrice[0]=price; + nPrice[1] = (LSL_Integer)quick_pay_buttons.Data[0]; + nPrice[2] = (LSL_Integer)quick_pay_buttons.Data[1]; + nPrice[3] = (LSL_Integer)quick_pay_buttons.Data[2]; nPrice[4] = (LSL_Integer)quick_pay_buttons.Data[3]; - m_host.ParentGroup.RootPart.PayPrice = nPrice; + m_host.ParentGroup.RootPart.PayPrice = nPrice; m_host.ParentGroup.HasGroupChanged = true; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index 3339995..e86d08c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -26,6 +26,7 @@ */ using System; +using System.Diagnostics; //for [DebuggerNonUserCode] using System.Runtime.Remoting.Lifetime; using System.Threading; using System.Reflection; @@ -309,6 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_LSL_Functions.llDialog(avatar, message, buttons, chat_channel); } + [DebuggerNonUserCode] public void llDie() { m_LSL_Functions.llDie(); -- cgit v1.1 From e442c2a3f9dc1823c00ddc1c81802fdabd7883dc Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Wed, 17 Mar 2010 17:42:33 +0100 Subject: Prevent llTeleportAgentHome from affecting gods --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 485a3b5..10ebf67 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4193,6 +4193,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(agentId); if (presence != null) { + // agent must not be a god + if (presence.GodLevel >= 200) return; + // agent must be over the owners land if (m_host.OwnerID == World.LandChannel.GetLandObject( presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) -- cgit v1.1 From 6df969894c1943dceeefd3765951daaf0a2eb94c Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Wed, 17 Mar 2010 13:30:48 -0400 Subject: Fix AbsolutePosition for autopilot/sit. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 24179a9..608e84c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -463,7 +463,8 @@ namespace OpenSim.Region.Framework.Scenes get { PhysicsActor actor = m_physicsActor; - if (actor != null) +// if (actor != null) + if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting! m_pos = actor.Position; return m_parentPosition + m_pos; @@ -484,7 +485,8 @@ namespace OpenSim.Region.Framework.Scenes } } - m_pos = value; + if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting! + m_pos = value; m_parentPosition = Vector3.Zero; } } @@ -1267,6 +1269,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); m_pos = m_LastFinitePos; + if (!m_pos.IsFinite()) { m_pos.X = 127f; @@ -1904,6 +1907,7 @@ namespace OpenSim.Region.Framework.Scenes { m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center autopilotTarget = part.AbsolutePosition; +//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget); } else return; // occupied small } // end large/small @@ -2280,7 +2284,8 @@ namespace OpenSim.Region.Framework.Scenes m_pos += SIT_TARGET_ADJUSTMENT; m_bodyRot = sitTargetOrient; m_parentPosition = part.AbsolutePosition; - part.IsOccupied = true; + part.IsOccupied = true; +Console.WriteLine("Scripted Sit ofset {0}", m_pos); } else { @@ -3348,6 +3353,7 @@ namespace OpenSim.Region.Framework.Scenes m_callbackURI = cAgent.CallbackURI; m_pos = cAgent.Position; + m_velocity = cAgent.Velocity; m_CameraCenter = cAgent.Center; //m_avHeight = cAgent.Size.Z; -- cgit v1.1 From f35eb8819c6a872e7c4727940ffc560f7d5d68bd Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 18 Mar 2010 18:57:29 +0000 Subject: Unify a previous refactor of object return with the older solution. We really don't need two methods doing the same thing, but differently. --- .../Region/CoreModules/World/Land/LandObject.cs | 2 +- .../World/Permissions/PermissionsModule.cs | 71 ++-------------------- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 7 ++- .../Region/Framework/Scenes/Scene.Permissions.cs | 29 ++------- .../RegionCombinerModule/RegionCombinerModule.cs | 3 +- .../RegionCombinerPermissionModule.cs | 11 +--- 6 files changed, 21 insertions(+), 102 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 1c65965..b8c35f7 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -915,7 +915,7 @@ namespace OpenSim.Region.CoreModules.World.Land foreach (List ol in returns.Values) { - if (m_scene.Permissions.CanUseObjectReturn(this, type, remote_client, ol)) + if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); } } diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 1533462..7159dc6 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -200,7 +200,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand; //FULLY IMPLEMENTED m_scene.Permissions.OnMoveObject += CanMoveObject; //MAYBE FULLY IMPLEMENTED m_scene.Permissions.OnObjectEntry += CanObjectEntry; - m_scene.Permissions.OnReturnObject += CanReturnObject; //NOT YET IMPLEMENTED + m_scene.Permissions.OnReturnObjects += CanReturnObjects; //NOT YET IMPLEMENTED m_scene.Permissions.OnRezObject += CanRezObject; //MAYBE FULLY IMPLEMENTED m_scene.Permissions.OnRunConsoleCommand += CanRunConsoleCommand; m_scene.Permissions.OnRunScript += CanRunScript; //NOT YET IMPLEMENTED @@ -230,7 +230,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; //NOT YET IMPLEMENTED m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED - m_scene.Permissions.OnUseObjectReturn += CanUseObjectReturn; //NOT YET IMPLEMENTED m_scene.AddCommand(this, "bypass permissions", "bypass permissions ", @@ -1258,12 +1257,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; } - private bool CanReturnObject(UUID objectID, UUID returnerID, Scene scene) + private bool CanReturnObjects(ILandObject land, UUID user, List objects, Scene scene) { + if (objects.Count == 0) + return false; + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(returnerID, objectID, false); + return GenericObjectPermission(user, objects[0].UUID, false); } private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) @@ -1730,67 +1732,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions return GenericObjectPermission(agentID, prim, false); } - private bool CanUseObjectReturn(ILandObject parcel, uint type, IClientAPI client, List retlist, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - long powers = 0; - if (parcel.LandData.GroupID != UUID.Zero) - client.GetGroupPowers(parcel.LandData.GroupID); - - switch (type) - { - case (uint)ObjectReturnType.Owner: - // Don't let group members return owner's objects, ever - // - if (parcel.LandData.IsGroupOwned) - { - if ((powers & (long)GroupPowers.ReturnGroupOwned) != 0) - return true; - } - else - { - if (parcel.LandData.OwnerID != client.AgentId) - return false; - } - return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnGroupOwned); - case (uint)ObjectReturnType.Group: - if (parcel.LandData.OwnerID != client.AgentId) - { - // If permissionis granted through a group... - // - if ((powers & (long)GroupPowers.ReturnGroupSet) != 0) - { - foreach (SceneObjectGroup g in new List(retlist)) - { - // check for and remove group owned objects unless - // the user also has permissions to return those - // - if (g.OwnerID == g.GroupID && - ((powers & (long)GroupPowers.ReturnGroupOwned) == 0)) - { - retlist.Remove(g); - } - } - // And allow the operation - // - return true; - } - } - return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnGroupSet); - case (uint)ObjectReturnType.Other: - if ((powers & (long)GroupPowers.ReturnNonGroup) != 0) - return true; - return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnNonGroup); - case (uint)ObjectReturnType.List: - break; - } - - return GenericParcelOwnerPermission(client.AgentId, parcel, 0); - // Is it correct to be less restrictive for lists of objects to be returned? - } - private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) { //m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType); switch (scriptType) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index b2b061e..ffbf745 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1581,9 +1581,10 @@ namespace OpenSim.Region.Framework.Scenes if (remoteClient != null) { permissionToTake = - Permissions.CanReturnObject( - grp.UUID, - remoteClient.AgentId); + Permissions.CanReturnObjects( + null, + remoteClient.AgentId, + new List() {grp}); permissionToDelete = permissionToTake; if (permissionToDelete) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs index d1d6b6a..7dab04f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs @@ -48,7 +48,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); - public delegate bool ReturnObjectHandler(UUID objectID, UUID returnerID, Scene scene); + public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List objects, Scene scene); public delegate bool InstantMessageHandler(UUID user, UUID target, Scene startScene); public delegate bool InventoryTransferHandler(UUID user, UUID target, Scene startScene); public delegate bool ViewScriptHandler(UUID script, UUID objectID, UUID user, Scene scene); @@ -81,7 +81,6 @@ namespace OpenSim.Region.Framework.Scenes public delegate bool CopyUserInventoryHandler(UUID itemID, UUID userID); public delegate bool DeleteUserInventoryHandler(UUID itemID, UUID userID); public delegate bool TeleportHandler(UUID userID, Scene scene); - public delegate bool UseObjectReturnHandler(ILandObject landData, uint type, IClientAPI client, List retlist, Scene scene); #endregion public class ScenePermissions @@ -107,7 +106,7 @@ namespace OpenSim.Region.Framework.Scenes public event EditObjectInventoryHandler OnEditObjectInventory; public event MoveObjectHandler OnMoveObject; public event ObjectEntryHandler OnObjectEntry; - public event ReturnObjectHandler OnReturnObject; + public event ReturnObjectsHandler OnReturnObjects; public event InstantMessageHandler OnInstantMessage; public event InventoryTransferHandler OnInventoryTransfer; public event ViewScriptHandler OnViewScript; @@ -140,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes public event CopyUserInventoryHandler OnCopyUserInventory; public event DeleteUserInventoryHandler OnDeleteUserInventory; public event TeleportHandler OnTeleport; - public event UseObjectReturnHandler OnUseObjectReturn; #endregion #region Object Permission Checks @@ -377,15 +375,15 @@ namespace OpenSim.Region.Framework.Scenes #endregion #region RETURN OBJECT - public bool CanReturnObject(UUID objectID, UUID returnerID) + public bool CanReturnObjects(ILandObject land, UUID user, List objects) { - ReturnObjectHandler handler = OnReturnObject; + ReturnObjectsHandler handler = OnReturnObjects; if (handler != null) { Delegate[] list = handler.GetInvocationList(); - foreach (ReturnObjectHandler h in list) + foreach (ReturnObjectsHandler h in list) { - if (h(objectID, returnerID, m_scene) == false) + if (h(land, user, objects, m_scene) == false) return false; } } @@ -949,20 +947,5 @@ namespace OpenSim.Region.Framework.Scenes } return true; } - - public bool CanUseObjectReturn(ILandObject landData, uint type , IClientAPI client, List retlist) - { - UseObjectReturnHandler handler = OnUseObjectReturn; - if (handler != null) - { - Delegate[] list = handler.GetInvocationList(); - foreach (UseObjectReturnHandler h in list) - { - if (h(landData, type, client, retlist, m_scene) == false) - return false; - } - } - return true; - } } } diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 92f060b..0b8771c 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -922,7 +922,7 @@ namespace OpenSim.Region.RegionCombinerModule VirtualRegion.Permissions.OnIssueEstateCommand += BigRegion.PermissionModule.CanIssueEstateCommand; //FULLY IMPLEMENTED VirtualRegion.Permissions.OnMoveObject += BigRegion.PermissionModule.CanMoveObject; //MAYBE FULLY IMPLEMENTED VirtualRegion.Permissions.OnObjectEntry += BigRegion.PermissionModule.CanObjectEntry; - VirtualRegion.Permissions.OnReturnObject += BigRegion.PermissionModule.CanReturnObject; //NOT YET IMPLEMENTED + VirtualRegion.Permissions.OnReturnObjects += BigRegion.PermissionModule.CanReturnObjects; //NOT YET IMPLEMENTED VirtualRegion.Permissions.OnRezObject += BigRegion.PermissionModule.CanRezObject; //MAYBE FULLY IMPLEMENTED VirtualRegion.Permissions.OnRunConsoleCommand += BigRegion.PermissionModule.CanRunConsoleCommand; VirtualRegion.Permissions.OnRunScript += BigRegion.PermissionModule.CanRunScript; //NOT YET IMPLEMENTED @@ -948,7 +948,6 @@ namespace OpenSim.Region.RegionCombinerModule VirtualRegion.Permissions.OnEditUserInventory += BigRegion.PermissionModule.CanEditUserInventory; //NOT YET IMPLEMENTED VirtualRegion.Permissions.OnDeleteUserInventory += BigRegion.PermissionModule.CanDeleteUserInventory; //NOT YET IMPLEMENTED VirtualRegion.Permissions.OnTeleport += BigRegion.PermissionModule.CanTeleport; //NOT YET IMPLEMENTED - VirtualRegion.Permissions.OnUseObjectReturn += BigRegion.PermissionModule.CanUseObjectReturn; //NOT YET IMPLEMENTED } #region console commands diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs index 4d1af57..393322d 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs @@ -135,9 +135,9 @@ namespace OpenSim.Region.RegionCombinerModule return m_rootScene.Permissions.CanObjectEntry(objectid, enteringregion, newpoint); } - public bool CanReturnObject(UUID objectid, UUID returnerid, Scene scene) + public bool CanReturnObjects(ILandObject land, UUID user, List objects, Scene scene) { - return m_rootScene.Permissions.CanReturnObject(objectid, returnerid); + return m_rootScene.Permissions.CanReturnObjects(land, user, objects); } public bool CanRezObject(int objectcount, UUID owner, Vector3 objectposition, Scene scene) @@ -265,11 +265,6 @@ namespace OpenSim.Region.RegionCombinerModule return m_rootScene.Permissions.CanTeleport(userid); } - public bool CanUseObjectReturn(ILandObject landdata, uint type, IClientAPI client, List retlist, Scene scene) - { - return m_rootScene.Permissions.CanUseObjectReturn(landdata, type, client, retlist); - } - #endregion } -} \ No newline at end of file +} -- cgit v1.1 From 69b5ddceda1fd418712fb7ada0443555dc82b231 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 18 Mar 2010 18:57:29 +0000 Subject: Unify a previous refactor of object return with the older solution. We really don't need two methods doing the same thing, but differently. --- .../Region/CoreModules/World/Land/LandObject.cs | 2 +- .../World/Permissions/PermissionsModule.cs | 71 ++-------------------- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 7 ++- .../Region/Framework/Scenes/Scene.Permissions.cs | 29 ++------- .../RegionCombinerModule/RegionCombinerModule.cs | 3 +- .../RegionCombinerPermissionModule.cs | 11 +--- 6 files changed, 21 insertions(+), 102 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index e85136a..331f183 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -892,7 +892,7 @@ namespace OpenSim.Region.CoreModules.World.Land foreach (List ol in returns.Values) { - if (m_scene.Permissions.CanUseObjectReturn(this, type, remote_client, ol)) + if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); } } diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 5c7f3b7..38fc250 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -217,7 +217,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand; //FULLY IMPLEMENTED m_scene.Permissions.OnMoveObject += CanMoveObject; //MAYBE FULLY IMPLEMENTED m_scene.Permissions.OnObjectEntry += CanObjectEntry; - m_scene.Permissions.OnReturnObject += CanReturnObject; //NOT YET IMPLEMENTED + m_scene.Permissions.OnReturnObjects += CanReturnObjects; //NOT YET IMPLEMENTED m_scene.Permissions.OnRezObject += CanRezObject; //MAYBE FULLY IMPLEMENTED m_scene.Permissions.OnRunConsoleCommand += CanRunConsoleCommand; m_scene.Permissions.OnRunScript += CanRunScript; //NOT YET IMPLEMENTED @@ -247,7 +247,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; //NOT YET IMPLEMENTED m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED - m_scene.Permissions.OnUseObjectReturn += CanUseObjectReturn; //NOT YET IMPLEMENTED m_scene.AddCommand(this, "bypass permissions", "bypass permissions ", @@ -1275,12 +1274,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; } - private bool CanReturnObject(UUID objectID, UUID returnerID, Scene scene) + private bool CanReturnObjects(ILandObject land, UUID user, List objects, Scene scene) { + if (objects.Count == 0) + return false; + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(returnerID, objectID, false); + return GenericObjectPermission(user, objects[0].UUID, false); } private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) @@ -1747,67 +1749,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions return GenericObjectPermission(agentID, prim, false); } - private bool CanUseObjectReturn(ILandObject parcel, uint type, IClientAPI client, List retlist, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - long powers = 0; - if (parcel.LandData.GroupID != UUID.Zero) - client.GetGroupPowers(parcel.LandData.GroupID); - - switch (type) - { - case (uint)ObjectReturnType.Owner: - // Don't let group members return owner's objects, ever - // - if (parcel.LandData.IsGroupOwned) - { - if ((powers & (long)GroupPowers.ReturnGroupOwned) != 0) - return true; - } - else - { - if (parcel.LandData.OwnerID != client.AgentId) - return false; - } - return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnGroupOwned); - case (uint)ObjectReturnType.Group: - if (parcel.LandData.OwnerID != client.AgentId) - { - // If permissionis granted through a group... - // - if ((powers & (long)GroupPowers.ReturnGroupSet) != 0) - { - foreach (SceneObjectGroup g in new List(retlist)) - { - // check for and remove group owned objects unless - // the user also has permissions to return those - // - if (g.OwnerID == g.GroupID && - ((powers & (long)GroupPowers.ReturnGroupOwned) == 0)) - { - retlist.Remove(g); - } - } - // And allow the operation - // - return true; - } - } - return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnGroupSet); - case (uint)ObjectReturnType.Other: - if ((powers & (long)GroupPowers.ReturnNonGroup) != 0) - return true; - return GenericParcelOwnerPermission(client.AgentId, parcel, (ulong)GroupPowers.ReturnNonGroup); - case (uint)ObjectReturnType.List: - break; - } - - return GenericParcelOwnerPermission(client.AgentId, parcel, 0); - // Is it correct to be less restrictive for lists of objects to be returned? - } - private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) { //m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType); switch (scriptType) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6ebd048..cadb858 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1522,9 +1522,10 @@ namespace OpenSim.Region.Framework.Scenes if (remoteClient != null) { permissionToTake = - Permissions.CanReturnObject( - grp.UUID, - remoteClient.AgentId); + Permissions.CanReturnObjects( + null, + remoteClient.AgentId, + new List() {grp}); permissionToDelete = permissionToTake; if (permissionToDelete) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs index d1d6b6a..7dab04f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs @@ -48,7 +48,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); - public delegate bool ReturnObjectHandler(UUID objectID, UUID returnerID, Scene scene); + public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List objects, Scene scene); public delegate bool InstantMessageHandler(UUID user, UUID target, Scene startScene); public delegate bool InventoryTransferHandler(UUID user, UUID target, Scene startScene); public delegate bool ViewScriptHandler(UUID script, UUID objectID, UUID user, Scene scene); @@ -81,7 +81,6 @@ namespace OpenSim.Region.Framework.Scenes public delegate bool CopyUserInventoryHandler(UUID itemID, UUID userID); public delegate bool DeleteUserInventoryHandler(UUID itemID, UUID userID); public delegate bool TeleportHandler(UUID userID, Scene scene); - public delegate bool UseObjectReturnHandler(ILandObject landData, uint type, IClientAPI client, List retlist, Scene scene); #endregion public class ScenePermissions @@ -107,7 +106,7 @@ namespace OpenSim.Region.Framework.Scenes public event EditObjectInventoryHandler OnEditObjectInventory; public event MoveObjectHandler OnMoveObject; public event ObjectEntryHandler OnObjectEntry; - public event ReturnObjectHandler OnReturnObject; + public event ReturnObjectsHandler OnReturnObjects; public event InstantMessageHandler OnInstantMessage; public event InventoryTransferHandler OnInventoryTransfer; public event ViewScriptHandler OnViewScript; @@ -140,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes public event CopyUserInventoryHandler OnCopyUserInventory; public event DeleteUserInventoryHandler OnDeleteUserInventory; public event TeleportHandler OnTeleport; - public event UseObjectReturnHandler OnUseObjectReturn; #endregion #region Object Permission Checks @@ -377,15 +375,15 @@ namespace OpenSim.Region.Framework.Scenes #endregion #region RETURN OBJECT - public bool CanReturnObject(UUID objectID, UUID returnerID) + public bool CanReturnObjects(ILandObject land, UUID user, List objects) { - ReturnObjectHandler handler = OnReturnObject; + ReturnObjectsHandler handler = OnReturnObjects; if (handler != null) { Delegate[] list = handler.GetInvocationList(); - foreach (ReturnObjectHandler h in list) + foreach (ReturnObjectsHandler h in list) { - if (h(objectID, returnerID, m_scene) == false) + if (h(land, user, objects, m_scene) == false) return false; } } @@ -949,20 +947,5 @@ namespace OpenSim.Region.Framework.Scenes } return true; } - - public bool CanUseObjectReturn(ILandObject landData, uint type , IClientAPI client, List retlist) - { - UseObjectReturnHandler handler = OnUseObjectReturn; - if (handler != null) - { - Delegate[] list = handler.GetInvocationList(); - foreach (UseObjectReturnHandler h in list) - { - if (h(landData, type, client, retlist, m_scene) == false) - return false; - } - } - return true; - } } } diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 92f060b..0b8771c 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -922,7 +922,7 @@ namespace OpenSim.Region.RegionCombinerModule VirtualRegion.Permissions.OnIssueEstateCommand += BigRegion.PermissionModule.CanIssueEstateCommand; //FULLY IMPLEMENTED VirtualRegion.Permissions.OnMoveObject += BigRegion.PermissionModule.CanMoveObject; //MAYBE FULLY IMPLEMENTED VirtualRegion.Permissions.OnObjectEntry += BigRegion.PermissionModule.CanObjectEntry; - VirtualRegion.Permissions.OnReturnObject += BigRegion.PermissionModule.CanReturnObject; //NOT YET IMPLEMENTED + VirtualRegion.Permissions.OnReturnObjects += BigRegion.PermissionModule.CanReturnObjects; //NOT YET IMPLEMENTED VirtualRegion.Permissions.OnRezObject += BigRegion.PermissionModule.CanRezObject; //MAYBE FULLY IMPLEMENTED VirtualRegion.Permissions.OnRunConsoleCommand += BigRegion.PermissionModule.CanRunConsoleCommand; VirtualRegion.Permissions.OnRunScript += BigRegion.PermissionModule.CanRunScript; //NOT YET IMPLEMENTED @@ -948,7 +948,6 @@ namespace OpenSim.Region.RegionCombinerModule VirtualRegion.Permissions.OnEditUserInventory += BigRegion.PermissionModule.CanEditUserInventory; //NOT YET IMPLEMENTED VirtualRegion.Permissions.OnDeleteUserInventory += BigRegion.PermissionModule.CanDeleteUserInventory; //NOT YET IMPLEMENTED VirtualRegion.Permissions.OnTeleport += BigRegion.PermissionModule.CanTeleport; //NOT YET IMPLEMENTED - VirtualRegion.Permissions.OnUseObjectReturn += BigRegion.PermissionModule.CanUseObjectReturn; //NOT YET IMPLEMENTED } #region console commands diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs index 4d1af57..393322d 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerPermissionModule.cs @@ -135,9 +135,9 @@ namespace OpenSim.Region.RegionCombinerModule return m_rootScene.Permissions.CanObjectEntry(objectid, enteringregion, newpoint); } - public bool CanReturnObject(UUID objectid, UUID returnerid, Scene scene) + public bool CanReturnObjects(ILandObject land, UUID user, List objects, Scene scene) { - return m_rootScene.Permissions.CanReturnObject(objectid, returnerid); + return m_rootScene.Permissions.CanReturnObjects(land, user, objects); } public bool CanRezObject(int objectcount, UUID owner, Vector3 objectposition, Scene scene) @@ -265,11 +265,6 @@ namespace OpenSim.Region.RegionCombinerModule return m_rootScene.Permissions.CanTeleport(userid); } - public bool CanUseObjectReturn(ILandObject landdata, uint type, IClientAPI client, List retlist, Scene scene) - { - return m_rootScene.Permissions.CanUseObjectReturn(landdata, type, client, retlist); - } - #endregion } -} \ No newline at end of file +} -- cgit v1.1 From 3ea72eeabb12cff4f71523f501450a7df38a17b1 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Fri, 19 Mar 2010 13:26:34 -0400 Subject: Fix sit with autopilot. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 123d6f3..2603fe1 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -455,8 +455,9 @@ namespace OpenSim.Region.Framework.Scenes get { PhysicsActor actor = m_physicsActor; - if (actor != null) - m_pos = actor.Position; +// if (actor != null) + if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting! + m_pos = actor.Position; return m_parentPosition + m_pos; } @@ -476,7 +477,8 @@ namespace OpenSim.Region.Framework.Scenes } } - m_pos = value; + if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting! + m_pos = value; m_parentPosition = Vector3.Zero; } } -- cgit v1.1 From add47befacb0397f2a0b5c9455ed1e658616aba4 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Fri, 19 Mar 2010 18:53:16 -0400 Subject: Update acceleration to 0 on no tphysical. --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 5e6696e..e8894f7 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -804,6 +804,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_isphysical && Body != IntPtr.Zero) { d.BodyDisable(Body); + Halt(); } } @@ -2972,7 +2973,8 @@ Console.WriteLine(" JointCreateFixed"); m_wLinObjectVel = Vector3.Zero; m_angularMotorDirection = Vector3.Zero; m_lastAngularVelocity = Vector3.Zero; - m_angularMotorDVel = Vector3.Zero; + m_angularMotorDVel = Vector3.Zero; + _acceleration = Vector3.Zero; } private void UpdateLinDecay() -- cgit v1.1 From e0b287961f51d776f830728c5e0fdaba5f7e53bc Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 23 Mar 2010 17:04:37 +0100 Subject: Change land overlay to send group owned status properly --- OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 9be94ce..6c9830c 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -1014,6 +1014,10 @@ namespace OpenSim.Region.CoreModules.World.Land //Owner Flag tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_REQUESTER); } + else if (currentParcelBlock.LandData.IsGroupOwned && remote_client.IsGroupMember(currentParcelBlock.LandData.GroupID)) + { + tempByte = Convert.ToByte(tempByte | LandChannel.LAND_TYPE_OWNED_BY_GROUP); + } else if (currentParcelBlock.LandData.SalePrice > 0 && (currentParcelBlock.LandData.AuthBuyerID == UUID.Zero || currentParcelBlock.LandData.AuthBuyerID == remote_client.AgentId)) -- cgit v1.1 From dd544f811a8a46b91b6101fb83b3504ef246a83c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 26 Mar 2010 19:09:09 +0000 Subject: switch flavor to RC1 --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index ec94b2d..f8ed5ae 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -30,7 +30,7 @@ namespace OpenSim public class VersionInfo { private const string VERSION_NUMBER = "0.6.9"; - private const Flavour VERSION_FLAVOUR = Flavour.Dev; + private const Flavour VERSION_FLAVOUR = Flavour.RC1; public enum Flavour { -- cgit v1.1 From 4d712ddaaef8772a6b8a96c26b948e9f827578f4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 26 Mar 2010 19:33:19 +0000 Subject: comment out very probably unused dist and distdir nant targets --- .nant/local.include | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/.nant/local.include b/.nant/local.include index 5e02665..d4c7fb0 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -1,8 +1,23 @@ - + + @@ -317,17 +333,3 @@ - - - - - - - - - - - - - - -- cgit v1.1 From 18ed68cd31383f1aff8fc1028a9f0ff5d20733b9 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 26 Mar 2010 20:47:26 +0000 Subject: add nant distbin target this will delete all extraneous source code files and copy OpenSim.ini.example to OpenSim.ini --- .nant/local.include | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/.nant/local.include b/.nant/local.include index d4c7fb0..1e8bedc 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -2,6 +2,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + -- cgit v1.1 From 7d917e7c5c599549d2a87451fe3d6ca2bf6e62a4 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 30 Mar 2010 23:29:03 +0100 Subject: Rename Meta7Windlight to LightShare --- OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs | 6 +- OpenSim/Data/MySQL/MySQLLegacyRegionData.cs | 6 +- OpenSim/Data/Null/NullDataStore.cs | 6 +- OpenSim/Data/SQLite/SQLiteRegionData.cs | 6 +- OpenSim/Framework/RegionInfo.cs | 10 +- .../CoreModules/World/Land/LandManagementModule.cs | 10 +- .../World/Meta7Windlight/Meta7WindlightModule.cs | 274 --------------------- .../Framework/Interfaces/IRegionDataStore.cs | 4 +- OpenSim/Region/Framework/Scenes/EventManager.cs | 4 +- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- .../Region/Framework/Scenes/SceneObjectGroup.cs | 11 +- .../Region/Framework/Scenes/Tests/SceneTests.cs | 6 +- .../Shared/Api/Implementation/CM_Api.cs | 116 ++++----- bin/OpenSim.ini.example | 2 +- 14 files changed, 94 insertions(+), 369 deletions(-) delete mode 100644 OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs diff --git a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs index b1339b6..d6cb91f 100644 --- a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs @@ -691,13 +691,13 @@ VALUES cmd.ExecuteNonQuery(); } } - public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) { //This connector doesn't support the windlight module yet //Return default LL windlight settings - return new RegionMeta7WindlightData(); + return new RegionLightShareData(); } - public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + public void StoreRegionWindlightSettings(RegionLightShareData wl) { //This connector doesn't support the windlight module yet } diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs index f84beb6..a395ddc 100644 --- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs @@ -711,9 +711,9 @@ namespace OpenSim.Data.MySQL } } - public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) { - RegionMeta7WindlightData nWP = new RegionMeta7WindlightData(); + RegionLightShareData nWP = new RegionLightShareData(); nWP.OnSave += StoreRegionWindlightSettings; using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) @@ -845,7 +845,7 @@ namespace OpenSim.Data.MySQL return rs; } - public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + public void StoreRegionWindlightSettings(RegionLightShareData wl) { using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { diff --git a/OpenSim/Data/Null/NullDataStore.cs b/OpenSim/Data/Null/NullDataStore.cs index 4b6d0f3..3ba44bb 100644 --- a/OpenSim/Data/Null/NullDataStore.cs +++ b/OpenSim/Data/Null/NullDataStore.cs @@ -50,13 +50,13 @@ namespace OpenSim.Data.Null public void StoreRegionSettings(RegionSettings rs) { } - public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) { //This connector doesn't support the windlight module yet //Return default LL windlight settings - return new RegionMeta7WindlightData(); + return new RegionLightShareData(); } - public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + public void StoreRegionWindlightSettings(RegionLightShareData wl) { //This connector doesn't support the windlight module yet } diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs index 81c0703..d2ba9ae 100644 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLite/SQLiteRegionData.cs @@ -272,13 +272,13 @@ namespace OpenSim.Data.SQLite Commit(); } } - public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) { //This connector doesn't support the windlight module yet //Return default LL windlight settings - return new RegionMeta7WindlightData(); + return new RegionLightShareData(); } - public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + public void StoreRegionWindlightSettings(RegionLightShareData wl) { //This connector doesn't support the windlight module yet } diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 05f9cf9..5eacd73 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -39,7 +39,7 @@ using OpenSim.Framework.Console; namespace OpenSim.Framework { - public class RegionMeta7WindlightData : ICloneable + public class RegionLightShareData : ICloneable { public UUID regionID = UUID.Zero; public Vector3 waterColor = new Vector3(4.0f,38.0f,64.0f); @@ -80,7 +80,7 @@ namespace OpenSim.Framework public bool cloudScrollYLock = false; public bool drawClassicClouds = true; - public delegate void SaveDelegate(RegionMeta7WindlightData wl); + public delegate void SaveDelegate(RegionLightShareData wl); public event SaveDelegate OnSave; public void Save() { @@ -356,7 +356,7 @@ namespace OpenSim.Framework private bool m_clampPrimSize = false; private int m_objectCapacity = 0; private string m_regionType = String.Empty; - private RegionMeta7WindlightData m_windlight = new RegionMeta7WindlightData(); + private RegionLightShareData m_windlight = new RegionLightShareData(); protected uint m_httpPort; protected string m_serverURI; protected string m_regionName = String.Empty; @@ -495,13 +495,13 @@ namespace OpenSim.Framework set { m_regionSettings = value; } } - public RegionMeta7WindlightData WindlightSettings + public RegionLightShareData WindlightSettings { get { if (m_windlight == null) { - m_windlight = new RegionMeta7WindlightData(); + m_windlight = new RegionLightShareData(); } return m_windlight; diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index b6afac6..7f6a0ad 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -1532,7 +1532,7 @@ namespace OpenSim.Region.CoreModules.World.Land private void ClientOnSimWideDeletes(IClientAPI client, UUID agentID, int flags, UUID targetID) { ScenePresence SP; - ((Scene)client.Scene).TryGetAvatar(client.AgentId, out SP); + ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out SP); List returns = new List(); if (SP.GodLevel != 0) { @@ -1597,9 +1597,9 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelFreezeUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) { ScenePresence targetAvatar = null; - ((Scene)client.Scene).TryGetAvatar(target, out targetAvatar); + ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar); ScenePresence parcelManager = null; - ((Scene)client.Scene).TryGetAvatar(client.AgentId, out parcelManager); + ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager); System.Threading.Timer Timer; if (targetAvatar.GodLevel == 0) @@ -1641,9 +1641,9 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelEjectUser(IClientAPI client, UUID parcelowner, uint flags, UUID target) { ScenePresence targetAvatar = null; - ((Scene)client.Scene).TryGetAvatar(target, out targetAvatar); + ((Scene)client.Scene).TryGetScenePresence(target, out targetAvatar); ScenePresence parcelManager = null; - ((Scene)client.Scene).TryGetAvatar(client.AgentId, out parcelManager); + ((Scene)client.Scene).TryGetScenePresence(client.AgentId, out parcelManager); //Just eject if (flags == 0) { diff --git a/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs b/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs deleted file mode 100644 index 72b0b38..0000000 --- a/OpenSim/Region/CoreModules/World/Meta7Windlight/Meta7WindlightModule.cs +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (c) Thomas Grimshaw and Magne Metaverse Research - * - * This module is not open source. All rights reserved. - * Unauthorised copying, distribution or public display is prohibited. - * - */ - -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; -using OpenMetaverse; -using log4net; -using Nini.Config; -using OpenSim.Data; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.Framework.InterfaceCommander; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - - -namespace OpenSim.Region.CoreModules.World.Meta7Windlight -{ - public class Meta7WindlightModule : IRegionModule, ICommandableModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private readonly Commander m_commander = new Commander("windlight"); - private Scene m_scene; - private static bool m_enableWindlight; - - #region ICommandableModule Members - - public ICommander CommandInterface - { - get { return m_commander; } - } - - #endregion - - #region IRegionModule Members - - public static bool EnableWindlight - { - get - { - return m_enableWindlight; - } - set - { - } - } - - public void Initialise(Scene scene, IConfigSource config) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; - - // ini file settings - try - { - m_enableWindlight = config.Configs["Meta7Windlight"].GetBoolean("enable_windlight", false); - } - catch (Exception) - { - m_log.Debug("[WINDLIGHT]: ini failure for enable_windlight - using default"); - } - - if (m_enableWindlight) - { - m_scene.EventManager.OnMakeRootAgent += EventManager_OnMakeRootAgent; - m_scene.EventManager.OnSaveNewWindlightProfile += EventManager_OnSaveNewWindlightProfile; - m_scene.EventManager.OnSendNewWindlightProfileTargeted += EventManager_OnSendNewWindlightProfileTargeted; - } - - InstallCommands(); - - m_log.Debug("[WINDLIGHT]: Initialised windlight module"); - } - - private List compileWindlightSettings(RegionMeta7WindlightData wl) - { - byte[] mBlock = new Byte[249]; - int pos = 0; - - wl.waterColor.ToBytes(mBlock, 0); pos += 12; - Utils.FloatToBytes(wl.waterFogDensityExponent).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.underwaterFogModifier).CopyTo(mBlock, pos); pos += 4; - wl.reflectionWaveletScale.ToBytes(mBlock, pos); pos += 12; - Utils.FloatToBytes(wl.fresnelScale).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.fresnelOffset).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.refractScaleAbove).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.refractScaleBelow).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.blurMultiplier).CopyTo(mBlock, pos); pos += 4; - wl.bigWaveDirection.ToBytes(mBlock, pos); pos += 8; - wl.littleWaveDirection.ToBytes(mBlock, pos); pos += 8; - wl.normalMapTexture.ToBytes(mBlock, pos); pos += 16; - wl.horizon.ToBytes(mBlock, pos); pos += 16; - Utils.FloatToBytes(wl.hazeHorizon).CopyTo(mBlock, pos); pos += 4; - wl.blueDensity.ToBytes(mBlock, pos); pos += 16; - Utils.FloatToBytes(wl.hazeDensity).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.densityMultiplier).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.distanceMultiplier).CopyTo(mBlock, pos); pos += 4; - wl.sunMoonColor.ToBytes(mBlock, pos); pos += 16; - Utils.FloatToBytes(wl.sunMoonPosition).CopyTo(mBlock, pos); pos += 4; - wl.ambient.ToBytes(mBlock, pos); pos += 16; - Utils.FloatToBytes(wl.eastAngle).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.sunGlowFocus).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.sunGlowSize).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.sceneGamma).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.starBrightness).CopyTo(mBlock, pos); pos += 4; - wl.cloudColor.ToBytes(mBlock, pos); pos += 16; - wl.cloudXYDensity.ToBytes(mBlock, pos); pos += 12; - Utils.FloatToBytes(wl.cloudCoverage).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.cloudScale).CopyTo(mBlock, pos); pos += 4; - wl.cloudDetailXYDensity.ToBytes(mBlock, pos); pos += 12; - Utils.FloatToBytes(wl.cloudScrollX).CopyTo(mBlock, pos); pos += 4; - Utils.FloatToBytes(wl.cloudScrollY).CopyTo(mBlock, pos); pos += 4; - Utils.UInt16ToBytes(wl.maxAltitude).CopyTo(mBlock, pos); pos += 2; - mBlock[pos] = Convert.ToByte(wl.cloudScrollXLock); pos++; - mBlock[pos] = Convert.ToByte(wl.cloudScrollYLock); pos++; - mBlock[pos] = Convert.ToByte(wl.drawClassicClouds); pos++; - List param = new List(); - param.Add(mBlock); - return param; - } - public void SendProfileToClient(ScenePresence presence) - { - IClientAPI client = presence.ControllingClient; - if (m_enableWindlight) - { - if (presence.IsChildAgent == false) - { - List param = compileWindlightSettings(m_scene.RegionInfo.WindlightSettings); - client.SendGenericMessage("Windlight", param); - } - } - else - { - //We probably don't want to spam chat with this.. probably - //m_log.Debug("[WINDLIGHT]: Module disabled"); - } - } - public void SendProfileToClient(ScenePresence presence, RegionMeta7WindlightData wl) - { - IClientAPI client = presence.ControllingClient; - if (m_enableWindlight) - { - if (presence.IsChildAgent == false) - { - List param = compileWindlightSettings(wl); - client.SendGenericMessage("Windlight", param); - } - } - else - { - //We probably don't want to spam chat with this.. probably - //m_log.Debug("[WINDLIGHT]: Module disabled"); - } - } - private void EventManager_OnMakeRootAgent(ScenePresence presence) - { - m_log.Debug("[WINDLIGHT]: Sending windlight scene to new client"); - SendProfileToClient(presence); - } - private void EventManager_OnSendNewWindlightProfileTargeted(RegionMeta7WindlightData wl, UUID pUUID) - { - ScenePresence Sc; - if (m_scene.TryGetAvatar(pUUID,out Sc)) - { - SendProfileToClient(Sc,wl); - } - } - private void EventManager_OnSaveNewWindlightProfile() - { - m_scene.ForEachScenePresence(SendProfileToClient); - } - - public void PostInitialise() - { - - } - - public void Close() - { - } - - public string Name - { - get { return "Meta7WindlightModule"; } - } - - public bool IsSharedModule - { - get { return false; } - } - - #endregion - - #region events - - #endregion - - #region ICommandableModule Members - - private void InstallCommands() - { - Command wlload = new Command("load", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleLoad, "Load windlight profile from the database and broadcast"); - Command wlenable = new Command("enable", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleEnable, "Enable the windlight plugin"); - Command wldisable = new Command("disable", CommandIntentions.COMMAND_NON_HAZARDOUS, HandleDisable, "Enable the windlight plugin"); - - m_commander.RegisterCommand("load", wlload); - m_commander.RegisterCommand("enable", wlenable); - m_commander.RegisterCommand("disable", wldisable); - - m_scene.RegisterModuleCommander(m_commander); - } - - private void HandleLoad(Object[] args) - { - if (!m_enableWindlight) - { - m_log.InfoFormat("[WINDLIGHT]: Cannot load windlight profile, module disabled. Use 'windlight enable' first."); - } - else - { - m_log.InfoFormat("[WINDLIGHT]: Loading Windlight profile from database"); - m_scene.LoadWindlightProfile(); - m_log.InfoFormat("[WINDLIGHT]: Load complete"); - } - } - - private void HandleDisable(Object[] args) - { - m_log.InfoFormat("[WINDLIGHT]: Plugin now disabled"); - m_enableWindlight=false; - } - - private void HandleEnable(Object[] args) - { - m_log.InfoFormat("[WINDLIGHT]: Plugin now enabled"); - m_enableWindlight = true; - } - - /// - /// Processes commandline input. Do not call directly. - /// - /// Commandline arguments - private void EventManager_OnPluginConsole(string[] args) - { - if (args[0] == "windlight") - { - if (args.Length == 1) - { - m_commander.ProcessConsoleCommand("add", new string[0]); - return; - } - - string[] tmpArgs = new string[args.Length - 2]; - int i; - for (i = 2; i < args.Length; i++) - { - tmpArgs[i - 2] = args[i]; - } - - m_commander.ProcessConsoleCommand(args[1], tmpArgs); - } - } - #endregion - - } -} - diff --git a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs index 7312799..3e8e196 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionDataStore.cs @@ -103,8 +103,8 @@ namespace OpenSim.Region.Framework.Interfaces void StoreRegionSettings(RegionSettings rs); RegionSettings LoadRegionSettings(UUID regionUUID); - RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID); - void StoreRegionWindlightSettings(RegionMeta7WindlightData wl); + RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID); + void StoreRegionWindlightSettings(RegionLightShareData wl); void Shutdown(); } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 37a51d9..ef125cd 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -207,7 +207,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnMakeRootAgentDelegate(ScenePresence presence); public delegate void OnSaveNewWindlightProfileDelegate(); - public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionMeta7WindlightData wl, UUID user); + public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); public event OnMakeRootAgentDelegate OnMakeRootAgent; public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; public event OnSaveNewWindlightProfileDelegate OnSaveNewWindlightProfile; @@ -1220,7 +1220,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public void TriggerOnSendNewWindlightProfileTargeted(RegionMeta7WindlightData wl, UUID user) + public void TriggerOnSendNewWindlightProfileTargeted(RegionLightShareData wl, UUID user) { OnSendNewWindlightProfileTargetedDelegate handlerSendNewWindlightProfileTargeted = OnSendNewWindlightProfileTargeted; if (handlerSendNewWindlightProfileTargeted != null) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2b6f80b..1f604c5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1729,7 +1729,7 @@ namespace OpenSim.Region.Framework.Scenes m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); } - public void StoreWindlightProfile(RegionMeta7WindlightData wl) + public void StoreWindlightProfile(RegionLightShareData wl) { m_regInfo.WindlightSettings = wl; m_storageManager.DataStore.StoreRegionWindlightSettings(wl); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 3895d93..7ed29a5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1370,21 +1370,20 @@ namespace OpenSim.Region.Framework.Scenes { // part.Inventory.RemoveScriptInstances(); - List avatars = Scene.GetScenePresences(); - for (int i = 0; i < avatars.Count; i++) + Scene.ForEachScenePresence(delegate (ScenePresence sp) { - if (avatars[i].ParentID == LocalId) + if (sp.ParentID == LocalId) { - avatars[i].StandUp(); + sp.StandUp(); } if (!silent) { part.UpdateFlag = 0; if (part == m_rootPart) - avatars[i].ControllingClient.SendKillObject(m_regionHandle, part.LocalId); + sp.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); } - } + }); } diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index 68035ca..8b2d387 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -101,13 +101,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests { throw new NotImplementedException(); } - public RegionMeta7WindlightData LoadRegionWindlightSettings(UUID regionUUID) + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) { //This connector doesn't support the windlight module yet //Return default LL windlight settings - return new RegionMeta7WindlightData(); + return new RegionLightShareData(); } - public void StoreRegionWindlightSettings(RegionMeta7WindlightData wl) + public void StoreRegionWindlightSettings(RegionLightShareData wl) { //This connector doesn't support the windlight module yet } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 99973b4..4e8a3c4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -7,7 +7,7 @@ using OpenMetaverse; using Nini.Config; using OpenSim; using OpenSim.Framework; -using OpenSim.Region.CoreModules.World.Meta7Windlight; +using OpenSim.Region.CoreModules.World.LightShare; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.ScriptEngine.Shared; @@ -97,7 +97,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_List(); } m_host.AddScriptLPS(1); - RegionMeta7WindlightData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; + RegionLightShareData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; LSL_List values = new LSL_List(); int idx = 0; @@ -229,11 +229,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return values; - } - - private RegionMeta7WindlightData getWindlightProfileFromRules(LSL_List rules) - { - RegionMeta7WindlightData wl = (RegionMeta7WindlightData)m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.Clone(); + } + + private RegionLightShareData getWindlightProfileFromRules(LSL_List rules) + { + RegionLightShareData wl = (RegionLightShareData)m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.Clone(); LSL_List values = new LSL_List(); int idx = 0; @@ -244,9 +244,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Types.Vector3 iV; switch (rule) { - case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: - idx++; - wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); + case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: + idx++; + wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); break; case (int)ScriptBaseClass.WL_AMBIENT: idx++; @@ -419,58 +419,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CMShoutError("Careminster functions are not enabled."); return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - CMShoutError("cmSetWindlightScene can only be used by estate managers or owners."); - return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + CMShoutError("cmSetWindlightScene can only be used by estate managers or owners."); + return 0; } int success = 0; - m_host.AddScriptLPS(1); - if (Meta7WindlightModule.EnableWindlight) - { - RegionMeta7WindlightData wl = getWindlightProfileFromRules(rules); - m_host.ParentGroup.Scene.StoreWindlightProfile(wl); - success = 1; - } - else - { - CMShoutError("Windlight module is disabled"); - return 0; + m_host.AddScriptLPS(1); + if (LightShareModule.EnableWindlight) + { + RegionLightShareData wl = getWindlightProfileFromRules(rules); + m_host.ParentGroup.Scene.StoreWindlightProfile(wl); + success = 1; + } + else + { + CMShoutError("Windlight module is disabled"); + return 0; + } + return success; + } + /// + /// Set the current Windlight scene to a target avatar + /// + /// + /// success: true or false + public int cmSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) + { + if (!m_CMFunctionsEnabled) + { + CMShoutError("Careminster functions are not enabled."); + return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + CMShoutError("cmSetWindlightSceneTargeted can only be used by estate managers or owners."); + return 0; + } + int success = 0; + m_host.AddScriptLPS(1); + if (LightShareModule.EnableWindlight) + { + RegionLightShareData wl = getWindlightProfileFromRules(rules); + World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); + success = 1; + } + else + { + CMShoutError("Windlight module is disabled"); + return 0; } return success; - } - /// - /// Set the current Windlight scene to a target avatar - /// - /// - /// success: true or false - public int cmSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) - { - if (!m_CMFunctionsEnabled) - { - CMShoutError("Careminster functions are not enabled."); - return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - CMShoutError("cmSetWindlightSceneTargeted can only be used by estate managers or owners."); - return 0; - } - int success = 0; - m_host.AddScriptLPS(1); - if (Meta7WindlightModule.EnableWindlight) - { - RegionMeta7WindlightData wl = getWindlightProfileFromRules(rules); - World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); - success = 1; - } - else - { - CMShoutError("Windlight module is disabled"); - return 0; - } - return success; } } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index d660f36..9b0c09b 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -771,7 +771,7 @@ ; default is 1000 cloud_update_rate = 1000 -[Meta7Windlight] +[LightShare] ; This enables the transmission of Windlight scenes to supporting clients, such as the Meta7 viewer. ; It has no ill effect on viewers which do not support server-side windlight settings. -- cgit v1.1 From 956225f0e1a3441e47a74b8882cc975f626e8b36 Mon Sep 17 00:00:00 2001 From: lcc Date: Sun, 4 Apr 2010 18:29:18 +0200 Subject: Fixed Ban and parcel exclusion. Need to fix the parcel chat too --- OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 6c9830c..8039558 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -390,7 +390,7 @@ namespace OpenSim.Region.CoreModules.World.Land { if (avatar.AbsolutePosition.Z < LandChannel.BAN_LINE_SAFETY_HIEGHT) { - if (parcelAvatarIsEntering.IsBannedFromLand(avatar.UUID)) + if (parcelAvatarIsEntering.IsEitherBannedOrRestricted(avatar.UUID)) { MoveUserOutOfParcel(avatar); } -- cgit v1.1 From e2a521742a737aa54e43dd934c0a0d5f2e380e8f Mon Sep 17 00:00:00 2001 From: kitto Date: Sun, 4 Apr 2010 22:57:32 -0400 Subject: ChODE Only: Corrected Heightmap load to iliminate crack at 255M. Added 'fence' option to prevent physical objects crossing region border. --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 202 +++++++++++++----------- OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs | 111 ++++++------- 2 files changed, 157 insertions(+), 156 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index e8894f7..67f8af5 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -180,6 +180,7 @@ namespace OpenSim.Region.Physics.OdePlugin internal int m_material = (int)Material.Wood; private int frcount = 0; // Used to limit dynamics debug output to + private int revcount = 0; // Reverse motion while > 0 private IntPtr m_body = IntPtr.Zero; @@ -1888,22 +1889,19 @@ namespace OpenSim.Region.Physics.OdePlugin public void changemove(float timestep) { -//Console.WriteLine("changemove for {0}", m_primName ); - +//Console.WriteLine("changemove sing/root {0} to {1}", m_primName, _position ); if (m_isphysical) { //Console.WriteLine("phys {0} {1} {2}", m_disabled, m_taintremove, childPrim); // if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits! if (!m_taintremove && !childPrim) { -//Console.WriteLine("physOK"); if (Body == IntPtr.Zero) enableBody(); //Prim auto disable after 20 frames, //if you move it, re-enable the prim manually. if (_parent != null) { -//Console.WriteLine("physChild"); if (m_linkJoint != IntPtr.Zero) { d.JointDestroy(m_linkJoint); @@ -1912,7 +1910,6 @@ namespace OpenSim.Region.Physics.OdePlugin } if (Body != IntPtr.Zero) { -//Console.WriteLine("physNotIPZ"); d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); if (_parent != null) @@ -1945,7 +1942,6 @@ Console.WriteLine(" JointCreateFixed"); } else { -//Console.WriteLine("NONphys"); // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); _parent_scene.waitForSpaceUnlock(m_targetSpace); @@ -2382,9 +2378,7 @@ Console.WriteLine(" JointCreateFixed"); if (IsPhysical) { if (Body != IntPtr.Zero) - { d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); - } } //resetCollisionAccounting(); @@ -2394,31 +2388,9 @@ Console.WriteLine(" JointCreateFixed"); public void UpdatePositionAndVelocity() { - return; // moved to the Move() method - } -/* No one uses this? - public Matrix4 FromDMass(d.Mass pMass) - { - Matrix4 obj; - obj.M11 = pMass.I.M00; - obj.M12 = pMass.I.M01; - obj.M13 = pMass.I.M02; - obj.M14 = 0; - obj.M21 = pMass.I.M10; - obj.M22 = pMass.I.M11; - obj.M23 = pMass.I.M12; - obj.M24 = 0; - obj.M31 = pMass.I.M20; - obj.M32 = pMass.I.M21; - obj.M33 = pMass.I.M22; - obj.M34 = 0; - obj.M41 = 0; - obj.M42 = 0; - obj.M43 = 0; - obj.M44 = 1; - return obj; + return; // moved to the Move () method } -*/ + public d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj) { obj.I.M00 = pMat[0, 0]; @@ -2996,44 +2968,114 @@ Console.WriteLine(" JointCreateFixed"); float fx = 0; float fy = 0; float fz = 0; + Vector3 linvel; // velocity applied, including any reversal + int outside = 0; + + // If geomCrossingFailuresBeforeOutofbounds is set to 0 in OpenSim.ini then phys objects bounce off region borders. + // This is a temp patch until proper region crossing is developed. + + int failureLimit = _parent_scene.geomCrossingFailuresBeforeOutofbounds; + int fence = _parent_scene.geomRegionFence; + + float border_limit = 0.05f; // original limit + if (fence == 1) border_limit = 0.5f; // bounce point frcount++; // used to limit debug comment output if (frcount > 100) frcount = 0; - if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. + if(revcount > 0) revcount--; + + if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // Only move root prims. { - -// Old public void UpdatePositionAndVelocity(), more accuratley calculated here + // Old public void UpdatePositionAndVelocity(), more accuratley calculated here bool lastZeroFlag = _zeroFlag; // was it stopped + d.Vector3 vec = d.BodyGetPosition(Body); - d.Quaternion ori = d.BodyGetQuaternion(Body); - d.Vector3 vel = d.BodyGetLinearVel(Body); - // d.Vector3 rotvel = d.BodyGetAngularVel(Body); - d.Vector3 torque = d.BodyGetTorque(Body); - _torque = new Vector3(torque.X, torque.Y, torque.Z); Vector3 l_position = Vector3.Zero; - Quaternion l_orientation = Quaternion.Identity; - - m_lastposition = _position; - m_lastorientation = _orientation; - l_position.X = vec.X; l_position.Y = vec.Y; l_position.Z = vec.Z; - l_orientation.X = ori.X; - l_orientation.Y = ori.Y; - l_orientation.Z = ori.Z; - l_orientation.W = ori.W; + m_lastposition = _position; + _position = l_position; + + d.Quaternion ori = d.BodyGetQuaternion(Body); + // Quaternion l_orientation = Quaternion.Identity; + _orientation.X = ori.X; + _orientation.Y = ori.Y; + _orientation.Z = ori.Z; + _orientation.W = ori.W; + m_lastorientation = _orientation; + + d.Vector3 vel = d.BodyGetLinearVel(Body); + m_lastVelocity = _velocity; + _velocity.X = vel.X; + _velocity.Y = vel.Y; + _velocity.Z = vel.Z; + _acceleration = ((_velocity - m_lastVelocity) / timestep); + + d.Vector3 torque = d.BodyGetTorque(Body); + _torque = new Vector3(torque.X, torque.Y, torque.Z); + + base.RequestPhysicsterseUpdate(); + //Console.WriteLine("Move {0} at {1}", m_primName, l_position); - // Check if outside region horizontally - if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || - l_position.X < 0f || - l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || - l_position.Y < 0f) + // Check if outside region + // In Scene.cs/CrossPrimGroupIntoNewRegion the object is checked for 0.1M from border! + if (l_position.X > ((float)_parent_scene.WorldExtents.X - border_limit)) + { + l_position.X = ((float)_parent_scene.WorldExtents.X - border_limit); + outside = 1; + } + + if (l_position.X < border_limit) + { + l_position.X = border_limit; + outside = 2; + } + if (l_position.Y > ((float)_parent_scene.WorldExtents.Y - border_limit)) + { + l_position.Y = ((float)_parent_scene.WorldExtents.Y - border_limit); + outside = 3; + } + + if (l_position.Y < border_limit) + { + l_position.Y = border_limit; + outside = 4; + } + + if (outside > 0) { - if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds) +//Console.WriteLine(" fence = {0}",fence); + +//Console.WriteLine("Border {0}", l_position); + if (fence == 1) // bounce object off boundary + { + if (revcount == 0) + { + if (outside < 3) + { + _velocity.X = -_velocity.X; + } + else + { + _velocity.Y = -_velocity.Y; + } + if (m_type != Vehicle.TYPE_NONE) Halt(); + _position = l_position; + m_taintposition = _position; + m_lastVelocity = _velocity; + _acceleration = Vector3.Zero; + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); + base.RequestPhysicsterseUpdate(); + + revcount = 25; // wait for object to move away from border + } + } // else old crossing mode + else if (m_crossingfailures < failureLimit) { // keep trying to cross? _position = l_position; //_parent_scene.remActivePrim(this); @@ -3043,9 +3085,12 @@ Console.WriteLine(" JointCreateFixed"); else { // Too many tries if (_parent == null) base.RaiseOutOfBounds(l_position); +//Console.WriteLine("ROOB 2"); + return; // Dont process any other motion? - } + } // end various methods } // end outside region horizontally + if (l_position.Z < 0) { @@ -3057,6 +3102,8 @@ Console.WriteLine(" JointCreateFixed"); //IsPhysical = false; if (_parent == null) base.RaiseOutOfBounds(_position); +//Console.WriteLine("ROOB 3"); + _acceleration.X = 0; // This stuff may stop client display but it has no _acceleration.Y = 0; // effect on the object in phys engine! @@ -3081,10 +3128,9 @@ Console.WriteLine(" JointCreateFixed"); if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) - && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large + && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, _orientation)) < 0.0001)) // KF 0.01 is far to large { _zeroFlag = true; -//Console.WriteLine("ZFT 2"); m_throttleUpdates = false; } else @@ -3104,10 +3150,7 @@ Console.WriteLine(" JointCreateFixed"); _acceleration.X = 0; _acceleration.Y = 0; _acceleration.Z = 0; - //_orientation.w = 0f; - //_orientation.X = 0f; - //_orientation.Y = 0f; - //_orientation.Z = 0f; + m_rotationalVelocity.X = 0; m_rotationalVelocity.Y = 0; m_rotationalVelocity.Z = 0; @@ -3132,26 +3175,6 @@ Console.WriteLine(" JointCreateFixed"); base.RequestPhysicsterseUpdate(); } } - - m_lastVelocity = _velocity; - - _position = l_position; - - _velocity.X = vel.X; - _velocity.Y = vel.Y; - _velocity.Z = vel.Z; -// Why 2 calcs??? -// _acceleration = ((_velocity - m_lastVelocity) / 0.1f); -// _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, -// _velocity.Y - m_lastVelocity.Y / 0.1f, -// _velocity.Z - m_lastVelocity.Z / 0.1f); - - _acceleration = ((_velocity - m_lastVelocity) / timestep); - - _orientation.X = ori.X; - _orientation.Y = ori.Y; - _orientation.Z = ori.Z; - _orientation.W = ori.W; m_lastUpdateSent = false; if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) { @@ -3167,11 +3190,8 @@ Console.WriteLine(" JointCreateFixed"); } m_lastposition = l_position; - /// End of old UpdatePositionAndVelocity insert + /// End UpdatePositionAndVelocity insert -//if (!Acceleration.ApproxEquals(Vector3.Zero, 0.01f)) Console.WriteLine("Move " + m_primName + " Accel=" + Acceleration); -// if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_type + -// " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); if (m_type != Vehicle.TYPE_NONE) { // get body attitude @@ -3299,11 +3319,12 @@ Console.WriteLine(" JointCreateFixed"); { // not hovering, Gravity rules m_wLinObjectVel.Z = vel_now.Z; } - - + linvel = m_wLinObjectVel; + // Vehicle Linear Motion done ======================================= // Apply velocity - d.BodySetLinearVel(Body, m_wLinObjectVel.X, m_wLinObjectVel.Y, m_wLinObjectVel.Z); +//if(frcount == 0) Console.WriteLine("LV {0}", linvel); + d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z); // apply gravity force d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); //if(frcount == 0) Console.WriteLine("Grav {0}", grav); @@ -3626,9 +3647,10 @@ Console.WriteLine(" JointCreateFixed"); // react to the physics scene by moving it's position. // Avatar to Avatar collisions // Prim to avatar collisions + d.Vector3 dlinvel = vel; d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); - d.BodySetLinearVel(Body, vel.X, vel.Y, 0); + d.BodySetLinearVel(Body, dlinvel.X, dlinvel.Y, dlinvel.Z); d.BodyAddForce(Body, 0, 0, fz); //KF this prevents furthur motions return; } diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs index deb6164..79e2986 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs @@ -224,6 +224,7 @@ namespace OpenSim.Region.Physics.OdePlugin public float bodyPIDG = 25; public int geomCrossingFailuresBeforeOutofbounds = 5; + public int geomRegionFence = 0; public float bodyMotorJointMaxforceTensor = 2; @@ -447,6 +448,7 @@ namespace OpenSim.Region.Physics.OdePlugin geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3); geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); + geomRegionFence = physicsconfig.GetInt("region_border_fence", 0); geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f); bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20); @@ -3419,76 +3421,56 @@ namespace OpenSim.Region.Physics.OdePlugin public void SetTerrain(float[] heightMap, Vector3 pOffset) { - // this._heightmap[i] = (double)heightMap[i]; - // dbm (danx0r) -- creating a buffer zone of one extra sample all around - //_origheightmap = heightMap; + uint regionsize = (uint) Constants.RegionSize; // visible region size eg. 256(M) + + uint heightmapWidth = regionsize + 1; // ODE map size 257 x 257 (Meters) (1 extra + uint heightmapHeight = regionsize + 1; + + uint heightmapWidthSamples = (uint)regionsize + 2; // Sample file size, 258 x 258 samples + uint heightmapHeightSamples = (uint)regionsize + 2; + + // Array of height samples for ODE float[] _heightmap; + _heightmap = new float[(heightmapWidthSamples * heightmapHeightSamples)]; // loaded samples 258 x 258 - // zero out a heightmap array float array (single dimension [flattened])) - //if ((int)Constants.RegionSize == 256) - // _heightmap = new float[514 * 514]; - //else - - _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))]; - - uint heightmapWidth = Constants.RegionSize + 1; - uint heightmapHeight = Constants.RegionSize + 1; - - uint heightmapWidthSamples; - - uint heightmapHeightSamples; - - //if (((int)Constants.RegionSize) == 256) - //{ - // heightmapWidthSamples = 2 * (uint)Constants.RegionSize + 2; - // heightmapHeightSamples = 2 * (uint)Constants.RegionSize + 2; - // heightmapWidth++; - // heightmapHeight++; - //} - //else - //{ - - heightmapWidthSamples = (uint)Constants.RegionSize + 1; - heightmapHeightSamples = (uint)Constants.RegionSize + 1; - //} - + // Other ODE parameters const float scale = 1.0f; const float offset = 0.0f; - const float thickness = 0.2f; + const float thickness = 2.0f; // Was 0.2f, Larger appears to prevent Av fall-through const int wrap = 0; - int regionsize = (int) Constants.RegionSize + 2; - //Double resolution - //if (((int)Constants.RegionSize) == 256) - // heightMap = ResizeTerrain512Interpolation(heightMap); - - - // if (((int)Constants.RegionSize) == 256 && (int)Constants.RegionSize == 256) - // regionsize = 512; - - float hfmin = 2000; - float hfmax = -2000; + float hfmin = 2000f; + float hfmax = -2000f; + float minele = 0.0f; // Dont allow -ve heights - for (int x = 0; x < heightmapWidthSamples; x++) + uint x = 0; + uint y = 0; + uint xx = 0; + uint yy = 0; + + // load the height samples array from the heightMap + for ( x = 0; x < heightmapWidthSamples; x++) // 0 to 257 + { + for ( y = 0; y < heightmapHeightSamples; y++) // 0 to 257 { - for (int y = 0; y < heightmapHeightSamples; y++) - { - int xx = Util.Clip(x - 1, 0, regionsize - 1); - int yy = Util.Clip(y - 1, 0, regionsize - 1); - - - float val= heightMap[yy * (int)Constants.RegionSize + xx]; - _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val; - - hfmin = (val < hfmin) ? val : hfmin; - hfmax = (val > hfmax) ? val : hfmax; - } + xx = x - 1; + if (xx < 0) xx = 0; + if (xx > (regionsize - 1)) xx = regionsize - 1; + + yy = y - 1; + if (yy < 0) yy = 0; + if (yy > (regionsize - 1)) yy = regionsize - 1; + // Input xx = 0 0 1 2 ..... 254 255 255 256 total in + // Output x = 0 1 2 3 ..... 255 256 257 258 total out + float val= heightMap[(yy * regionsize) + xx]; // input from heightMap, <0-255 * 256> <0-255> + if (val < minele) val = minele; + _heightmap[x * (regionsize + 2) + y] = val; // samples output to _heightmap, <0-257 * 258> <0-257> + hfmin = (val < hfmin) ? val : hfmin; + hfmax = (val > hfmax) ? val : hfmax; } + } - - - lock (OdeLock) { IntPtr GroundGeom = IntPtr.Zero; @@ -3504,19 +3486,17 @@ namespace OpenSim.Region.Physics.OdePlugin d.SpaceRemove(space, GroundGeom); d.GeomDestroy(GroundGeom); } - } IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); - d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth + 1, heightmapHeight + 1, - (int)heightmapWidthSamples + 1, (int)heightmapHeightSamples + 1, scale, - offset, thickness, wrap); + d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, + heightmapWidth, heightmapHeight, (int)heightmapWidthSamples, + (int)heightmapHeightSamples, scale, offset, thickness, wrap); d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); GroundGeom = d.CreateHeightfield(space, HeightmapData, 1); if (GroundGeom != IntPtr.Zero) { d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); - } geom_name_map[GroundGeom] = "Terrain"; @@ -3534,7 +3514,7 @@ namespace OpenSim.Region.Physics.OdePlugin d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); d.GeomSetRotation(GroundGeom, ref R); - d.GeomSetPosition(GroundGeom, (pOffset.X + ((int)Constants.RegionSize * 0.5f)) - 1, (pOffset.Y + ((int)Constants.RegionSize * 0.5f)) - 1, 0); + d.GeomSetPosition(GroundGeom, (pOffset.X + (regionsize * 0.5f)) - 0.5f, (pOffset.Y + (regionsize * 0.5f)) - 0.5f, 0); IntPtr testGround = IntPtr.Zero; if (RegionTerrain.TryGetValue(pOffset, out testGround)) { @@ -3542,7 +3522,6 @@ namespace OpenSim.Region.Physics.OdePlugin } RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); TerrainHeightFieldHeights.Add(GroundGeom,_heightmap); - } } -- cgit v1.1 From 2fbbc13c71052e66269035031e894b736e2ead5d Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 5 Apr 2010 19:42:15 +0100 Subject: Fix some overlooked merge conflicts that got committed --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5951a92..0785f7f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2203,13 +2203,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForTerseUpdate() { -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs lockPartsForRead(true); -======= -// m_log.DebugFormat("[SOG]: Scheduling terse update for {0} {1}", Name, UUID); - - lock (m_parts) ->>>>>>> 0.6.9-post-fixes:OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs { foreach (SceneObjectPart part in m_parts.Values) { @@ -3765,15 +3759,11 @@ namespace OpenSim.Region.Framework.Scenes HasGroupChanged = true; } -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs lockPartsForRead(false); - ScheduleGroupForFullUpdate(); -======= // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled // for the same object with very different properties. The caller must schedule the update. //ScheduleGroupForFullUpdate(); ->>>>>>> 0.6.9-post-fixes:OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs } public void TriggerScriptChangedEvent(Changed val) -- cgit v1.1 From f34cc6b46949033803c79235b9d82da9bf9634dd Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Mon, 5 Apr 2010 22:08:34 +0200 Subject: Add a much cheaper agent count retrieval method. This is obsoleted by 0.7 so it can be reverted then. --- OpenSim/ApplicationPlugins/Rest/Regions/GETHandler.cs | 2 +- .../ApplicationPlugins/Rest/Regions/GETRegionInfoHandler.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 10 +++++++++- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/OpenSim/ApplicationPlugins/Rest/Regions/GETHandler.cs b/OpenSim/ApplicationPlugins/Rest/Regions/GETHandler.cs index ed18207..dea166d 100644 --- a/OpenSim/ApplicationPlugins/Rest/Regions/GETHandler.cs +++ b/OpenSim/ApplicationPlugins/Rest/Regions/GETHandler.cs @@ -192,7 +192,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Regions protected string RegionStats(OSHttpResponse httpResponse, Scene scene) { - int users = scene.GetAvatars().Count; + int users = scene.GetRootAgentCount(); int objects = scene.Entities.Count - users; RestXmlWriter rxw = new RestXmlWriter(new StringWriter()); diff --git a/OpenSim/ApplicationPlugins/Rest/Regions/GETRegionInfoHandler.cs b/OpenSim/ApplicationPlugins/Rest/Regions/GETRegionInfoHandler.cs index 5798286..82e9d9b 100644 --- a/OpenSim/ApplicationPlugins/Rest/Regions/GETRegionInfoHandler.cs +++ b/OpenSim/ApplicationPlugins/Rest/Regions/GETRegionInfoHandler.cs @@ -125,7 +125,7 @@ namespace OpenSim.ApplicationPlugins.Rest.Regions rxw.WriteString(s.RegionInfo.InternalEndPoint.ToString()); rxw.WriteEndAttribute(); - int users = s.GetAvatars().Count; + int users = s.GetRootAgentCount(); rxw.WriteStartAttribute(String.Empty, "avatars", String.Empty); rxw.WriteValue(users); rxw.WriteEndAttribute(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ab0d397..e5e6fc9 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1523,7 +1523,7 @@ namespace OpenSim.Region.Framework.Scenes public void SaveTerrain() { m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); - } + } public void StoreWindlightProfile(RegionMeta7WindlightData wl) { @@ -4339,6 +4339,14 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Cheaply return the number of avatars in a region (without fetching a list object) + /// + public int GetRootAgentCount() + { + return m_sceneGraph.GetRootAgentCount(); + } + + /// /// Return a list of all ScenePresences in this region. This returns child agents as well as root agents. /// This list is a new object, so it can be iterated over without locking. /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 10ebf67..a76f386 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5266,7 +5266,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llGetRegionAgentCount() { m_host.AddScriptLPS(1); - return new LSL_Integer(World.GetAvatars().Count); + return new LSL_Integer(World.GetRootAgentCount()); } public LSL_Vector llGetRegionCorner() -- cgit v1.1 From 7a3bb266ebc057a1af589fc642bfeca08de72c98 Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Mon, 5 Apr 2010 22:11:05 +0200 Subject: This commit adds some randomness to object persistence. It's a Work In Progress, I am working on improving this to a tiered approach. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 46 ++++++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5443c28..9a205e0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -104,8 +104,12 @@ namespace OpenSim.Region.Framework.Scenes /// since the group's last persistent backup /// private bool m_hasGroupChanged = false; - private long timeFirstChanged; - private long timeLastChanged; + private long timeFirstChanged = 0; + private long timeLastChanged = 0; + long m_maxPersistTime = 0; + long m_minPersistTime = 0; + Random m_rand; + private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); public void lockPartsForRead(bool locked) @@ -182,6 +186,28 @@ namespace OpenSim.Region.Framework.Scenes timeLastChanged = DateTime.Now.Ticks; if (!m_hasGroupChanged) timeFirstChanged = DateTime.Now.Ticks; + if (m_rand == null) + { + byte[] val = new byte[16]; + m_rootPart.UUID.ToBytes(val, 0); + m_rand = new Random(BitConverter.ToInt32(val, 0)); + } + if (Scene.GetRootAgentCount() == 0) + { + //If the region is empty, this change has been made by an automated process + //and thus we delay the persist time by a random amount between 1.5 and 2.5. + + float factor = 1.5f + (float)(m_rand.NextDouble()); + m_maxPersistTime = (long)((float)Scene.m_persistAfter * factor); + m_minPersistTime = (long)((float)Scene.m_dontPersistBefore * factor); + } + else + { + //If the region is not empty, we want to obey the minimum and maximum persist times + //but add a random factor so we stagger the object persistance a little + m_maxPersistTime = (long)((float)Scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 + m_minPersistTime = (long)((float)Scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 + } } m_hasGroupChanged = value; } @@ -197,8 +223,19 @@ namespace OpenSim.Region.Framework.Scenes return false; if (m_scene.ShuttingDown) return true; + + if (m_minPersistTime == 0 || m_maxPersistTime == 0) + { + m_maxPersistTime = m_scene.m_persistAfter; + m_minPersistTime = m_scene.m_dontPersistBefore; + } + long currentTime = DateTime.Now.Ticks; - if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) + + if (timeLastChanged == 0) timeLastChanged = currentTime; + if (timeFirstChanged == 0) timeFirstChanged = currentTime; + + if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime) return true; return false; } @@ -529,6 +566,7 @@ namespace OpenSim.Region.Framework.Scenes /// public SceneObjectGroup() { + } /// @@ -545,7 +583,7 @@ namespace OpenSim.Region.Framework.Scenes /// Constructor. This object is added to the scene later via AttachToScene() /// public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) - { + { SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); } -- cgit v1.1 From 5c04d768a69814324521181f37c7da87ba2b4819 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 5 Apr 2010 22:26:18 +0200 Subject: Bump version number --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 58d65d1..d7c2ed0 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,7 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.6.8CM"; + private const string VERSION_NUMBER = "0.6.9CM"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour -- cgit v1.1 From a573b5767b42766a6782d549b22cc53f079ecc14 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 5 Apr 2010 22:31:30 +0200 Subject: Test commit --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index d7c2ed0..cf417d7 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -33,7 +33,7 @@ namespace OpenSim private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour - { + { Unknown, Dev, RC1, -- cgit v1.1 From 2f454843d82ce0253af393817cf6f0ebb9046112 Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Mon, 5 Apr 2010 23:17:06 +0200 Subject: Fix up my own shoddy code! Fixes prim rez break. Whups! --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 48 ++++++++++++---------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 0277ed8..13d1d4e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -106,9 +106,9 @@ namespace OpenSim.Region.Framework.Scenes private bool m_hasGroupChanged = false; private long timeFirstChanged = 0; private long timeLastChanged = 0; - long m_maxPersistTime = 0; - long m_minPersistTime = 0; - Random m_rand; + private long m_maxPersistTime = 0; + private long m_minPersistTime = 0; + private Random m_rand; private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); @@ -186,27 +186,31 @@ namespace OpenSim.Region.Framework.Scenes timeLastChanged = DateTime.Now.Ticks; if (!m_hasGroupChanged) timeFirstChanged = DateTime.Now.Ticks; - if (m_rand == null) + if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null) { - byte[] val = new byte[16]; - m_rootPart.UUID.ToBytes(val, 0); - m_rand = new Random(BitConverter.ToInt32(val, 0)); - } - if (Scene.GetRootAgentCount() == 0) - { - //If the region is empty, this change has been made by an automated process - //and thus we delay the persist time by a random amount between 1.5 and 2.5. + if (m_rand == null) + { + byte[] val = new byte[16]; + m_rootPart.UUID.ToBytes(val, 0); + m_rand = new Random(BitConverter.ToInt32(val, 0)); + } + + if (m_scene.GetRootAgentCount() == 0) + { + //If the region is empty, this change has been made by an automated process + //and thus we delay the persist time by a random amount between 1.5 and 2.5. - float factor = 1.5f + (float)(m_rand.NextDouble()); - m_maxPersistTime = (long)((float)Scene.m_persistAfter * factor); - m_minPersistTime = (long)((float)Scene.m_dontPersistBefore * factor); - } - else - { - //If the region is not empty, we want to obey the minimum and maximum persist times - //but add a random factor so we stagger the object persistance a little - m_maxPersistTime = (long)((float)Scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 - m_minPersistTime = (long)((float)Scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 + float factor = 1.5f + (float)(m_rand.NextDouble()); + m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor); + m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor); + } + else + { + //If the region is not empty, we want to obey the minimum and maximum persist times + //but add a random factor so we stagger the object persistance a little + m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 + m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 + } } } m_hasGroupChanged = value; -- cgit v1.1 From e7be131b8990e5397e13c5049caaafde4c0c447c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 5 Apr 2010 23:20:56 +0200 Subject: Add the ISnmpModule interface definition to Careminster release --- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 OpenSim/Region/Framework/Interfaces/ISnmpModule.cs diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs new file mode 100644 index 0000000..9790fc7 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -0,0 +1,11 @@ +/////////////////////////////////////////////////////////////////// +// +// (c) Careminster LImited, Melanie Thielker and the Meta7 Team +// +// This file is not open source. All rights reserved +// +public interface ISnmpModule +{ + void Alert(string message); + void Trap(string message); +} -- cgit v1.1 From 335c1b44206531bc6c0996157884d6873a580527 Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Wed, 7 Apr 2010 07:48:26 +0200 Subject: Implement PSYS_SRC_INNERANGLE and PSYS_SRC_OUTERANGLE --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a76f386..5be8929 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6195,6 +6195,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api tempf = (float)rules.GetLSLFloatItem(i + 1); prules.OuterAngle = (float)tempf; break; + + case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: + tempf = (float)rules.GetLSLFloatItem(i + 1); + prules.InnerAngle = (float)tempf; + break; + + case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: + tempf = (float)rules.GetLSLFloatItem(i + 1); + prules.OuterAngle = (float)tempf; + break; } } -- cgit v1.1 From 20e3de1f0a1434d51cf833b6418e983101438568 Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Wed, 7 Apr 2010 08:28:57 +0200 Subject: Add CHANGED_REGION_START (alias for CHANGED_REGION_RESTART as per LL Jira SVC-3773) --- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index ee35fa4..b3e4740 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -274,6 +274,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int CHANGED_ALLOWED_DROP = 64; public const int CHANGED_OWNER = 128; public const int CHANGED_REGION_RESTART = 256; + public const int CHANGED_REGION_START = 256; //LL Changed the constant from CHANGED_REGION_RESTART public const int CHANGED_REGION = 512; public const int CHANGED_TELEPORT = 1024; public const int CHANGED_ANIMATION = 16384; -- cgit v1.1 From db5ea850f66308038b16c4adcabd9e0d529ec947 Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Wed, 7 Apr 2010 09:49:11 +0200 Subject: Fix llLookAt so that it doesn't "roll" the object and more closely imitates the behaviour in SL. ( http://bugs.meta7.com/view.php?id=28 ) --- .../Shared/Api/Implementation/LSL_Api.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5be8929..75dd615 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2881,6 +2881,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llLookAt(LSL_Vector target, double strength, double damping) { + /* m_host.AddScriptLPS(1); // Determine where we are looking from LSL_Vector from = llGetPos(); @@ -2900,12 +2901,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // the angles of rotation in radians into rotation value LSL_Types.Quaternion rot = llEuler2Rot(angle); - /* - Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); - m_host.startLookAt(rotation, (float)damping, (float)strength); - This would only work if your physics system contains an APID controller */ + + // This would only work if your physics system contains an APID controller: + // Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); + // m_host.startLookAt(rotation, (float)damping, (float)strength); + // Orient the object to the angle calculated llSetRot(rot); + */ + + //The above code, while nice, doesn't replicate the behaviour of SL and tends to "roll" the object. + //There's probably a smarter way of doing this, my rotation math-fu is weak. + // http://bugs.meta7.com/view.php?id=28 + // - Tom + + LSL_Rotation newrot = llGetRot() * llRotBetween(new LSL_Vector(1.0d, 0.0d, 0.0d) * llGetRot(), new LSL_Vector(0.0d, 0.0d, -1.0d)); + llSetRot(newrot * llRotBetween(new LSL_Vector(0.0d,0.0d,1.0d) * newrot, target - llGetPos())); + } public void llRotLookAt(LSL_Rotation target, double strength, double damping) -- cgit v1.1 From 309f440fc04cc965e31232947bed698864308356 Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Wed, 7 Apr 2010 10:13:47 +0200 Subject: Fix llDialog responses so that they can be heard throughout the region. This now conforms to the behaviour in SL. ( http://bugs.meta7.com/view.php?id=13 ) --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index ebcdd62..b0e3655 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -5200,7 +5200,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP args.Channel = ch; args.From = String.Empty; args.Message = Utils.BytesToString(msg); - args.Type = ChatTypeEnum.Shout; + args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance args.Position = new Vector3(); args.Scene = Scene; args.Sender = this; -- cgit v1.1 From e80e04c5fd3892cf3c988baaa00aa8ccfa330256 Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Wed, 7 Apr 2010 22:59:13 +0200 Subject: Increase the amount of time we wait for a teleport to complete. This allows teleportation to a remote region without a local connection to the asset server without timing out. --- OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 5f84252..04626d3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -1032,7 +1032,7 @@ namespace OpenSim.Region.Framework.Scenes public bool WaitForCallback(UUID id) { - int count = 200; + int count = 400; while (m_agentsInTransit.Contains(id) && count-- > 0) { //m_log.Debug(" >>> Waiting... " + count); -- cgit v1.1 From d834a2c3da1aa97887e087e5a265e73a914c5f7b Mon Sep 17 00:00:00 2001 From: Thomas Grimshaw Date: Wed, 7 Apr 2010 23:53:08 +0200 Subject: Implement cmGetAvatarList(). This returns a strided list of all avatars in the region, including their UUID, position and name. The radar is often the most taxing scripts on a sim, this function can help radars reduce their impact by 66% by eliminating the need for sensors. --- .../Shared/Api/Implementation/CM_Api.cs | 130 ++++++++++++--------- .../ScriptEngine/Shared/Api/Interface/ICM_Api.cs | 3 +- .../ScriptEngine/Shared/Api/Runtime/CM_Stub.cs | 14 ++- 3 files changed, 87 insertions(+), 60 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 99973b4..9f829da 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -86,6 +86,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// + /// Like osGetAgents but returns enough info for a radar + /// + /// Strided list of the UUID, position and name of each avatar in the region + public LSL_List cmGetAvatarList() + { + LSL_List result = new LSL_List(); + foreach (ScenePresence avatar in World.GetAvatars()) + { + if (avatar.UUID != m_host.OwnerID) + { + if (avatar.IsChildAgent == false) + { + result.Add(avatar.UUID); + result.Add(avatar.PhysicsActor.Position); + result.Add(avatar.Name); + } + } + } + return result; + } + + /// /// Get the current Windlight scene /// /// List of windlight parameters @@ -229,10 +251,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return values; - } - + } + private RegionMeta7WindlightData getWindlightProfileFromRules(LSL_List rules) - { + { RegionMeta7WindlightData wl = (RegionMeta7WindlightData)m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.Clone(); LSL_List values = new LSL_List(); @@ -244,9 +266,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Types.Vector3 iV; switch (rule) { - case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: - idx++; - wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); + case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: + idx++; + wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); break; case (int)ScriptBaseClass.WL_AMBIENT: idx++; @@ -419,58 +441,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CMShoutError("Careminster functions are not enabled."); return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - CMShoutError("cmSetWindlightScene can only be used by estate managers or owners."); - return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + CMShoutError("cmSetWindlightScene can only be used by estate managers or owners."); + return 0; + } + int success = 0; + m_host.AddScriptLPS(1); + if (Meta7WindlightModule.EnableWindlight) + { + RegionMeta7WindlightData wl = getWindlightProfileFromRules(rules); + m_host.ParentGroup.Scene.StoreWindlightProfile(wl); + success = 1; + } + else + { + CMShoutError("Windlight module is disabled"); + return 0; + } + return success; + } + /// + /// Set the current Windlight scene to a target avatar + /// + /// + /// success: true or false + public int cmSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) + { + if (!m_CMFunctionsEnabled) + { + CMShoutError("Careminster functions are not enabled."); + return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + CMShoutError("cmSetWindlightSceneTargeted can only be used by estate managers or owners."); + return 0; } int success = 0; - m_host.AddScriptLPS(1); - if (Meta7WindlightModule.EnableWindlight) - { - RegionMeta7WindlightData wl = getWindlightProfileFromRules(rules); - m_host.ParentGroup.Scene.StoreWindlightProfile(wl); - success = 1; - } - else - { - CMShoutError("Windlight module is disabled"); - return 0; + m_host.AddScriptLPS(1); + if (Meta7WindlightModule.EnableWindlight) + { + RegionMeta7WindlightData wl = getWindlightProfileFromRules(rules); + World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); + success = 1; + } + else + { + CMShoutError("Windlight module is disabled"); + return 0; } return success; - } - /// - /// Set the current Windlight scene to a target avatar - /// - /// - /// success: true or false - public int cmSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) - { - if (!m_CMFunctionsEnabled) - { - CMShoutError("Careminster functions are not enabled."); - return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - CMShoutError("cmSetWindlightSceneTargeted can only be used by estate managers or owners."); - return 0; - } - int success = 0; - m_host.AddScriptLPS(1); - if (Meta7WindlightModule.EnableWindlight) - { - RegionMeta7WindlightData wl = getWindlightProfileFromRules(rules); - World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); - success = 1; - } - else - { - CMShoutError("Windlight module is disabled"); - return 0; - } - return success; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs index ef990a1..6239726 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs @@ -15,7 +15,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { // Windlight Functions LSL_List cmGetWindlightScene(LSL_List rules); - int cmSetWindlightScene(LSL_List rules); + int cmSetWindlightScene(LSL_List rules); int cmSetWindlightSceneTargeted(LSL_List rules, key target); + LSL_List cmGetAvatarList(); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs index 5bc3a88..aaffbe4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs @@ -66,11 +66,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public int cmSetWindlightScene(LSL_List rules) { return m_CM_Functions.cmSetWindlightScene(rules); - } - - public int cmSetWindlightSceneTargeted(LSL_List rules, key target) - { - return m_CM_Functions.cmSetWindlightSceneTargeted(rules, target); + } + + public int cmSetWindlightSceneTargeted(LSL_List rules, key target) + { + return m_CM_Functions.cmSetWindlightSceneTargeted(rules, target); + } + public LSL_List cmGetAvatarList() + { + return m_CM_Functions.cmGetAvatarList(); } } } -- cgit v1.1 From 0f3314c04ccd07e0ff9b5be69903b0a72dd73115 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 8 Apr 2010 15:00:01 -0700 Subject: Backported GetTextureModule and IAssetService.GetCached() --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 7 +- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 5 + .../CoreModules/Avatar/Assets/GetTextureModule.cs | 220 +++++++++++++++++++++ .../ServiceConnectorsOut/Asset/HGAssetBroker.cs | 8 + .../Asset/LocalAssetServiceConnector.cs | 8 + OpenSim/Services/AssetService/AssetService.cs | 5 + .../Connectors/Asset/AssetServiceConnector.cs | 8 + .../Connectors/Asset/HGAssetServiceConnector.cs | 14 ++ OpenSim/Services/Interfaces/IAssetService.cs | 10 +- OpenSim/Tests/Common/Mock/MockAssetService.cs | 5 + 10 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 2ca2657..8b81377 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -11228,9 +11228,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_groupPowers.Clear(); - for (int i = 0; i < GroupMembership.Length; i++) + if (GroupMembership != null) { - m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + for (int i = 0; i < GroupMembership.Length; i++) + { + m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + } } } } diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 967c0a1..dd796da 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -406,6 +406,11 @@ namespace Flotsam.RegionModules.AssetCache return asset; } + public AssetBase GetCached(string id) + { + return Get(id); + } + public void Expire(string id) { if (m_LogLevel >= 2) diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs new file mode 100644 index 0000000..53d2cef --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs @@ -0,0 +1,220 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Specialized; +using System.Reflection; +using System.IO; +using System.Web; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps +{ + #region Stream Handler + + public delegate byte[] StreamHandlerCallback(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse); + + public class StreamHandler : BaseStreamHandler + { + StreamHandlerCallback m_callback; + + public StreamHandler(string httpMethod, string path, StreamHandlerCallback callback) + : base(httpMethod, path) + { + m_callback = callback; + } + + public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return m_callback(path, request, httpRequest, httpResponse); + } + } + + #endregion Stream Handler + + public class GetTextureModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + private IAssetService m_assetService; + + #region IRegionModule Members + + public void Initialise(Scene pScene, IConfigSource pSource) + { + m_scene = pScene; + } + + public void PostInitialise() + { + m_assetService = m_scene.RequestModuleInterface(); + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void Close() { } + + public string Name { get { return "GetTextureModule"; } } + public bool IsSharedModule { get { return false; } } + + public void RegisterCaps(UUID agentID, Caps caps) + { + UUID capID = UUID.Random(); + + m_log.Info("[GETTEXTURE]: /CAPS/" + capID); + caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); + } + + #endregion + + private byte[] ProcessGetTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + // TODO: Change this to a config option + const string REDIRECT_URL = null; + + // Try to parse the texture ID from the request URL + NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); + string textureStr = query.GetOne("texture_id"); + + if (m_assetService == null) + { + m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return null; + } + + UUID textureID; + if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) + { + AssetBase texture; + + if (!String.IsNullOrEmpty(REDIRECT_URL)) + { + // Only try to fetch locally cached textures. Misses are redirected + texture = m_assetService.GetCached(textureID.ToString()); + + if (texture != null) + { + SendTexture(httpRequest, httpResponse, texture); + } + else + { + string textureUrl = REDIRECT_URL + textureID.ToString(); + m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); + httpResponse.RedirectLocation = textureUrl; + } + } + else + { + // Fetch locally or remotely. Misses return a 404 + texture = m_assetService.Get(textureID.ToString()); + + if (texture != null) + { + SendTexture(httpRequest, httpResponse, texture); + } + else + { + m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + } + } + } + else + { + m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); + } + + httpResponse.Send(); + return null; + } + + private void SendTexture(OSHttpRequest request, OSHttpResponse response, AssetBase texture) + { + string range = request.Headers.GetOne("Range"); + if (!String.IsNullOrEmpty(range)) + { + // Range request + int start, end; + if (TryParseRange(range, out start, out end)) + { + end = Utils.Clamp(end, 1, texture.Data.Length); + start = Utils.Clamp(start, 0, end - 1); + + m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); + + if (end - start < texture.Data.Length) + response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; + + response.ContentLength = end - start; + response.ContentType = texture.Metadata.ContentType; + + response.Body.Write(texture.Data, start, end - start); + } + else + { + m_log.Warn("Malformed Range header: " + range); + response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; + } + } + else + { + // Full content request + response.ContentLength = texture.Data.Length; + response.ContentType = texture.Metadata.ContentType; + response.Body.Write(texture.Data, 0, texture.Data.Length); + } + } + + private bool TryParseRange(string header, out int start, out int end) + { + if (header.StartsWith("bytes=")) + { + string[] rangeValues = header.Substring(6).Split('-'); + if (rangeValues.Length == 2) + { + if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end)) + return true; + } + } + + start = end = 0; + return false; + } + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index 0aa753d..0522256 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -229,6 +229,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { AssetBase asset = null; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 50348da..1b3419d 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -165,6 +165,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { AssetBase asset = null; diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index b9723a8..ed87f3f 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -93,6 +93,11 @@ namespace OpenSim.Services.AssetService return m_Database.GetAsset(assetID); } + public AssetBase GetCached(string id) + { + return Get(id); + } + public AssetMetadata GetMetadata(string id) { UUID assetID; diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index 8e311d7..84fbcd3 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -111,6 +111,14 @@ namespace OpenSim.Services.Connectors return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { if (m_Cache != null) diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs index 677169d..34df54a 100644 --- a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs @@ -116,6 +116,20 @@ namespace OpenSim.Services.Connectors return null; } + public AssetBase GetCached(string id) + { + string url = string.Empty; + string assetID = string.Empty; + + if (StringToUrlAndAssetID(id, out url, out assetID)) + { + IAssetService connector = GetConnector(url); + return connector.GetCached(assetID); + } + + return null; + } + public AssetMetadata GetMetadata(string id) { string url = string.Empty; diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs index 6dfe78d..3be6815 100644 --- a/OpenSim/Services/Interfaces/IAssetService.cs +++ b/OpenSim/Services/Interfaces/IAssetService.cs @@ -51,7 +51,15 @@ namespace OpenSim.Services.Interfaces byte[] GetData(string id); /// - /// Get an asset asynchronously + /// Synchronously fetches an asset from the local cache only + /// + /// Asset ID + /// The fetched asset, or null if it did not exist in the local cache + AssetBase GetCached(string id); + + /// + /// Get an asset synchronously or asynchronously (depending on whether + /// it is locally cached) and fire a callback with the fetched asset /// /// The asset id /// Represents the requester. Passed back via the handler diff --git a/OpenSim/Tests/Common/Mock/MockAssetService.cs b/OpenSim/Tests/Common/Mock/MockAssetService.cs index cb38043..4118308 100644 --- a/OpenSim/Tests/Common/Mock/MockAssetService.cs +++ b/OpenSim/Tests/Common/Mock/MockAssetService.cs @@ -65,6 +65,11 @@ namespace OpenSim.Tests.Common.Mock return asset; } + public AssetBase GetCached(string id) + { + return Get(id); + } + public AssetMetadata GetMetadata(string id) { throw new System.NotImplementedException(); -- cgit v1.1 From c4c4c3696edbe99496ad7e6db9b3eb0b339f09c5 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 8 Apr 2010 15:26:51 -0700 Subject: Backported WebUtil.cs from master to 0.6.9-postfixes to fix the build break --- OpenSim/Framework/WebUtil.cs | 361 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100644 OpenSim/Framework/WebUtil.cs diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs new file mode 100644 index 0000000..2843e20 --- /dev/null +++ b/OpenSim/Framework/WebUtil.cs @@ -0,0 +1,361 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Net; +using System.Net.Security; +using System.Reflection; +using System.Text; +using System.Web; +using log4net; +using OpenSim.Framework.Servers.HttpServer; +using OpenMetaverse.StructuredData; + +namespace OpenSim.Framework +{ + /// + /// Miscellaneous static methods and extension methods related to the web + /// + public static class WebUtil + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Send LLSD to an HTTP client in application/llsd+json form + /// + /// HTTP response to send the data in + /// LLSD to send to the client + public static void SendJSONResponse(OSHttpResponse response, OSDMap body) + { + byte[] responseData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(body)); + + response.ContentEncoding = Encoding.UTF8; + response.ContentLength = responseData.Length; + response.ContentType = "application/llsd+json"; + response.Body.Write(responseData, 0, responseData.Length); + } + + /// + /// Send LLSD to an HTTP client in application/llsd+xml form + /// + /// HTTP response to send the data in + /// LLSD to send to the client + public static void SendXMLResponse(OSHttpResponse response, OSDMap body) + { + byte[] responseData = OSDParser.SerializeLLSDXmlBytes(body); + + response.ContentEncoding = Encoding.UTF8; + response.ContentLength = responseData.Length; + response.ContentType = "application/llsd+xml"; + response.Body.Write(responseData, 0, responseData.Length); + } + + /// + /// Make a GET or GET-like request to a web service that returns LLSD + /// or JSON data + /// + public static OSDMap ServiceRequest(string url, string httpVerb) + { + string errorMessage; + + try + { + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); + request.Method = httpVerb; + + using (WebResponse response = request.GetResponse()) + { + using (Stream responseStream = response.GetResponseStream()) + { + try + { + string responseStr = responseStream.GetStreamString(); + OSD responseOSD = OSDParser.Deserialize(responseStr); + if (responseOSD.Type == OSDType.Map) + return (OSDMap)responseOSD; + else + errorMessage = "Response format was invalid."; + } + catch + { + errorMessage = "Failed to parse the response."; + } + } + } + } + catch (Exception ex) + { + m_log.Warn("GET from URL " + url + " failed: " + ex.Message); + errorMessage = ex.Message; + } + + return new OSDMap { { "Message", OSD.FromString("Service request failed. " + errorMessage) } }; + } + + /// + /// POST URL-encoded form data to a web service that returns LLSD or + /// JSON data + /// + public static OSDMap PostToService(string url, NameValueCollection data) + { + string errorMessage; + + try + { + string queryString = BuildQueryString(data); + byte[] requestData = System.Text.Encoding.UTF8.GetBytes(queryString); + + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); + request.Method = "POST"; + request.ContentLength = requestData.Length; + request.ContentType = "application/x-www-form-urlencoded"; + + using (Stream requestStream = request.GetRequestStream()) + requestStream.Write(requestData, 0, requestData.Length); + + using (WebResponse response = request.GetResponse()) + { + using (Stream responseStream = response.GetResponseStream()) + { + try + { + string responseStr = responseStream.GetStreamString(); + OSD responseOSD = OSDParser.Deserialize(responseStr); + if (responseOSD.Type == OSDType.Map) + return (OSDMap)responseOSD; + else + errorMessage = "Response format was invalid."; + } + catch + { + errorMessage = "Failed to parse the response."; + } + } + } + } + catch (Exception ex) + { + m_log.Warn("POST to URL " + url + " failed: " + ex.Message); + errorMessage = ex.Message; + } + + return new OSDMap { { "Message", OSD.FromString("Service request failed. " + errorMessage) } }; + } + + #region Uri + + /// + /// Combines a Uri that can contain both a base Uri and relative path + /// with a second relative path fragment + /// + /// Starting (base) Uri + /// Relative path fragment to append to the end + /// of the Uri + /// The combined Uri + /// This is similar to the Uri constructor that takes a base + /// Uri and the relative path, except this method can append a relative + /// path fragment on to an existing relative path + public static Uri Combine(this Uri uri, string fragment) + { + string fragment1 = uri.Fragment; + string fragment2 = fragment; + + if (!fragment1.EndsWith("/")) + fragment1 = fragment1 + '/'; + if (fragment2.StartsWith("/")) + fragment2 = fragment2.Substring(1); + + return new Uri(uri, fragment1 + fragment2); + } + + /// + /// Combines a Uri that can contain both a base Uri and relative path + /// with a second relative path fragment. If the fragment is absolute, + /// it will be returned without modification + /// + /// Starting (base) Uri + /// Relative path fragment to append to the end + /// of the Uri, or an absolute Uri to return unmodified + /// The combined Uri + public static Uri Combine(this Uri uri, Uri fragment) + { + if (fragment.IsAbsoluteUri) + return fragment; + + string fragment1 = uri.Fragment; + string fragment2 = fragment.ToString(); + + if (!fragment1.EndsWith("/")) + fragment1 = fragment1 + '/'; + if (fragment2.StartsWith("/")) + fragment2 = fragment2.Substring(1); + + return new Uri(uri, fragment1 + fragment2); + } + + /// + /// Appends a query string to a Uri that may or may not have existing + /// query parameters + /// + /// Uri to append the query to + /// Query string to append. Can either start with ? + /// or just containg key/value pairs + /// String representation of the Uri with the query string + /// appended + public static string AppendQuery(this Uri uri, string query) + { + if (String.IsNullOrEmpty(query)) + return uri.ToString(); + + if (query[0] == '?' || query[0] == '&') + query = query.Substring(1); + + string uriStr = uri.ToString(); + + if (uriStr.Contains("?")) + return uriStr + '&' + query; + else + return uriStr + '?' + query; + } + + #endregion Uri + + #region NameValueCollection + + /// + /// Convert a NameValueCollection into a query string. This is the + /// inverse of HttpUtility.ParseQueryString() + /// + /// Collection of key/value pairs to convert + /// A query string with URL-escaped values + public static string BuildQueryString(NameValueCollection parameters) + { + List items = new List(parameters.Count); + + foreach (string key in parameters.Keys) + { + string[] values = parameters.GetValues(key); + if (values != null) + { + foreach (string value in values) + items.Add(String.Concat(key, "=", HttpUtility.UrlEncode(value ?? String.Empty))); + } + } + + return String.Join("&", items.ToArray()); + } + + /// + /// + /// + /// + /// + /// + public static string GetOne(this NameValueCollection collection, string key) + { + string[] values = collection.GetValues(key); + if (values != null && values.Length > 0) + return values[0]; + + return null; + } + + #endregion NameValueCollection + + #region Stream + + /// + /// Copies the contents of one stream to another, starting at the + /// current position of each stream + /// + /// The stream to copy from, at the position + /// where copying should begin + /// The stream to copy to, at the position where + /// bytes should be written + /// The maximum bytes to copy + /// The total number of bytes copied + /// + /// Copying begins at the streams' current positions. The positions are + /// NOT reset after copying is complete. + /// + public static int CopyTo(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy) + { + byte[] buffer = new byte[4096]; + int readBytes; + int totalCopiedBytes = 0; + + while ((readBytes = copyFrom.Read(buffer, 0, Math.Min(4096, maximumBytesToCopy))) > 0) + { + int writeBytes = Math.Min(maximumBytesToCopy, readBytes); + copyTo.Write(buffer, 0, writeBytes); + totalCopiedBytes += writeBytes; + maximumBytesToCopy -= writeBytes; + } + + return totalCopiedBytes; + } + + /// + /// Converts an entire stream to a string, regardless of current stream + /// position + /// + /// The stream to convert to a string + /// + /// When this method is done, the stream position will be + /// reset to its previous position before this method was called + public static string GetStreamString(this Stream stream) + { + string value = null; + + if (stream != null && stream.CanRead) + { + long rewindPos = -1; + + if (stream.CanSeek) + { + rewindPos = stream.Position; + stream.Seek(0, SeekOrigin.Begin); + } + + StreamReader reader = new StreamReader(stream); + value = reader.ReadToEnd(); + + if (rewindPos >= 0) + stream.Seek(rewindPos, SeekOrigin.Begin); + } + + return value; + } + + #endregion Stream + } +} -- cgit v1.1 From 94a46867ed763752dc69b3218ab54fcd338b0ad9 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 8 Apr 2010 15:38:58 -0700 Subject: Added a missing reference to prebuild.xml --- prebuild.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/prebuild.xml b/prebuild.xml index 6b25792..fd71475 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -157,6 +157,7 @@ + -- cgit v1.1 From 54cedfe4320573ac302b11716e293086110a4f9b Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Thu, 8 Apr 2010 15:57:00 -0700 Subject: Changed the GetTextureModule backport to work with the 0.6.9 codebase --- OpenSim/Framework/WebUtil.cs | 361 --------------------- .../CoreModules/Avatar/Assets/GetTextureModule.cs | 13 +- prebuild.xml | 1 - 3 files changed, 11 insertions(+), 364 deletions(-) delete mode 100644 OpenSim/Framework/WebUtil.cs diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs deleted file mode 100644 index 2843e20..0000000 --- a/OpenSim/Framework/WebUtil.cs +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.Net; -using System.Net.Security; -using System.Reflection; -using System.Text; -using System.Web; -using log4net; -using OpenSim.Framework.Servers.HttpServer; -using OpenMetaverse.StructuredData; - -namespace OpenSim.Framework -{ - /// - /// Miscellaneous static methods and extension methods related to the web - /// - public static class WebUtil - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Send LLSD to an HTTP client in application/llsd+json form - /// - /// HTTP response to send the data in - /// LLSD to send to the client - public static void SendJSONResponse(OSHttpResponse response, OSDMap body) - { - byte[] responseData = Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(body)); - - response.ContentEncoding = Encoding.UTF8; - response.ContentLength = responseData.Length; - response.ContentType = "application/llsd+json"; - response.Body.Write(responseData, 0, responseData.Length); - } - - /// - /// Send LLSD to an HTTP client in application/llsd+xml form - /// - /// HTTP response to send the data in - /// LLSD to send to the client - public static void SendXMLResponse(OSHttpResponse response, OSDMap body) - { - byte[] responseData = OSDParser.SerializeLLSDXmlBytes(body); - - response.ContentEncoding = Encoding.UTF8; - response.ContentLength = responseData.Length; - response.ContentType = "application/llsd+xml"; - response.Body.Write(responseData, 0, responseData.Length); - } - - /// - /// Make a GET or GET-like request to a web service that returns LLSD - /// or JSON data - /// - public static OSDMap ServiceRequest(string url, string httpVerb) - { - string errorMessage; - - try - { - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); - request.Method = httpVerb; - - using (WebResponse response = request.GetResponse()) - { - using (Stream responseStream = response.GetResponseStream()) - { - try - { - string responseStr = responseStream.GetStreamString(); - OSD responseOSD = OSDParser.Deserialize(responseStr); - if (responseOSD.Type == OSDType.Map) - return (OSDMap)responseOSD; - else - errorMessage = "Response format was invalid."; - } - catch - { - errorMessage = "Failed to parse the response."; - } - } - } - } - catch (Exception ex) - { - m_log.Warn("GET from URL " + url + " failed: " + ex.Message); - errorMessage = ex.Message; - } - - return new OSDMap { { "Message", OSD.FromString("Service request failed. " + errorMessage) } }; - } - - /// - /// POST URL-encoded form data to a web service that returns LLSD or - /// JSON data - /// - public static OSDMap PostToService(string url, NameValueCollection data) - { - string errorMessage; - - try - { - string queryString = BuildQueryString(data); - byte[] requestData = System.Text.Encoding.UTF8.GetBytes(queryString); - - HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); - request.Method = "POST"; - request.ContentLength = requestData.Length; - request.ContentType = "application/x-www-form-urlencoded"; - - using (Stream requestStream = request.GetRequestStream()) - requestStream.Write(requestData, 0, requestData.Length); - - using (WebResponse response = request.GetResponse()) - { - using (Stream responseStream = response.GetResponseStream()) - { - try - { - string responseStr = responseStream.GetStreamString(); - OSD responseOSD = OSDParser.Deserialize(responseStr); - if (responseOSD.Type == OSDType.Map) - return (OSDMap)responseOSD; - else - errorMessage = "Response format was invalid."; - } - catch - { - errorMessage = "Failed to parse the response."; - } - } - } - } - catch (Exception ex) - { - m_log.Warn("POST to URL " + url + " failed: " + ex.Message); - errorMessage = ex.Message; - } - - return new OSDMap { { "Message", OSD.FromString("Service request failed. " + errorMessage) } }; - } - - #region Uri - - /// - /// Combines a Uri that can contain both a base Uri and relative path - /// with a second relative path fragment - /// - /// Starting (base) Uri - /// Relative path fragment to append to the end - /// of the Uri - /// The combined Uri - /// This is similar to the Uri constructor that takes a base - /// Uri and the relative path, except this method can append a relative - /// path fragment on to an existing relative path - public static Uri Combine(this Uri uri, string fragment) - { - string fragment1 = uri.Fragment; - string fragment2 = fragment; - - if (!fragment1.EndsWith("/")) - fragment1 = fragment1 + '/'; - if (fragment2.StartsWith("/")) - fragment2 = fragment2.Substring(1); - - return new Uri(uri, fragment1 + fragment2); - } - - /// - /// Combines a Uri that can contain both a base Uri and relative path - /// with a second relative path fragment. If the fragment is absolute, - /// it will be returned without modification - /// - /// Starting (base) Uri - /// Relative path fragment to append to the end - /// of the Uri, or an absolute Uri to return unmodified - /// The combined Uri - public static Uri Combine(this Uri uri, Uri fragment) - { - if (fragment.IsAbsoluteUri) - return fragment; - - string fragment1 = uri.Fragment; - string fragment2 = fragment.ToString(); - - if (!fragment1.EndsWith("/")) - fragment1 = fragment1 + '/'; - if (fragment2.StartsWith("/")) - fragment2 = fragment2.Substring(1); - - return new Uri(uri, fragment1 + fragment2); - } - - /// - /// Appends a query string to a Uri that may or may not have existing - /// query parameters - /// - /// Uri to append the query to - /// Query string to append. Can either start with ? - /// or just containg key/value pairs - /// String representation of the Uri with the query string - /// appended - public static string AppendQuery(this Uri uri, string query) - { - if (String.IsNullOrEmpty(query)) - return uri.ToString(); - - if (query[0] == '?' || query[0] == '&') - query = query.Substring(1); - - string uriStr = uri.ToString(); - - if (uriStr.Contains("?")) - return uriStr + '&' + query; - else - return uriStr + '?' + query; - } - - #endregion Uri - - #region NameValueCollection - - /// - /// Convert a NameValueCollection into a query string. This is the - /// inverse of HttpUtility.ParseQueryString() - /// - /// Collection of key/value pairs to convert - /// A query string with URL-escaped values - public static string BuildQueryString(NameValueCollection parameters) - { - List items = new List(parameters.Count); - - foreach (string key in parameters.Keys) - { - string[] values = parameters.GetValues(key); - if (values != null) - { - foreach (string value in values) - items.Add(String.Concat(key, "=", HttpUtility.UrlEncode(value ?? String.Empty))); - } - } - - return String.Join("&", items.ToArray()); - } - - /// - /// - /// - /// - /// - /// - public static string GetOne(this NameValueCollection collection, string key) - { - string[] values = collection.GetValues(key); - if (values != null && values.Length > 0) - return values[0]; - - return null; - } - - #endregion NameValueCollection - - #region Stream - - /// - /// Copies the contents of one stream to another, starting at the - /// current position of each stream - /// - /// The stream to copy from, at the position - /// where copying should begin - /// The stream to copy to, at the position where - /// bytes should be written - /// The maximum bytes to copy - /// The total number of bytes copied - /// - /// Copying begins at the streams' current positions. The positions are - /// NOT reset after copying is complete. - /// - public static int CopyTo(this Stream copyFrom, Stream copyTo, int maximumBytesToCopy) - { - byte[] buffer = new byte[4096]; - int readBytes; - int totalCopiedBytes = 0; - - while ((readBytes = copyFrom.Read(buffer, 0, Math.Min(4096, maximumBytesToCopy))) > 0) - { - int writeBytes = Math.Min(maximumBytesToCopy, readBytes); - copyTo.Write(buffer, 0, writeBytes); - totalCopiedBytes += writeBytes; - maximumBytesToCopy -= writeBytes; - } - - return totalCopiedBytes; - } - - /// - /// Converts an entire stream to a string, regardless of current stream - /// position - /// - /// The stream to convert to a string - /// - /// When this method is done, the stream position will be - /// reset to its previous position before this method was called - public static string GetStreamString(this Stream stream) - { - string value = null; - - if (stream != null && stream.CanRead) - { - long rewindPos = -1; - - if (stream.CanSeek) - { - rewindPos = stream.Position; - stream.Seek(0, SeekOrigin.Begin); - } - - StreamReader reader = new StreamReader(stream); - value = reader.ReadToEnd(); - - if (rewindPos >= 0) - stream.Seek(rewindPos, SeekOrigin.Begin); - } - - return value; - } - - #endregion Stream - } -} diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs index 53d2cef..3b66859 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs @@ -109,7 +109,7 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps // Try to parse the texture ID from the request URL NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); - string textureStr = query.GetOne("texture_id"); + string textureStr = GetOne(query, "texture_id"); if (m_assetService == null) { @@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps private void SendTexture(OSHttpRequest request, OSHttpResponse response, AssetBase texture) { - string range = request.Headers.GetOne("Range"); + string range = GetOne(request.Headers, "Range"); if (!String.IsNullOrEmpty(range)) { // Range request @@ -216,5 +216,14 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps start = end = 0; return false; } + + private static string GetOne(NameValueCollection collection, string key) + { + string[] values = collection.GetValues(key); + if (values != null && values.Length > 0) + return values[0]; + + return null; + } } } diff --git a/prebuild.xml b/prebuild.xml index fd71475..6b25792 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -157,7 +157,6 @@ - -- cgit v1.1 From 7701ea27983be851a3c9d3954346018e07680ae6 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 9 Apr 2010 06:49:14 +0100 Subject: Add Scene.SnmpService, which is of type ISnmpModule and, if nun-null, can be used to send snmp alerts --- OpenSim/Region/Framework/Scenes/Scene.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 55f4550..db073e8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -158,6 +158,20 @@ namespace OpenSim.Region.Framework.Scenes public IXfer XferManager; + protected ISnmpModule m_snmpService = null; + public ISnmpModule SnmpService + { + get + { + if (m_snmpService == null) + { + m_snmpService = RequestModuleInterface(); + } + + return m_snmpService; + } + } + protected IAssetService m_AssetService; protected IAuthorizationService m_AuthorizationService; -- cgit v1.1 From d975bd8e5c937314bbcd5c3b66a48f87057358d0 Mon Sep 17 00:00:00 2001 From: lcc Date: Sat, 10 Apr 2010 17:51:51 +0200 Subject: Fixing Trap --- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 OpenSim/Region/Framework/Interfaces/ISnmpModule.cs diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs deleted file mode 100644 index 9790fc7..0000000 --- a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs +++ /dev/null @@ -1,11 +0,0 @@ -/////////////////////////////////////////////////////////////////// -// -// (c) Careminster LImited, Melanie Thielker and the Meta7 Team -// -// This file is not open source. All rights reserved -// -public interface ISnmpModule -{ - void Alert(string message); - void Trap(string message); -} -- cgit v1.1 From c4eaf195b53be3f19fe25bd7ac4a41bd002bbc8d Mon Sep 17 00:00:00 2001 From: lcc Date: Sat, 10 Apr 2010 17:59:08 +0200 Subject: dding this deleted file... --- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs index 9790fc7..cdd1bd8 100644 --- a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -3,9 +3,9 @@ // (c) Careminster LImited, Melanie Thielker and the Meta7 Team // // This file is not open source. All rights reserved -// +// Mod 2 public interface ISnmpModule { void Alert(string message); - void Trap(string message); + void Trap(int code,string simname,string Message); } -- cgit v1.1 From 58dac970afb09bc003c7089f35fe592516fb209e Mon Sep 17 00:00:00 2001 From: lcc Date: Sat, 10 Apr 2010 18:05:08 +0200 Subject: re-fixing this darn file --- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 OpenSim/Region/Framework/Interfaces/ISnmpModule.cs diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs new file mode 100644 index 0000000..4e03df5 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -0,0 +1,11 @@ +/////////////////////////////////////////////////////////////////// +// +// (c) Careminster LImited, Melanie Thielker and the Meta7 Team +// +// This file is not open source. All rights reserved +// +public interface ISnmpModule +{ + void Alert(string message); + void Trap(int code,string simname,string Message); +} -- cgit v1.1 From 0b2b2daf23dbf7a51f3d568903548cd964334ce2 Mon Sep 17 00:00:00 2001 From: Mike Rieker Date: Sat, 10 Apr 2010 14:43:26 -0400 Subject: guarantee that a script engine's GetScriptErrors() will not be called until after its OnRezScript() returns so that script compile error messages can be retrieved --- .../Framework/Interfaces/IEntityInventory.cs | 4 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 3 +- .../Framework/Scenes/SceneObjectPartInventory.cs | 76 +++++++++++++++++++--- 3 files changed, 71 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index f58904f..16ca3f9 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -73,8 +73,6 @@ namespace OpenSim.Region.Framework.Interfaces /// void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource); - ArrayList GetScriptErrors(UUID itemID); - /// /// Stop all the scripts in this entity. /// @@ -104,6 +102,8 @@ namespace OpenSim.Region.Framework.Interfaces /// void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); + ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); + /// /// Stop a script which is in this prim's inventory. /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index b04871e..6c57d18 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -271,8 +271,7 @@ namespace OpenSim.Region.Framework.Scenes { // Needs to determine which engine was running it and use that // - part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); - errors = part.Inventory.GetScriptErrors(item.ItemID); + errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0); } else { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 5d00917..d03b464 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -46,6 +46,8 @@ namespace OpenSim.Region.Framework.Scenes private string m_inventoryFileName = String.Empty; private int m_inventoryFileNameSerial = 0; + + private Dictionary m_scriptErrors = new Dictionary(); /// /// The part to which the inventory belongs. @@ -211,7 +213,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public ArrayList GetScriptErrors(UUID itemID) + private ArrayList GetScriptErrors(UUID itemID) { ArrayList ret = new ArrayList(); @@ -270,7 +272,10 @@ namespace OpenSim.Region.Framework.Scenes // item.Name, item.ItemID, Name, UUID); if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) + { + StoreScriptError(item.ItemID, "no permission"); return; + } m_part.AddFlag(PrimFlags.Scripted); @@ -285,6 +290,7 @@ namespace OpenSim.Region.Framework.Scenes m_items.LockItemsForWrite(false); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); + StoreScriptErrors(item.ItemID, GetScriptErrors(item.ItemID)); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); return; @@ -294,11 +300,13 @@ namespace OpenSim.Region.Framework.Scenes { if (null == asset) { + string msg = String.Format("asset ID {0} could not be found", item.AssetID); + StoreScriptError(item.ItemID, msg); m_log.ErrorFormat( "[PRIM INVENTORY]: " + - "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", + "Couldn't start script {0}, {1} at {2} in {3} since {4}", item.Name, item.ItemID, m_part.AbsolutePosition, - m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); + m_part.ParentGroup.Scene.RegionInfo.RegionName, msg); } else { @@ -311,11 +319,16 @@ namespace OpenSim.Region.Framework.Scenes string script = Utils.BytesToString(asset.Data); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); + StoreScriptErrors(item.ItemID, GetScriptErrors(item.ItemID)); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); } }); } + else + { + StoreScriptError(item.ItemID, "scripts disabled"); + } } private void RestoreSavedScriptState(UUID oldID, UUID newID) @@ -392,24 +405,71 @@ namespace OpenSim.Region.Framework.Scenes else { m_items.LockItemsForRead(false); + string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID, + m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); + StoreScriptError(itemId, msg); m_log.ErrorFormat( "[PRIM INVENTORY]: " + - "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", - itemId, m_part.Name, m_part.UUID, - m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); + "Couldn't start script with ID {0} since it {1}", itemId, msg); } } else { m_items.LockItemsForRead(false); + string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID); + StoreScriptError(itemId, msg); m_log.ErrorFormat( "[PRIM INVENTORY]: " + - "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", - itemId, m_part.Name, m_part.UUID); + "Couldn't start script with ID {0} since it {1}", itemId, msg); } } + public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) + { + ArrayList errors; + + lock (m_scriptErrors) + { + m_scriptErrors.Remove(itemId); + } + CreateScriptInstance(itemId, startParam, postOnRez, engine, stateSource); + lock (m_scriptErrors) + { + while (!m_scriptErrors.TryGetValue(itemId, out errors)) + { + if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000)) + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "timedout waiting for script {0} errors", itemId); + if (!m_scriptErrors.TryGetValue(itemId, out errors)) + { + errors = new ArrayList(1); + errors.Add("timedout waiting for errors"); + } + break; + } + } + m_scriptErrors.Remove(itemId); + } + return errors; + } + private void StoreScriptErrors(UUID itemId, ArrayList errors) + { + lock (m_scriptErrors) + { + m_scriptErrors[itemId] = errors; + System.Threading.Monitor.PulseAll(m_scriptErrors); + } + } + private void StoreScriptError(UUID itemId, string message) + { + ArrayList errors = new ArrayList(1); + errors.Add(message); + StoreScriptErrors(itemId, errors); + } + /// /// Stop a script which is in this prim's inventory. /// -- cgit v1.1 From c6ba50b7e29789937170c6efdee5386bce54ff3d Mon Sep 17 00:00:00 2001 From: lcc Date: Sat, 10 Apr 2010 23:39:06 +0200 Subject: Adding ColdStart event --- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs index cdd1bd8..6fd6ba7 100644 --- a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -8,4 +8,5 @@ public interface ISnmpModule { void Alert(string message); void Trap(int code,string simname,string Message); + void ColdStart(int step , string simname); } -- cgit v1.1 From 9b6e89457c692fd65a0a221ef7809cc0e4836fe7 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Sun, 11 Apr 2010 14:12:01 -0400 Subject: Fixed LINEAR_MOTOR Z drive, Mantis #30 --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 58 ++++++++++++++++----------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 67f8af5..01c3f81 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -2626,15 +2626,15 @@ Console.WriteLine(" JointCreateFixed"); // m_angularDeflectionEfficiency = pValue; break; case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.1f) pValue = 0.1f; // m_angularDeflectionTimescale = pValue; break; case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.3f) pValue = 0.3f; m_angularMotorDecayTimescale = pValue; break; case Vehicle.ANGULAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.3f) pValue = 0.3f; m_angularMotorTimescale = pValue; break; case Vehicle.BANKING_EFFICIENCY: @@ -2663,7 +2663,7 @@ Console.WriteLine(" JointCreateFixed"); m_VhoverHeight = pValue; break; case Vehicle.HOVER_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.1f) pValue = 0.1f; m_VhoverTimescale = pValue; break; case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: @@ -2675,11 +2675,11 @@ Console.WriteLine(" JointCreateFixed"); // m_linearDeflectionTimescale = pValue; break; case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.3f) pValue = 0.3f; m_linearMotorDecayTimescale = pValue; break; case Vehicle.LINEAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.1f) pValue = 0.1f; m_linearMotorTimescale = pValue; break; case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: @@ -2688,7 +2688,7 @@ Console.WriteLine(" JointCreateFixed"); m_verticalAttractionEfficiency = pValue; break; case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.1f) pValue = 0.1f; m_verticalAttractionTimescale = pValue; break; @@ -2704,6 +2704,7 @@ Console.WriteLine(" JointCreateFixed"); UpdateAngDecay(); break; case Vehicle.LINEAR_FRICTION_TIMESCALE: + if (pValue < 0.1f) pValue = 0.1f; m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); break; case Vehicle.LINEAR_MOTOR_DIRECTION: @@ -2743,6 +2744,9 @@ Console.WriteLine(" JointCreateFixed"); UpdateAngDecay(); break; case Vehicle.LINEAR_FRICTION_TIMESCALE: + if (pValue.X < 0.1f) pValue.X = 0.1f; + if (pValue.Y < 0.1f) pValue.Y = 0.1f; + if (pValue.Z < 0.1f) pValue.Z = 0.1f; m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.LINEAR_MOTOR_DIRECTION: @@ -2939,7 +2943,7 @@ Console.WriteLine(" JointCreateFixed"); internal void Halt() { // Kill all motions, when non-physical - m_linearMotorDirection = Vector3.Zero; + // m_linearMotorDirection = Vector3.Zero; m_lLinMotorDVel = Vector3.Zero; m_lLinObjectVel = Vector3.Zero; m_wLinObjectVel = Vector3.Zero; @@ -2951,16 +2955,22 @@ Console.WriteLine(" JointCreateFixed"); private void UpdateLinDecay() { - if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X; - if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y; - if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z; +// if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X; +// if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y; +// if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z; + m_lLinMotorDVel.X = m_linearMotorDirection.X; + m_lLinMotorDVel.Y = m_linearMotorDirection.Y; + m_lLinMotorDVel.Z = m_linearMotorDirection.Z; } // else let the motor decay on its own private void UpdateAngDecay() { - if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X; - if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y; - if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z; +// if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X; +// if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y; +// if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z; + m_angularMotorDVel.X = m_angularMotorDirection.X; + m_angularMotorDVel.Y = m_angularMotorDirection.Y; + m_angularMotorDVel.Z = m_angularMotorDirection.Z; } // else let the motor decay on its own public void Move(float timestep) @@ -2981,7 +2991,7 @@ Console.WriteLine(" JointCreateFixed"); if (fence == 1) border_limit = 0.5f; // bounce point frcount++; // used to limit debug comment output - if (frcount > 100) + if (frcount > 10) frcount = 0; if(revcount > 0) revcount--; @@ -3222,12 +3232,13 @@ Console.WriteLine(" JointCreateFixed"); { m_lLinMotorDVel = Vector3.Zero; } - else + + /* else { if (Math.Abs(m_lLinMotorDVel.X) < Math.Abs(m_lLinObjectVel.X)) m_lLinObjectVel.X = m_lLinMotorDVel.X; if (Math.Abs(m_lLinMotorDVel.Y) < Math.Abs(m_lLinObjectVel.Y)) m_lLinObjectVel.Y = m_lLinMotorDVel.Y; - if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z; - } + if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z; + } */ } // end linear motor decay if ( (! m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! m_lLinObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) @@ -3255,7 +3266,6 @@ Console.WriteLine(" JointCreateFixed"); if (m_linearFrictionTimescale.Z < 300.0f) { float fricfactor = m_linearFrictionTimescale.Z / timestep; -//if(frcount == 0) Console.WriteLine("Zfric={0}", fricfactor); float fricZ = m_lLinObjectVel.Z / fricfactor; m_lLinObjectVel.Z -= fricZ; } @@ -3316,15 +3326,17 @@ Console.WriteLine(" JointCreateFixed"); } } else - { // not hovering, Gravity rules - m_wLinObjectVel.Z = vel_now.Z; + { // not hovering + if (m_wLinObjectVel.Z == 0f) + { // Gravity rules + m_wLinObjectVel.Z = vel_now.Z; + } // else the motor has it } linvel = m_wLinObjectVel; // Vehicle Linear Motion done ======================================= // Apply velocity -//if(frcount == 0) Console.WriteLine("LV {0}", linvel); - d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z); + d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z); // apply gravity force d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); //if(frcount == 0) Console.WriteLine("Grav {0}", grav); -- cgit v1.1 From 4433f53f72c6be11ee0a3453ceec403b5de567fa Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 13 Apr 2010 20:14:56 +0100 Subject: Drop unused Alert() method from ISnmpModule --- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs index 6fd6ba7..d37a01b 100644 --- a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -6,7 +6,6 @@ // Mod 2 public interface ISnmpModule { - void Alert(string message); - void Trap(int code,string simname,string Message); + void Trap(int code,string simname,string Message); void ColdStart(int step , string simname); } -- cgit v1.1 From fac55bc78b70a1f8a3a53b222d9df515e32e82ae Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 14 Apr 2010 01:17:27 +0100 Subject: Change ISnmpModule to use scene references --- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs index d37a01b..5143b21 100644 --- a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -4,8 +4,15 @@ // // This file is not open source. All rights reserved // Mod 2 + +using OpenSim.Region.Framework.Scenes; + public interface ISnmpModule { - void Trap(int code,string simname,string Message); - void ColdStart(int step , string simname); + void Trap(int code, string Message, Scene scene); + void Critcal(string Message, Scene scene); + void Warning(string Message, Scene scene); + void Major(string Message, Scene scene); + void ColdStart(int step , Scene scene); + void Shutdown(int step , Scene scene); } -- cgit v1.1 From 1636f535ba1915732927054be36b909b67a6de6c Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 14 Apr 2010 10:42:14 +0100 Subject: Committing sacha's partial work (from orpheus). The GridBrat needs to learn a bit of git --- OpenSim/Region/Application/OpenSimBase.cs | 45 ++++++++++++++++++++++ OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index cf2ab65..f3aaa76 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -346,10 +346,28 @@ namespace OpenSim else m_log.Error("[MODULES]: The new RegionModulesController is missing..."); scene.SetModuleInterfaces(); +// First Step of bootreport sequence + if (scene.SnmpService != null) + { + scene.SnmpService.ColdStart(1,scene); + } + +// it should be a LinkDown event +// Maped inside opennms +// bad... + if (scene.SnmpService != null) + { + scene.SnmpService.Warning("Loading prins", scene); + } // Prims have to be loaded after module configuration since some modules may be invoked during the load scene.LoadPrimsFromStorage(regionInfo.originRegionID); + if (scene.SnmpService != null) + { + scene.SnmpService.Warning("Creating region texture", scene); + } + // moved these here as the terrain texture has to be created after the modules are initialized // and has to happen before the region is registered with the grid. scene.CreateTerrainTexture(false); @@ -357,6 +375,10 @@ namespace OpenSim // TODO : Try setting resource for region xstats here on scene MainServer.Instance.AddStreamHandler(new Region.Framework.Scenes.RegionStatsHandler(regionInfo)); + if (scene.SnmpService != null) + { + scene.SnmpService.Warning("Grid Registration in progress", scene); + } try { scene.RegisterRegionWithGrid(); @@ -365,11 +387,20 @@ namespace OpenSim { m_log.ErrorFormat("[STARTUP]: Registration of region with grid failed, aborting startup - {0}", e.StackTrace); + if (scene.SnmpService != null) + { + scene.SnmpService.Critical("Grid registration failed. Startup aborted.", scene); + } // Carrying on now causes a lot of confusion down the // line - we need to get the user's attention Environment.Exit(1); } + if (scene.SnmpService != null) + { + scene.SnmpService.Warning("Grid Registration done", scene); + } + // We need to do this after we've initialized the // scripting engines. scene.CreateScriptInstances(); @@ -377,6 +408,11 @@ namespace OpenSim scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); scene.EventManager.TriggerParcelPrimCountUpdate(); + if (scene.SnmpService != null) + { + scene.SnmpService.Warning("ScriptEngine started", scene); + } + m_sceneManager.Add(scene); if (m_autoCreateClientStack) @@ -385,6 +421,10 @@ namespace OpenSim clientServer.Start(); } + if (scene.SnmpService != null) + { + scene.SnmpService.Warning("Initializing region modules", scene); + } if (do_post_init) { foreach (IRegionModule module in modules) @@ -396,6 +436,11 @@ namespace OpenSim mscene = scene; + if (scene.SnmpService != null) + { + scene.SnmpService.Warning("The region is operational", scene); + } + scene.StartTimer(); return clientServer; diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs index 5143b21..8a83fe9 100644 --- a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -10,7 +10,7 @@ using OpenSim.Region.Framework.Scenes; public interface ISnmpModule { void Trap(int code, string Message, Scene scene); - void Critcal(string Message, Scene scene); + void Critical(string Message, Scene scene); void Warning(string Message, Scene scene); void Major(string Message, Scene scene); void ColdStart(int step , Scene scene); -- cgit v1.1 From c77444a8215748633812e67adea8c7ff66a5480d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 16 Apr 2010 20:40:01 +0100 Subject: Fix http://opensimulator.org/mantis/view.php?id=4657 where OpenSim.Grid.UserServer.exe fails on startup if no previous config probably appears to occur because mono 2.4.2.3 (and possibly later) erroneously returns a value of 0 for BufferWidth and BufferHeight in some circumstances --- OpenSim/Framework/Console/LocalConsole.cs | 63 +++++++++++++++++++++++-------- OpenSim/Framework/Util.cs | 2 +- 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs index be936b6..a3036d0 100644 --- a/OpenSim/Framework/Console/LocalConsole.cs +++ b/OpenSim/Framework/Console/LocalConsole.cs @@ -38,7 +38,7 @@ namespace OpenSim.Framework.Console { /// /// A console that uses cursor control and color - /// + /// public class LocalConsole : CommandConsole { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -100,24 +100,40 @@ namespace OpenSim.Framework.Console private int SetCursorTop(int top) { // From at least mono 2.4.2.3, window resizing can give mono an invalid row and column values. If we try - // to set a cursor row position with a currently invalid column, mono will throw an exception. - // Therefore, we need to make sure that the column position is valid first. + // to set a cursor row position with a currently invalid column, mono will throw an exception. + // Therefore, we need to make sure that the column position is valid first. int left = System.Console.CursorLeft; if (left < 0) + { System.Console.CursorLeft = 0; - else if (left >= System.Console.BufferWidth) - System.Console.CursorLeft = System.Console.BufferWidth - 1; + } + else + { + int bw = System.Console.BufferWidth; + + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bw > 0 && left >= bw) + System.Console.CursorLeft = bw - 1; + } if (top < 0) + { top = 0; - if (top >= System.Console.BufferHeight) - top = System.Console.BufferHeight - 1; + } + else + { + int bh = System.Console.BufferHeight; + + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bh > 0 && top >= bh) + top = bh - 1; + } System.Console.CursorTop = top; return top; - } + } /// /// Set the cursor column. @@ -129,23 +145,38 @@ namespace OpenSim.Framework.Console /// /// /// The new cursor column. - /// + /// private int SetCursorLeft(int left) { // From at least mono 2.4.2.3, window resizing can give mono an invalid row and column values. If we try - // to set a cursor column position with a currently invalid row, mono will throw an exception. - // Therefore, we need to make sure that the row position is valid first. + // to set a cursor column position with a currently invalid row, mono will throw an exception. + // Therefore, we need to make sure that the row position is valid first. int top = System.Console.CursorTop; if (top < 0) + { System.Console.CursorTop = 0; - else if (top >= System.Console.BufferHeight) - System.Console.CursorTop = System.Console.BufferHeight - 1; + } + else + { + int bh = System.Console.BufferHeight; + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bh > 0 && top >= bh) + System.Console.CursorTop = bh - 1; + } if (left < 0) + { left = 0; - if (left >= System.Console.BufferWidth) - left = System.Console.BufferWidth - 1; + } + else + { + int bw = System.Console.BufferWidth; + + // On Mono 2.4.2.3 (and possibly above), the buffer value is sometimes erroneously zero (Mantis 4657) + if (bw > 0 && left >= bw) + left = bw - 1; + } System.Console.CursorLeft = left; @@ -183,7 +214,7 @@ namespace OpenSim.Framework.Console System.Console.Write("{0}", prompt); SetCursorTop(new_y); - SetCursorLeft(new_x); + SetCursorLeft(new_x); } } diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 48435cb..ec33b5e 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1441,4 +1441,4 @@ namespace OpenSim.Framework return (diff >= 0) ? diff : (diff + EnvironmentTickCountMask + 1); } } -} +} \ No newline at end of file -- cgit v1.1 From b7457a0a5d70667d741c03483ef00955f604c16f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sun, 18 Apr 2010 19:16:41 +0100 Subject: Update OpenMetaverse libraries to those used in master as of commit 9a781e7 This removes Mono.Security.dll which might help with Mono 2.6.3 compatability issues (notwithstanding the sqlite problem) --- bin/Mono.Security.dll | Bin 289792 -> 0 bytes bin/OpenMetaverse.Http.dll | Bin 36864 -> 0 bytes bin/OpenMetaverse.StructuredData.dll | Bin 102400 -> 102400 bytes bin/OpenMetaverse.dll | Bin 1650688 -> 1691648 bytes bin/OpenMetaverseTypes.dll | Bin 102400 -> 106496 bytes 5 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 bin/Mono.Security.dll delete mode 100644 bin/OpenMetaverse.Http.dll diff --git a/bin/Mono.Security.dll b/bin/Mono.Security.dll deleted file mode 100644 index c027c19..0000000 Binary files a/bin/Mono.Security.dll and /dev/null differ diff --git a/bin/OpenMetaverse.Http.dll b/bin/OpenMetaverse.Http.dll deleted file mode 100644 index dbbe4d3..0000000 Binary files a/bin/OpenMetaverse.Http.dll and /dev/null differ diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index f3244f6..f4992a2 100644 Binary files a/bin/OpenMetaverse.StructuredData.dll and b/bin/OpenMetaverse.StructuredData.dll differ diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index edbf3ce..8751bfc 100644 Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index 95d6021..6c6440e 100644 Binary files a/bin/OpenMetaverseTypes.dll and b/bin/OpenMetaverseTypes.dll differ -- cgit v1.1 From 43acd99bb38de4568614e8ae88ea2daa6797f37d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sun, 18 Apr 2010 19:19:50 +0100 Subject: Slightly tweak README to account for the fact that first-time standalone users may effectively set up their avatar as 'master avatar' in the region configuration stage. --- README.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.txt b/README.txt index ed59bf5..f1a71be 100644 --- a/README.txt +++ b/README.txt @@ -59,7 +59,8 @@ Once you are presented with a prompt that looks like: You have successfully started OpenSim. -Before you can log in you will need to create a user account. You can do +Before you can log in you will need to create a user account if you didn't already create +your user as the "Master Avatar" during the region configuration stage. You can do this by running the "create user" command on the OpenSim console. This will ask you a series of questions such as first name, last name and password. -- cgit v1.1 From 68a4f897b4f39e46c291d180db5062725130392d Mon Sep 17 00:00:00 2001 From: Mike Rieker Date: Sun, 18 Apr 2010 19:19:16 -0400 Subject: This GetScriptErrors() change allows initial XEngine to run in background thread. It should block only for the case of being called by CapsUpdateTaskInventoryScriptAsset(). --- .../Framework/Scenes/SceneObjectPartInventory.cs | 71 ++++++++++++++++++++-- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index d03b464..a2fceb7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -290,7 +290,7 @@ namespace OpenSim.Region.Framework.Scenes m_items.LockItemsForWrite(false); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); - StoreScriptErrors(item.ItemID, GetScriptErrors(item.ItemID)); + StoreScriptErrors(item.ItemID, null); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); return; @@ -319,7 +319,7 @@ namespace OpenSim.Region.Framework.Scenes string script = Utils.BytesToString(asset.Data); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); - StoreScriptErrors(item.ItemID, GetScriptErrors(item.ItemID)); + StoreScriptErrors(item.ItemID, null); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); } @@ -388,12 +388,23 @@ namespace OpenSim.Region.Framework.Scenes /// /// Start a script which is in this prim's inventory. + /// Some processing may occur in the background, but this routine returns asap. /// /// /// A /// public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) { + lock (m_scriptErrors) + { + // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion + m_scriptErrors.Remove(itemId); + } + CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource); + } + + private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) + { m_items.LockItemsForRead(true); if (m_items.ContainsKey(itemId)) { @@ -425,25 +436,38 @@ namespace OpenSim.Region.Framework.Scenes } + /// + /// Start a script which is in this prim's inventory and return any compilation error messages. + /// + /// + /// A + /// public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) { ArrayList errors; + // Indicate to CreateScriptInstanceInternal() we want it to + // post any compilation/loading error messages lock (m_scriptErrors) { - m_scriptErrors.Remove(itemId); + m_scriptErrors[itemId] = null; } - CreateScriptInstance(itemId, startParam, postOnRez, engine, stateSource); + + // Perform compilation/loading + CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource); + + // Wait for and retrieve any errors lock (m_scriptErrors) { - while (!m_scriptErrors.TryGetValue(itemId, out errors)) + while ((errors = m_scriptErrors[itemId]) == null) { if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000)) { m_log.ErrorFormat( "[PRIM INVENTORY]: " + "timedout waiting for script {0} errors", itemId); - if (!m_scriptErrors.TryGetValue(itemId, out errors)) + errors = m_scriptErrors[itemId]; + if (errors == null) { errors = new ArrayList(1); errors.Add("timedout waiting for errors"); @@ -455,14 +479,49 @@ namespace OpenSim.Region.Framework.Scenes } return errors; } + + // Signal to CreateScriptInstanceEr() that compilation/loading is complete private void StoreScriptErrors(UUID itemId, ArrayList errors) { lock (m_scriptErrors) { + // If compilation/loading initiated via CreateScriptInstance(), + // it does not want the errors, so just get out + if (!m_scriptErrors.ContainsKey(itemId)) + { + return; + } + + // Initiated via CreateScriptInstanceEr(), if we know what the + // errors are, save them and wake CreateScriptInstanceEr(). + if (errors != null) + { + m_scriptErrors[itemId] = errors; + System.Threading.Monitor.PulseAll(m_scriptErrors); + return; + } + } + + // Initiated via CreateScriptInstanceEr() but we don't know what + // the errors are yet, so retrieve them from the script engine. + // This may involve some waiting internal to GetScriptErrors(). + errors = GetScriptErrors(itemId); + + // Get a default non-null value to indicate success. + if (errors == null) + { + errors = new ArrayList(); + } + + // Post to CreateScriptInstanceEr() and wake it up + lock (m_scriptErrors) + { m_scriptErrors[itemId] = errors; System.Threading.Monitor.PulseAll(m_scriptErrors); } } + + // Like StoreScriptErrors(), but just posts a single string message private void StoreScriptError(UUID itemId, string message) { ArrayList errors = new ArrayList(1); -- cgit v1.1 From 1667a29c88905e6734c1402a51a9365209114e1d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 19 Apr 2010 12:54:33 +0200 Subject: And some more rez modes that weren't covered before --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 66ed64b..2f1a189 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1281,6 +1281,7 @@ namespace OpenSim.Region.Framework.Scenes // "Rezzed script {0} into prim local ID {1} for user {2}", // item.inventoryName, localID, remoteClient.Name); part.GetProperties(remoteClient); + part.ParentGroup.ResumeScripts(); } else { @@ -1350,6 +1351,7 @@ namespace OpenSim.Region.Framework.Scenes part.GetProperties(remoteClient); part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); + part.ParentGroup.ResumeScripts(); } } -- cgit v1.1 From 80024c023ad134416038b68a29d5e583f5d5e8a0 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 19 Apr 2010 18:44:21 +0200 Subject: Remove the event trigger for the attach event from the attachment module. The script engine already triggers this internally. --- OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 77e73fb..9178a0e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -241,7 +241,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3); // Do this last so that event listeners have access to all the effects of the attachment - m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); + //m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); } else { -- cgit v1.1 From de63b60748e33fb5089a463b7a114bb2de33bb5f Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 19 Apr 2010 19:27:45 +0200 Subject: Avoid duplicate script resumes. Move resume calls to more logical places --- OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 2 +- .../CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 9178a0e..354994b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -239,6 +239,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Fire after attach, so we don't get messy perms dialogs // 3 == AttachedRez objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3); + objatt.ResumeScripts(); // Do this last so that event listeners have access to all the effects of the attachment //m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); @@ -250,7 +251,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments itemID, remoteClient.Name, AttachmentPt); } - objatt.ResumeScripts(); return objatt; } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 32a0df9..2352ced 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -601,6 +601,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0); + rootPart.ParentGroup.ResumeScripts(); rootPart.ScheduleFullUpdate(); } @@ -621,7 +622,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } - rootPart.ParentGroup.ResumeScripts(); return rootPart.ParentGroup; } } -- cgit v1.1 From 780630d7c05f7306ffceb52db0eda1401112f426 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 23 Apr 2010 14:41:20 +0200 Subject: Fix a nullref in attachment handling. Add some debug to find the attachment state issue --- OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 3 ++- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 1 + OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1 + OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 6 ++++++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 354994b..a667b80 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -271,7 +271,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) { InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); - item = m_scene.InventoryService.GetItem(item); + if (m_scene.InventoryService != null) + item = m_scene.InventoryService.GetItem(item); presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e6e414f..44fd2e1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1628,6 +1628,7 @@ namespace OpenSim.Region.Framework.Scenes remoteClient.AgentId); AssetService.Store(asset); + m_log.DebugFormat("[ScriptState]: Saved attachment as asset {0}", asset.FullID); item.AssetID = asset.FullID; item.Description = asset.Description; item.Name = asset.Name; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 84c3719..1f8c732 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -612,6 +612,7 @@ namespace OpenSim.Region.Framework.Scenes { UUID itemid = new UUID(node.Attributes["UUID"].Value); m_savedScriptState.Add(itemid, node.InnerXml); + m_log.DebugFormat("[ScriptState]: Retrieved state for script item ID {0}", itemid.ToString()); } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 04df35a..ce4802d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -333,8 +333,10 @@ namespace OpenSim.Region.Framework.Scenes if (engines == null) // No engine at all return; + m_log.DebugFormat("[ScriptState]: Item ID changed: {0} to {1}", oldID, newID); if (m_part.ParentGroup.m_savedScriptState.ContainsKey(oldID)) { + m_log.DebugFormat("[ScriptState]: Found script state for {0}, applying to new script item {1}", oldID, newID); XmlDocument doc = new XmlDocument(); doc.LoadXml(m_part.ParentGroup.m_savedScriptState[oldID]); @@ -380,6 +382,10 @@ namespace OpenSim.Region.Framework.Scenes } m_part.ParentGroup.m_savedScriptState.Remove(oldID); } + else + { + m_log.DebugFormat("[ScriptState]: No state for old ID {0}", oldID); + } } /// -- cgit v1.1 From 7eda9364fd93906d6657e720681e8c079cb2ce1e Mon Sep 17 00:00:00 2001 From: sacha Date: Fri, 23 Apr 2010 10:51:27 -0400 Subject: Adding LinkUp/LinkDown when a region is started or stoped. Those two events could be used to compute the region availibility --- OpenSim/Region/Application/OpenSimBase.cs | 5 ++--- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index f3aaa76..06bb886 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -350,11 +350,9 @@ namespace OpenSim if (scene.SnmpService != null) { scene.SnmpService.ColdStart(1,scene); + scene.SnmpService.LinkDown(scene); } -// it should be a LinkDown event -// Maped inside opennms -// bad... if (scene.SnmpService != null) { scene.SnmpService.Warning("Loading prins", scene); @@ -439,6 +437,7 @@ namespace OpenSim if (scene.SnmpService != null) { scene.SnmpService.Warning("The region is operational", scene); + scene.SnmpService.LinkUp(scene); } scene.StartTimer(); diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs index 8a83fe9..cc31322 100644 --- a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -15,4 +15,9 @@ public interface ISnmpModule void Major(string Message, Scene scene); void ColdStart(int step , Scene scene); void Shutdown(int step , Scene scene); + // + // Node Start/stop events + // + void LinkUp(Scene scene); + void LinkDown(Scene scene); } -- cgit v1.1 From 31e0704c8d7f6100153ddedd64be7f2ab1ad9311 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 23 Apr 2010 17:48:50 +0200 Subject: Remove debug output, the culprit has been identified --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 1 - OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1 - OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 6 ------ 3 files changed, 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 44fd2e1..e6e414f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1628,7 +1628,6 @@ namespace OpenSim.Region.Framework.Scenes remoteClient.AgentId); AssetService.Store(asset); - m_log.DebugFormat("[ScriptState]: Saved attachment as asset {0}", asset.FullID); item.AssetID = asset.FullID; item.Description = asset.Description; item.Name = asset.Name; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 1f8c732..84c3719 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -612,7 +612,6 @@ namespace OpenSim.Region.Framework.Scenes { UUID itemid = new UUID(node.Attributes["UUID"].Value); m_savedScriptState.Add(itemid, node.InnerXml); - m_log.DebugFormat("[ScriptState]: Retrieved state for script item ID {0}", itemid.ToString()); } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index ce4802d..04df35a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -333,10 +333,8 @@ namespace OpenSim.Region.Framework.Scenes if (engines == null) // No engine at all return; - m_log.DebugFormat("[ScriptState]: Item ID changed: {0} to {1}", oldID, newID); if (m_part.ParentGroup.m_savedScriptState.ContainsKey(oldID)) { - m_log.DebugFormat("[ScriptState]: Found script state for {0}, applying to new script item {1}", oldID, newID); XmlDocument doc = new XmlDocument(); doc.LoadXml(m_part.ParentGroup.m_savedScriptState[oldID]); @@ -382,10 +380,6 @@ namespace OpenSim.Region.Framework.Scenes } m_part.ParentGroup.m_savedScriptState.Remove(oldID); } - else - { - m_log.DebugFormat("[ScriptState]: No state for old ID {0}", oldID); - } } /// -- cgit v1.1 From 85646b157ce0e07ef37e41de72b553bb377243e1 Mon Sep 17 00:00:00 2001 From: sacha Date: Fri, 23 Apr 2010 12:40:27 -0400 Subject: Adding some more SNMP events and some refactoring Signed : The Masqued Foxi --- OpenSim/Region/Application/OpenSimBase.cs | 21 +++++++++++++-------- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 06bb886..1ec96a0 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -355,7 +355,7 @@ namespace OpenSim if (scene.SnmpService != null) { - scene.SnmpService.Warning("Loading prins", scene); + scene.SnmpService.BootInfo("Loading prins", scene); } // Prims have to be loaded after module configuration since some modules may be invoked during the load @@ -363,7 +363,7 @@ namespace OpenSim if (scene.SnmpService != null) { - scene.SnmpService.Warning("Creating region texture", scene); + scene.SnmpService.BootInfo("Creating region texture", scene); } // moved these here as the terrain texture has to be created after the modules are initialized @@ -375,8 +375,8 @@ namespace OpenSim if (scene.SnmpService != null) { - scene.SnmpService.Warning("Grid Registration in progress", scene); - } + scene.SnmpService.BootInfo("Grid Registration in progress", scene); + } try { scene.RegisterRegionWithGrid(); @@ -396,7 +396,7 @@ namespace OpenSim if (scene.SnmpService != null) { - scene.SnmpService.Warning("Grid Registration done", scene); + scene.SnmpService.BootInfo("Grid Registration done", scene); } // We need to do this after we've initialized the @@ -408,7 +408,7 @@ namespace OpenSim if (scene.SnmpService != null) { - scene.SnmpService.Warning("ScriptEngine started", scene); + scene.SnmpService.BootInfo("ScriptEngine started", scene); } m_sceneManager.Add(scene); @@ -421,7 +421,7 @@ namespace OpenSim if (scene.SnmpService != null) { - scene.SnmpService.Warning("Initializing region modules", scene); + scene.SnmpService.BootInfo("Initializing region modules", scene); } if (do_post_init) { @@ -436,7 +436,7 @@ namespace OpenSim if (scene.SnmpService != null) { - scene.SnmpService.Warning("The region is operational", scene); + scene.SnmpService.BootInfo("The region is operational", scene); scene.SnmpService.LinkUp(scene); } @@ -448,6 +448,11 @@ namespace OpenSim private void ShutdownRegion(Scene scene) { m_log.DebugFormat("[SHUTDOWN]: Shutting down region {0}", scene.RegionInfo.RegionName); + if (scene.SnmpService != null) + { + scene.SnmpService.BootInfo("The region is shutting down", scene); + scene.SnmpService.LinkDown(scene); + } IRegionModulesController controller; if (ApplicationRegistry.TryGet(out controller)) { diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs index cc31322..16a243c 100644 --- a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -20,4 +20,5 @@ public interface ISnmpModule // void LinkUp(Scene scene); void LinkDown(Scene scene); + void BootInfo(string data, Scene scene); } -- cgit v1.1 From 56f60a04d943c3270819ac66a3ae80773b6352e1 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 23 Apr 2010 20:18:34 +0200 Subject: Add an additional serialization call do the detach procedure. This call is executed only for it's side effects, which are to block until attach(NULL_KEY) completes, before commencing detachment. --- OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index a667b80..8307467 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -35,6 +35,7 @@ using OpenSim.Framework; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Scenes.Serialization; namespace OpenSim.Region.CoreModules.Avatar.Attachments { @@ -405,6 +406,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (group.GetFromItemID() == itemID) { m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); + // CM / XMREngine!!!! Needed to conclude attach event + SceneObjectSerializer.ToOriginalXmlFormat(group); group.DetachToInventoryPrep(); m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); m_scene.UpdateKnownItem(remoteClient, group,group.GetFromItemID(), group.OwnerID); -- cgit v1.1 From 71f42f185a48ef96391b39fa0197c1a8b793e969 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 24 Apr 2010 16:45:25 +0200 Subject: Plumb a data path to initialize an attachment from an alternate source --- .../Avatar/Attachments/AttachmentsModule.cs | 20 ++++++++++++-- .../InventoryAccess/InventoryAccessModule.cs | 1 + .../Framework/Interfaces/IAttachmentsModule.cs | 7 ++++- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- OpenSim/Services/Interfaces/IAttachmentsService.cs | 31 ++++++++++++++++++++++ 5 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 OpenSim/Services/Interfaces/IAttachmentsService.cs diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 8307467..1992bd4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -27,6 +27,7 @@ using System.Collections.Generic; using System.Reflection; +using System.Xml; using log4net; using Nini.Config; using OpenMetaverse; @@ -191,8 +192,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public UUID RezSingleAttachmentFromInventory( IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus) + { + return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null); + } + + public UUID RezSingleAttachmentFromInventory( + IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc) { - SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(remoteClient, itemID, AttachmentPt); + SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(remoteClient, itemID, AttachmentPt, doc); if (updateInventoryStatus) { @@ -211,7 +218,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( - IClientAPI remoteClient, UUID itemID, uint AttachmentPt) + IClientAPI remoteClient, UUID itemID, uint AttachmentPt, XmlDocument doc) { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); if (invAccess != null) @@ -237,6 +244,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (tainted) objatt.HasGroupChanged = true; + if (doc != null) + objatt.LoadScriptState(doc); + // Fire after attach, so we don't get messy perms dialogs // 3 == AttachedRez objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3); @@ -318,6 +328,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { // XXYY!! InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); + if (item == null) + m_log.Error("[ATTACHMENT]: item == null"); + if (m_scene == null) + m_log.Error("[ATTACHMENT]: m_scene == null"); + if (m_scene.InventoryService == null) + m_log.Error("[ATTACHMENT]: m_scene.InventoryService == null"); item = m_scene.InventoryService.GetItem(item); presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /* att.UUID */); diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 2352ced..c50abb8 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -524,6 +524,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } else { + throw new Exception("AttachTracer"); group.SetFromItemID(itemID); } diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index f8af367..958847b 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -26,6 +26,7 @@ */ using System; +using System.Xml; using OpenMetaverse; using OpenMetaverse.Packets; using OpenSim.Framework; @@ -82,6 +83,10 @@ namespace OpenSim.Region.Framework.Interfaces UUID RezSingleAttachmentFromInventory( IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus); + // Same as above, but also load script states from a separate doc + UUID RezSingleAttachmentFromInventory( + IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc); + /// /// Rez multiple attachments from a user's inventory /// @@ -132,4 +137,4 @@ namespace OpenSim.Region.Framework.Interfaces /// void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient); } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c220bf0..a5c0b0d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3984,7 +3984,7 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); { // Rez from inventory UUID asset - = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); + = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null); m_log.InfoFormat( "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", diff --git a/OpenSim/Services/Interfaces/IAttachmentsService.cs b/OpenSim/Services/Interfaces/IAttachmentsService.cs new file mode 100644 index 0000000..3b9f2f2 --- /dev/null +++ b/OpenSim/Services/Interfaces/IAttachmentsService.cs @@ -0,0 +1,31 @@ +//////////////////////////////////////////////////////////////// +// +// (c) 2009, 2010 Careminster Limited and Melanie Thielker +// +// All rights reserved +// +using System; +using System.Diagnostics; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using System.Reflection; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Server.Base; +using OpenSim.Services.Base; +using OpenSim.Services.Interfaces; +using Nini.Config; +using log4net; +using Careminster; +using OpenMetaverse; + +namespace Careminster +{ + public interface IAttachmentsService + { + string Get(string id); + void Store(string id, string data); + } +} -- cgit v1.1 From 27b3f23ff3c7b040885784b46a90e9523e633e93 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 24 Apr 2010 16:53:47 +0200 Subject: Remove some usings that stopped compilation --- OpenSim/Services/Interfaces/IAttachmentsService.cs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/OpenSim/Services/Interfaces/IAttachmentsService.cs b/OpenSim/Services/Interfaces/IAttachmentsService.cs index 3b9f2f2..bdde369 100644 --- a/OpenSim/Services/Interfaces/IAttachmentsService.cs +++ b/OpenSim/Services/Interfaces/IAttachmentsService.cs @@ -5,23 +5,9 @@ // All rights reserved // using System; -using System.Diagnostics; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading; -using System.Reflection; -using OpenSim.Framework; -using OpenSim.Framework.Console; -using OpenSim.Server.Base; -using OpenSim.Services.Base; -using OpenSim.Services.Interfaces; using Nini.Config; -using log4net; -using Careminster; -using OpenMetaverse; -namespace Careminster +namespace OpenSim.Services.Interfaces { public interface IAttachmentsService { -- cgit v1.1 From 899d521ab41910e09e66849a5c086d7ae32d01a4 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 24 Apr 2010 18:59:34 +0200 Subject: Use the saved script states --- .../InventoryAccess/InventoryAccessModule.cs | 1 - OpenSim/Region/Framework/Scenes/ScenePresence.cs | 37 +++++++++++++++++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index c50abb8..2352ced 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -524,7 +524,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } else { - throw new Exception("AttachTracer"); group.SetFromItemID(itemID); } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index a5c0b0d..ceb4395 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -26,6 +26,7 @@ */ using System; +using System.Xml; using System.Collections.Generic; using System.Reflection; using System.Timers; @@ -3963,6 +3964,32 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); return; } + XmlDocument doc = new XmlDocument(); + string stateData = String.Empty; + + IAttachmentsService attServ = m_scene.RequestModuleInterface(); + if (attServ != null) + { + m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service"); + stateData = attServ.Get(ControllingClient.AgentId.ToString()); + doc.LoadXml(stateData); + } + + Dictionary itemData = new Dictionary(); + + XmlNodeList nodes = doc.GetElementsByTagName("Attachment"); + if (nodes.Count > 0) + { + foreach (XmlNode n in nodes) + { + XmlElement elem = (XmlElement)n; + string itemID = elem.GetAttribute("ItemID"); + string xml = elem.InnerXml; + + itemData[new UUID(itemID)] = xml; + } + } + List attPoints = m_appearance.GetAttachedPoints(); foreach (int p in attPoints) { @@ -3982,9 +4009,17 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); try { + string xmlData; + XmlDocument d = new XmlDocument(); + if (itemData.TryGetValue(itemID, out xmlData)) + { + d.LoadXml(xmlData); + m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID); + } + // Rez from inventory UUID asset - = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null); + = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d); m_log.InfoFormat( "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", -- cgit v1.1 From 81ff5eaba09e7569ef5359874ffcfc7f8855f0b4 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 25 Apr 2010 22:03:35 +0200 Subject: Make scripted attachment states work. Finally. Also replace two monitor locks with RWLocks, hunting the 10^3 bug. Not successful, but needed to be done anyway --- .../Framework/Interfaces/IEntityInventory.cs | 1 + .../Region/Framework/Scenes/SceneObjectGroup.cs | 7 +++- .../Framework/Scenes/SceneObjectPartInventory.cs | 41 +++++++++++++++------- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 4dd50d6..d893890 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -215,5 +215,6 @@ namespace OpenSim.Region.Framework.Interfaces /// A /// Dictionary GetScriptStates(); + Dictionary GetScriptStates(bool oldIDs); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 84c3719..1c6f2d1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1041,6 +1041,11 @@ namespace OpenSim.Region.Framework.Scenes public void SaveScriptedState(XmlTextWriter writer) { + SaveScriptedState(writer, false); + } + + public void SaveScriptedState(XmlTextWriter writer, bool oldIDs) + { XmlDocument doc = new XmlDocument(); Dictionary states = new Dictionary(); @@ -1050,7 +1055,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in m_parts.Values) { - Dictionary pstates = part.Inventory.GetScriptStates(); + Dictionary pstates = part.Inventory.GetScriptStates(oldIDs); foreach (UUID itemid in pstates.Keys) { states.Add(itemid, pstates[itemid]); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 04df35a..f875224 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -311,11 +311,12 @@ namespace OpenSim.Region.Framework.Scenes if (m_part.ParentGroup.m_savedScriptState != null) RestoreSavedScriptState(item.OldItemID, item.ItemID); - lock (m_items) - { - m_items[item.ItemID].PermsMask = 0; - m_items[item.ItemID].PermsGranter = UUID.Zero; - } + m_items.LockItemsForWrite(true); + + m_items[item.ItemID].PermsMask = 0; + m_items[item.ItemID].PermsGranter = UUID.Zero; + + m_items.LockItemsForWrite(false); string script = Utils.BytesToString(asset.Data); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( @@ -713,15 +714,16 @@ namespace OpenSim.Region.Framework.Scenes { IList items = new List(); - lock (m_items) + m_items.LockItemsForRead(true); + + foreach (TaskInventoryItem item in m_items.Values) { - foreach (TaskInventoryItem item in m_items.Values) - { - if (item.Name == name) - items.Add(item); - } + if (item.Name == name) + items.Add(item); } + m_items.LockItemsForRead(false); + return items; } @@ -1115,6 +1117,11 @@ namespace OpenSim.Region.Framework.Scenes public Dictionary GetScriptStates() { + return GetScriptStates(false); + } + + public Dictionary GetScriptStates(bool oldIDs) + { IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); Dictionary ret = new Dictionary(); @@ -1132,8 +1139,16 @@ namespace OpenSim.Region.Framework.Scenes string n = e.GetXMLState(item.ItemID); if (n != String.Empty) { - if (!ret.ContainsKey(item.ItemID)) - ret[item.ItemID] = n; + if (oldIDs) + { + if (!ret.ContainsKey(item.OldItemID)) + ret[item.OldItemID] = n; + } + else + { + if (!ret.ContainsKey(item.ItemID)) + ret[item.ItemID] = n; + } break; } } -- cgit v1.1 From 06661708b4b2ed33116839ced93d43ca0f0909a0 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 27 Apr 2010 02:40:30 +0200 Subject: Add a parameter to prim inventory update to prevent event firing --- OpenSim/Region/Framework/Interfaces/IEntityInventory.cs | 1 + OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index d893890..1e2f60b 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -163,6 +163,7 @@ namespace OpenSim.Region.Framework.Interfaces /// in this prim's inventory. /// false if the item did not exist, true if the update occurred successfully bool UpdateInventoryItem(TaskInventoryItem item); + bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents); /// /// Remove an item from this entity's inventory diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index f875224..bc3225a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -735,6 +735,11 @@ namespace OpenSim.Region.Framework.Scenes /// false if the item did not exist, true if the update occurred successfully public bool UpdateInventoryItem(TaskInventoryItem item) { + return UpdateInventoryItem(item, true); + } + + public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents) + { m_items.LockItemsForWrite(true); if (m_items.ContainsKey(item.ItemID)) @@ -765,7 +770,8 @@ namespace OpenSim.Region.Framework.Scenes m_items[item.ItemID] = item; m_inventorySerial++; - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + if (fireScriptEvents) + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; m_items.LockItemsForWrite(false); -- cgit v1.1 From 5c23b4aa56a9de1baceb833ecba67f66274dca49 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 29 Apr 2010 13:50:11 -0400 Subject: Fix vertical attractor --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 84 ++++++++++++++------------- 1 file changed, 43 insertions(+), 41 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 01c3f81..fbe52c8 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -3395,6 +3395,44 @@ Console.WriteLine(" JointCreateFixed"); //if(frcount == 0) Console.WriteLine("VA = {0}", angObjectVel); + if ( (! m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! angObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) + { // if motor or object have motion + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); + + if (m_angularMotorTimescale < 300.0f) + { + Vector3 attack_error = m_angularMotorDVel - angObjectVel; + float angfactor = m_angularMotorTimescale/timestep; + Vector3 attackAmount = (attack_error/angfactor); + angObjectVel += attackAmount; +//if(frcount == 0) Console.WriteLine("Accel {0} Attk {1}",FrAaccel, attackAmount); +//if(frcount == 0) Console.WriteLine("V2+= {0}", angObjectVel); + } + + angObjectVel.X -= angObjectVel.X / (m_angularFrictionTimescale.X * 0.7f / timestep); + angObjectVel.Y -= angObjectVel.Y / (m_angularFrictionTimescale.Y * 0.7f / timestep); + angObjectVel.Z -= angObjectVel.Z / (m_angularFrictionTimescale.Z * 0.7f / timestep); + } // else no signif. motion + +//if(frcount == 0) Console.WriteLine("Dmotor {0} Obj {1}", m_angularMotorDVel, angObjectVel); + // Bank section tba + // Deflection section tba +//if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); + + + // Rotation Axis Disables: + if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) + { + if (m_angularEnable.X == 0) + angObjectVel.X = 0f; + if (m_angularEnable.Y == 0) + angObjectVel.Y = 0f; + if (m_angularEnable.Z == 0) + angObjectVel.Z = 0f; + } + + angObjectVel = angObjectVel * rotq; // ================ Converts to WORLD rotation + // Vertical attractor section Vector3 vertattr = Vector3.Zero; @@ -3419,8 +3457,9 @@ Console.WriteLine(" JointCreateFixed"); } verterr *= 0.5f; // verterror is 0 (no error) to +/- 1 (max error at 180-deg tilt) - - if ((!angObjectVel.ApproxEquals(Vector3.Zero, 0.001f)) || (verterr.Z < 0.49f)) + Vector3 xyav = angObjectVel; + xyav.Z = 0.0f; + if ((!xyav.ApproxEquals(Vector3.Zero, 0.001f)) || (verterr.Z < 0.49f)) { // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. @@ -3452,46 +3491,9 @@ Console.WriteLine(" JointCreateFixed"); } // else vertical attractor is off //if(frcount == 0) Console.WriteLine("V1 = {0}", angObjectVel); - if ( (! m_angularMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! angObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) - { // if motor or object have motion - if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); - - if (m_angularMotorTimescale < 300.0f) - { - Vector3 attack_error = m_angularMotorDVel - angObjectVel; - float angfactor = m_angularMotorTimescale/timestep; - Vector3 attackAmount = (attack_error/angfactor); - angObjectVel += attackAmount; -//if(frcount == 0) Console.WriteLine("Accel {0} Attk {1}",FrAaccel, attackAmount); -//if(frcount == 0) Console.WriteLine("V2+= {0}", angObjectVel); - } - - angObjectVel.X -= angObjectVel.X / (m_angularFrictionTimescale.X * 0.7f / timestep); - angObjectVel.Y -= angObjectVel.Y / (m_angularFrictionTimescale.Y * 0.7f / timestep); - angObjectVel.Z -= angObjectVel.Z / (m_angularFrictionTimescale.Z * 0.7f / timestep); - } // else no signif. motion - -//if(frcount == 0) Console.WriteLine("Dmotor {0} Obj {1}", m_angularMotorDVel, angObjectVel); - // Bank section tba - // Deflection section tba -//if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); - + m_lastAngularVelocity = angObjectVel; - - if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) - { - if (m_angularEnable.X == 0) - m_lastAngularVelocity.X = 0f; - if (m_angularEnable.Y == 0) - m_lastAngularVelocity.Y = 0f; - if (m_angularEnable.Z == 0) - m_lastAngularVelocity.Z = 0f; - } - // Apply to the body -// Vector3 aInc = m_lastAngularVelocity - initavel; -//if(frcount == 0) Console.WriteLine("Inc {0}", aInc); - m_lastAngularVelocity = m_lastAngularVelocity * rotq; // ================ Converts to WORLD rotation - + // apply Angular Velocity to body d.BodySetAngularVel (Body, m_lastAngularVelocity.X, m_lastAngularVelocity.Y, m_lastAngularVelocity.Z); //if(frcount == 0) Console.WriteLine("V4 = {0}", m_lastAngularVelocity); -- cgit v1.1 From f3c21524be94dac139e15b0cd80b1e79570f7916 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 29 Apr 2010 19:41:08 -0400 Subject: Fix Av jump motion S/W --- OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index 8e87ad9..7a5093b 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -1025,11 +1025,11 @@ namespace OpenSim.Region.Physics.OdePlugin // m_iscolliding includes collisions with the ground. // d.Vector3 pos = d.BodyGetPosition(Body); - if (_target_velocity.X > 0) + if (Math.Abs(_target_velocity.X) > 0) { vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; } - if (_target_velocity.Y > 0) + if (Math.Abs(_target_velocity.Y) > 0) { vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; } -- cgit v1.1 From 9c79fd630819412f4db94c86caea73200933db5d Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 30 Apr 2010 05:33:45 +0100 Subject: Treat a UserLevel of -1 as an unverified account and refer them to their activation email. --- OpenSim/Services/LLLoginService/LLLoginResponse.cs | 5 +++++ OpenSim/Services/LLLoginService/LLLoginService.cs | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index ee30fa3..0cd8f5b 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -57,6 +57,7 @@ namespace OpenSim.Services.LLLoginService public static LLFailedLoginResponse InventoryProblem; public static LLFailedLoginResponse DeadRegionProblem; public static LLFailedLoginResponse LoginBlockedProblem; + public static LLFailedLoginResponse UnverifiedAccountProblem; public static LLFailedLoginResponse AlreadyLoggedInProblem; public static LLFailedLoginResponse InternalError; @@ -80,6 +81,10 @@ namespace OpenSim.Services.LLLoginService LoginBlockedProblem = new LLFailedLoginResponse("presence", "Logins are currently restricted. Please try again later.", "false"); + UnverifiedAccountProblem = new LLFailedLoginResponse("presence", + "Your account has not yet been verified. Please check " + + "your email and click the provided link.", + "false"); AlreadyLoggedInProblem = new LLFailedLoginResponse("presence", "You appear to be already logged in. " + "If this is not the case please wait for your session to timeout. " + diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 4d7dfd1..5301140 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -164,6 +164,12 @@ namespace OpenSim.Services.LLLoginService return LLFailedLoginResponse.UserProblem; } + if (account.UserLevel < 0) + { + m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: Unverified account"); + return LLFailedLoginResponse.UnverifiedAccountProblem; + } + if (account.UserLevel < m_MinLoginLevel) { m_log.InfoFormat("[LLOGIN SERVICE]: Login failed, reason: login is blocked for user level {0}", account.UserLevel); -- cgit v1.1 From 04845c1898fee6a8b8563a8103b73cbe38525416 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 30 Apr 2010 11:46:50 +0100 Subject: Fix link security issue --- OpenSim/Framework/IClientAPI.cs | 2 +- .../Region/ClientStack/LindenUDP/LLClientView.cs | 2 +- .../World/Permissions/PermissionsModule.cs | 4 +- OpenSim/Region/DataSnapshot/ObjectSnapshot.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 50 ++++++++++++++++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 8 ++-- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 41 ++++-------------- 7 files changed, 68 insertions(+), 41 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 222bae0..a6a081d 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -73,7 +73,7 @@ namespace OpenSim.Framework public delegate void LinkObjects(IClientAPI remoteClient, uint parent, List children); - public delegate void DelinkObjects(List primIds); + public delegate void DelinkObjects(List primIds, IClientAPI client); public delegate void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag); diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 8b81377..2ab713d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -6084,7 +6084,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP DelinkObjects handlerDelinkObjects = OnDelinkObjects; if (handlerDelinkObjects != null) { - handlerDelinkObjects(prims); + handlerDelinkObjects(prims, this); } return true; diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 1533462..33e0884 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -1592,7 +1592,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return true; + return GenericObjectPermission(editorID, objectID, false); } private bool CanDelinkObject(UUID userID, UUID objectID) @@ -1600,7 +1600,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return true; + return GenericObjectPermission(editorID, objectID, false); } private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene) diff --git a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs index 76dac61..62666a4 100644 --- a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs +++ b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs @@ -69,7 +69,7 @@ namespace OpenSim.Region.DataSnapshot.Providers byte RayEndIsIntersection) { this.Stale = true; }; client.OnLinkObjects += delegate (IClientAPI remoteClient, uint parent, List children) { this.Stale = true; }; - client.OnDelinkObjects += delegate(List primIds) { this.Stale = true; }; + client.OnDelinkObjects += delegate(List primIds, IClientAPI clientApi) { this.Stale = true; }; client.OnGrabUpdate += delegate(UUID objectID, Vector3 offset, Vector3 grapPos, IClientAPI remoteClient, List surfaceArgs) { this.Stale = true; }; client.OnObjectAttach += delegate(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 5b21332..8716e0a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2568,5 +2568,55 @@ namespace OpenSim.Region.Framework.Scenes part.GetProperties(remoteClient); } } + + public void DelinkObjects(List primIds, IClientAPI client) + { + List parts = new List(); + + foreach (uint localID in primIds) + { + SceneObjectPart part = GetSceneObjectPart(localID); + + if (part == null) + continue; + + if (Permissions.CanDelinkObject(client.AgentId, part.ParentGroup.RootPart.UUID)) + parts.Add(part); + } + + m_sceneGraph.DelinkObjects(parts); + } + + public void LinkObjects(IClientAPI client, uint parentPrimId, List childPrimIds) + { + List owners = new List(); + + List children = new List(); + SceneObjectPart root = GetSceneObjectPart(parentPrimId); + + if (Permissions.CanLinkObject(client.AgentId, root.ParentGroup.RootPart.UUID)) + return; + + foreach (uint localID in childPrimIds) + { + SceneObjectPart part = GetSceneObjectPart(localID); + + if (part == null) + continue; + + if (!owners.Contains(part.OwnerID)) + owners.Add(part.OwnerID); + + if (Permissions.CanLinkObject(client.AgentId, part.ParentGroup.RootPart.UUID)) + children.Add(part); + } + + // Must be all one owner + // + if (owners.Count > 1) + return; + + m_sceneGraph.LinkObjects(root, children); + } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7796b8d..637ebff 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2721,8 +2721,8 @@ namespace OpenSim.Region.Framework.Scenes client.OnObjectName += m_sceneGraph.PrimName; client.OnObjectClickAction += m_sceneGraph.PrimClickAction; client.OnObjectMaterial += m_sceneGraph.PrimMaterial; - client.OnLinkObjects += m_sceneGraph.LinkObjects; - client.OnDelinkObjects += m_sceneGraph.DelinkObjects; + client.OnLinkObjects += LinkObjects; + client.OnDelinkObjects += DelinkObjects; client.OnObjectDuplicate += m_sceneGraph.DuplicateObject; client.OnObjectDuplicateOnRay += doObjectDuplicateOnRay; client.OnUpdatePrimFlags += m_sceneGraph.UpdatePrimFlags; @@ -2877,8 +2877,8 @@ namespace OpenSim.Region.Framework.Scenes client.OnObjectName -= m_sceneGraph.PrimName; client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; client.OnObjectMaterial -= m_sceneGraph.PrimMaterial; - client.OnLinkObjects -= m_sceneGraph.LinkObjects; - client.OnDelinkObjects -= m_sceneGraph.DelinkObjects; + client.OnLinkObjects -= LinkObjects; + client.OnDelinkObjects -= DelinkObjects; client.OnObjectDuplicate -= m_sceneGraph.DuplicateObject; client.OnObjectDuplicateOnRay -= doObjectDuplicateOnRay; client.OnUpdatePrimFlags -= m_sceneGraph.UpdatePrimFlags; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index d31b45e..ad24160 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1619,20 +1619,21 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - protected internal void LinkObjects(IClientAPI client, uint parentPrimId, List childPrimIds) + protected internal void LinkObjects(SceneObjectPart root, List children) { Monitor.Enter(m_updateLock); try { - SceneObjectGroup parentGroup = GetGroupByPrim(parentPrimId); + SceneObjectGroup parentGroup = root.ParentGroup; List childGroups = new List(); if (parentGroup != null) { // We do this in reverse to get the link order of the prims correct - for (int i = childPrimIds.Count - 1; i >= 0; i--) + for (int i = children.Count - 1; i >= 0; i--) { - SceneObjectGroup child = GetGroupByPrim(childPrimIds[i]); + SceneObjectGroup child = children[i].ParentGroup; + if (child != null) { // Make sure no child prim is set for sale @@ -1665,17 +1666,6 @@ namespace OpenSim.Region.Framework.Scenes parentGroup.HasGroupChanged = true; parentGroup.ScheduleGroupForFullUpdate(); -// if (client != null) -// { -// parentGroup.GetProperties(client); -// } -// else -// { -// foreach (ScenePresence p in GetScenePresences()) -// { -// parentGroup.GetProperties(p.ControllingClient); -// } -// } } finally { @@ -1687,12 +1677,7 @@ namespace OpenSim.Region.Framework.Scenes /// Delink a linkset /// /// - protected internal void DelinkObjects(List primIds) - { - DelinkObjects(primIds, true); - } - - protected internal void DelinkObjects(List primIds, bool sendEvents) + protected internal void DelinkObjects(List prims) { Monitor.Enter(m_updateLock); try @@ -1702,9 +1687,8 @@ namespace OpenSim.Region.Framework.Scenes List affectedGroups = new List(); // Look them all up in one go, since that is comparatively expensive // - foreach (uint primID in primIds) + foreach (SceneObjectPart part in prims) { - SceneObjectPart part = m_parentScene.GetSceneObjectPart(primID); if (part != null) { if (part.ParentGroup.Children.Count != 1) // Skip single @@ -1719,17 +1703,13 @@ namespace OpenSim.Region.Framework.Scenes affectedGroups.Add(group); } } - else - { - m_log.ErrorFormat("Viewer requested unlink of nonexistent part {0}", primID); - } } foreach (SceneObjectPart child in childParts) { // Unlink all child parts from their groups // - child.ParentGroup.DelinkFromGroup(child, sendEvents); + child.ParentGroup.DelinkFromGroup(child, true); } foreach (SceneObjectPart root in rootParts) @@ -1784,12 +1764,9 @@ namespace OpenSim.Region.Framework.Scenes List linkIDs = new List(); foreach (SceneObjectPart newChild in newSet) - { newChild.UpdateFlag = 0; - linkIDs.Add(newChild.LocalId); - } - LinkObjects(null, newRoot.LocalId, linkIDs); + LinkObjects(newRoot, newSet); if (!affectedGroups.Contains(newRoot.ParentGroup)) affectedGroups.Add(newRoot.ParentGroup); } -- cgit v1.1 From 9500ba2ff59fc2a47136337a2b06c000b420fd78 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 30 Apr 2010 12:06:58 +0100 Subject: Fix some symbol errors --- OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 86c91ac..212cfee 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -1594,7 +1594,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); + return GenericObjectPermission(userID, objectID, false); } private bool CanDelinkObject(UUID userID, UUID objectID) @@ -1602,7 +1602,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); + return GenericObjectPermission(userID, objectID, false); } private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene) -- cgit v1.1 From 10750421a3c7f9748f9263f587ff2b2350b48249 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 30 Apr 2010 12:06:58 +0100 Subject: Fix some symbol errors --- OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 33e0884..b557186 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -1592,7 +1592,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); + return GenericObjectPermission(userID, objectID, false); } private bool CanDelinkObject(UUID userID, UUID objectID) @@ -1600,7 +1600,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); + return GenericObjectPermission(userID, objectID, false); } private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene) -- cgit v1.1 From 486ab82c027639c62e98ceb8850aaf385f9cef5f Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 30 Apr 2010 12:06:58 +0100 Subject: Fix some symbol errors --- OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index f6bb3fe..69b247c 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -1721,7 +1721,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); + return GenericObjectPermission(userID, objectID, false); } private bool CanDelinkObject(UUID userID, UUID objectID) @@ -1729,7 +1729,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); + return GenericObjectPermission(userID, objectID, false); } private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene) -- cgit v1.1 From 959cd6022504fa3ffe2f69c66ed94827f6ae6951 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Apr 2010 17:17:15 +0100 Subject: Duplicate OpenSim.Data.SQLite into OpenSim.Data.SQLiteNG. SQLiteNG will shortly be changed to work under mono 2.6 and above --- OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs | 65 + OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql | 12 + OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql | 18 + OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql | 9 + .../Data/SQLiteNG/Resources/001_FriendsStore.sql | 10 + .../Data/SQLiteNG/Resources/001_InventoryStore.sql | 32 + .../Data/SQLiteNG/Resources/001_RegionStore.sql | 144 ++ .../Data/SQLiteNG/Resources/001_UserAccount.sql | 17 + OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql | 39 + OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql | 10 + OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql | 5 + .../Data/SQLiteNG/Resources/002_FriendsStore.sql | 5 + .../Data/SQLiteNG/Resources/002_InventoryStore.sql | 8 + .../Data/SQLiteNG/Resources/002_RegionStore.sql | 10 + .../Data/SQLiteNG/Resources/002_UserAccount.sql | 5 + OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql | 5 + OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql | 1 + .../Data/SQLiteNG/Resources/003_InventoryStore.sql | 5 + .../Data/SQLiteNG/Resources/003_RegionStore.sql | 5 + OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql | 6 + OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql | 7 + .../Data/SQLiteNG/Resources/004_InventoryStore.sql | 36 + .../Data/SQLiteNG/Resources/004_RegionStore.sql | 38 + OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql | 6 + .../Data/SQLiteNG/Resources/005_RegionStore.sql | 5 + OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql | 5 + .../Data/SQLiteNG/Resources/006_RegionStore.sql | 102 + OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql | 20 + .../Data/SQLiteNG/Resources/007_RegionStore.sql | 8 + OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql | 7 + .../Data/SQLiteNG/Resources/008_RegionStore.sql | 6 + OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql | 5 + .../Data/SQLiteNG/Resources/009_RegionStore.sql | 8 + OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql | 11 + .../Data/SQLiteNG/Resources/010_RegionStore.sql | 5 + OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql | 37 + .../Data/SQLiteNG/Resources/011_RegionStore.sql | 28 + .../Data/SQLiteNG/Resources/012_RegionStore.sql | 5 + .../Data/SQLiteNG/Resources/013_RegionStore.sql | 6 + .../Data/SQLiteNG/Resources/014_RegionStore.sql | 8 + .../Data/SQLiteNG/Resources/015_RegionStore.sql | 6 + .../Data/SQLiteNG/Resources/016_RegionStore.sql | 5 + .../Data/SQLiteNG/Resources/017_RegionStore.sql | 8 + .../Data/SQLiteNG/Resources/018_RegionStore.sql | 79 + .../Resources/OpenSim.Data.SQLite.addin.xml | 20 + OpenSim/Data/SQLiteNG/SQLiteAssetData.cs | 343 +++ OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs | 262 +++ OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs | 74 + OpenSim/Data/SQLiteNG/SQLiteEstateData.cs | 387 ++++ OpenSim/Data/SQLiteNG/SQLiteFramework.cs | 91 + OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs | 70 + OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs | 268 +++ OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs | 898 ++++++++ OpenSim/Data/SQLiteNG/SQLiteRegionData.cs | 2264 ++++++++++++++++++++ OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs | 81 + OpenSim/Data/SQLiteNG/SQLiteUtils.cs | 307 +++ OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs | 155 ++ OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs | 64 + OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs | 65 + OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs | 66 + OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs | 64 + prebuild.xml | 37 + 62 files changed, 6378 insertions(+) create mode 100644 OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs create mode 100644 OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/001_FriendsStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/001_InventoryStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/001_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/001_UserAccount.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/002_FriendsStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/002_InventoryStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/002_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/002_UserAccount.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/003_InventoryStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/003_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/004_InventoryStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/004_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/005_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/006_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/007_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/008_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/009_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/010_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/011_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/012_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/013_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/014_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/015_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/016_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/017_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/018_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteNG/Resources/OpenSim.Data.SQLite.addin.xml create mode 100644 OpenSim/Data/SQLiteNG/SQLiteAssetData.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteEstateData.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteFramework.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteRegionData.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteUtils.cs create mode 100644 OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs create mode 100644 OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs create mode 100644 OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs create mode 100644 OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs create mode 100644 OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs diff --git a/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..d45ab50 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs @@ -0,0 +1,65 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly : AssemblyTitle("OpenSim.Data.SQLite")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("http://opensimulator.org")] +[assembly : AssemblyProduct("OpenSim.Data.SQLite")] +[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly : ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly : Guid("6113d5ce-4547-49f4-9236-0dcc503457b1")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("0.6.5.*")] +[assembly : AssemblyFileVersion("0.6.5.0")] diff --git a/OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql new file mode 100644 index 0000000..2e026ca --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql @@ -0,0 +1,12 @@ +BEGIN TRANSACTION; +CREATE TABLE assets( + UUID varchar(255) primary key, + Name varchar(255), + Description varchar(255), + Type integer, + InvType integer, + Local integer, + Temporary integer, + Data blob); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql new file mode 100644 index 0000000..468567d --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql @@ -0,0 +1,18 @@ +BEGIN TRANSACTION; + +CREATE TABLE auth ( + UUID char(36) NOT NULL, + passwordHash char(32) NOT NULL default '', + passwordSalt char(32) NOT NULL default '', + webLoginKey varchar(255) NOT NULL default '', + accountType VARCHAR(32) NOT NULL DEFAULT 'UserAccount', + PRIMARY KEY (`UUID`) +); + +CREATE TABLE tokens ( + UUID char(36) NOT NULL, + token varchar(255) NOT NULL, + validity datetime NOT NULL +); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql b/OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql new file mode 100644 index 0000000..7ec906b --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql @@ -0,0 +1,9 @@ +BEGIN TRANSACTION; + +CREATE TABLE Avatars ( + PrincipalID CHAR(36) NOT NULL, + Name VARCHAR(32) NOT NULL, + Value VARCHAR(255) NOT NULL DEFAULT '', + PRIMARY KEY(PrincipalID, Name)); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_FriendsStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_FriendsStore.sql new file mode 100644 index 0000000..f1b9ab9 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/001_FriendsStore.sql @@ -0,0 +1,10 @@ +BEGIN TRANSACTION; + +CREATE TABLE `Friends` ( + `PrincipalID` CHAR(36) NOT NULL, + `Friend` VARCHAR(255) NOT NULL, + `Flags` VARCHAR(16) NOT NULL DEFAULT 0, + `Offered` VARCHAR(32) NOT NULL DEFAULT 0, + PRIMARY KEY(`PrincipalID`, `Friend`)); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_InventoryStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_InventoryStore.sql new file mode 100644 index 0000000..554d5c2 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/001_InventoryStore.sql @@ -0,0 +1,32 @@ +BEGIN TRANSACTION; + +CREATE TABLE inventoryfolders( + UUID varchar(255) primary key, + name varchar(255), + agentID varchar(255), + parentID varchar(255), + type integer, + version integer); + +CREATE TABLE inventoryitems( + UUID varchar(255) primary key, + assetID varchar(255), + assetType integer, + invType integer, + parentFolderID varchar(255), + avatarID varchar(255), + creatorsID varchar(255), + inventoryName varchar(255), + inventoryDescription varchar(255), + inventoryNextPermissions integer, + inventoryCurrentPermissions integer, + inventoryBasePermissions integer, + inventoryEveryOnePermissions integer, + salePrice integer default 99, + saleType integer default 0, + creationDate integer default 2000, + groupID varchar(255) default '00000000-0000-0000-0000-000000000000', + groupOwned integer default 0, + flags integer default 0); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_RegionStore.sql new file mode 100644 index 0000000..39e8180 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/001_RegionStore.sql @@ -0,0 +1,144 @@ +BEGIN TRANSACTION; + +CREATE TABLE prims( + UUID varchar(255) primary key, + RegionUUID varchar(255), + ParentID integer, + CreationDate integer, + Name varchar(255), + SceneGroupID varchar(255), + Text varchar(255), + Description varchar(255), + SitName varchar(255), + TouchName varchar(255), + CreatorID varchar(255), + OwnerID varchar(255), + GroupID varchar(255), + LastOwnerID varchar(255), + OwnerMask integer, + NextOwnerMask integer, + GroupMask integer, + EveryoneMask integer, + BaseMask integer, + PositionX float, + PositionY float, + PositionZ float, + GroupPositionX float, + GroupPositionY float, + GroupPositionZ float, + VelocityX float, + VelocityY float, + VelocityZ float, + AngularVelocityX float, + AngularVelocityY float, + AngularVelocityZ float, + AccelerationX float, + AccelerationY float, + AccelerationZ float, + RotationX float, + RotationY float, + RotationZ float, + RotationW float, + ObjectFlags integer, + SitTargetOffsetX float NOT NULL default 0, + SitTargetOffsetY float NOT NULL default 0, + SitTargetOffsetZ float NOT NULL default 0, + SitTargetOrientW float NOT NULL default 0, + SitTargetOrientX float NOT NULL default 0, + SitTargetOrientY float NOT NULL default 0, + SitTargetOrientZ float NOT NULL default 0); + +CREATE TABLE primshapes( + UUID varchar(255) primary key, + Shape integer, + ScaleX float, + ScaleY float, + ScaleZ float, + PCode integer, + PathBegin integer, + PathEnd integer, + PathScaleX integer, + PathScaleY integer, + PathShearX integer, + PathShearY integer, + PathSkew integer, + PathCurve integer, + PathRadiusOffset integer, + PathRevolutions integer, + PathTaperX integer, + PathTaperY integer, + PathTwist integer, + PathTwistBegin integer, + ProfileBegin integer, + ProfileEnd integer, + ProfileCurve integer, + ProfileHollow integer, + Texture blob, + ExtraParams blob, + State Integer NOT NULL default 0); + +CREATE TABLE primitems( + itemID varchar(255) primary key, + primID varchar(255), + assetID varchar(255), + parentFolderID varchar(255), + invType integer, + assetType integer, + name varchar(255), + description varchar(255), + creationDate integer, + creatorID varchar(255), + ownerID varchar(255), + lastOwnerID varchar(255), + groupID varchar(255), + nextPermissions string, + currentPermissions string, + basePermissions string, + everyonePermissions string, + groupPermissions string); + +CREATE TABLE terrain( + RegionUUID varchar(255), + Revision integer, + Heightfield blob); + +CREATE TABLE land( + UUID varchar(255) primary key, + RegionUUID varchar(255), + LocalLandID string, + Bitmap blob, + Name varchar(255), + Desc varchar(255), + OwnerUUID varchar(255), + IsGroupOwned string, + Area integer, + AuctionID integer, + Category integer, + ClaimDate integer, + ClaimPrice integer, + GroupUUID varchar(255), + SalePrice integer, + LandStatus integer, + LandFlags string, + LandingType string, + MediaAutoScale string, + MediaTextureUUID varchar(255), + MediaURL varchar(255), + MusicURL varchar(255), + PassHours float, + PassPrice string, + SnapshotUUID varchar(255), + UserLocationX float, + UserLocationY float, + UserLocationZ float, + UserLookAtX float, + UserLookAtY float, + UserLookAtZ float, + AuthbuyerID varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'); + +CREATE TABLE landaccesslist( + LandUUID varchar(255), + AccessUUID varchar(255), + Flags string); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_UserAccount.sql b/OpenSim/Data/SQLiteNG/Resources/001_UserAccount.sql new file mode 100644 index 0000000..c38d9a7 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/001_UserAccount.sql @@ -0,0 +1,17 @@ +BEGIN TRANSACTION; + +-- useraccounts table +CREATE TABLE UserAccounts ( + PrincipalID CHAR(36) primary key, + ScopeID CHAR(36) NOT NULL, + FirstName VARCHAR(64) NOT NULL, + LastName VARCHAR(64) NOT NULL, + Email VARCHAR(64), + ServiceURLs TEXT, + Created INT(11), + UserLevel integer NOT NULL DEFAULT 0, + UserFlags integer NOT NULL DEFAULT 0, + UserTitle varchar(64) NOT NULL DEFAULT '' +); + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql new file mode 100644 index 0000000..b584594 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql @@ -0,0 +1,39 @@ +BEGIN TRANSACTION; + +-- users table +CREATE TABLE users( + UUID varchar(255) primary key, + username varchar(255), + surname varchar(255), + passwordHash varchar(255), + passwordSalt varchar(255), + homeRegionX integer, + homeRegionY integer, + homeLocationX float, + homeLocationY float, + homeLocationZ float, + homeLookAtX float, + homeLookAtY float, + homeLookAtZ float, + created integer, + lastLogin integer, + rootInventoryFolderID varchar(255), + userInventoryURI varchar(255), + userAssetURI varchar(255), + profileCanDoMask integer, + profileWantDoMask integer, + profileAboutText varchar(255), + profileFirstText varchar(255), + profileImage varchar(255), + profileFirstImage varchar(255), + webLoginKey text default '00000000-0000-0000-0000-000000000000'); +-- friends table +CREATE TABLE userfriends( + ownerID varchar(255), + friendID varchar(255), + friendPerms integer, + ownerPerms integer, + datetimestamp integer); + +COMMIT; + diff --git a/OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql new file mode 100644 index 0000000..5339b84 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql @@ -0,0 +1,10 @@ +BEGIN TRANSACTION; + +CREATE TEMPORARY TABLE assets_backup(UUID,Name,Description,Type,Local,Temporary,Data); +INSERT INTO assets_backup SELECT UUID,Name,Description,Type,Local,Temporary,Data FROM assets; +DROP TABLE assets; +CREATE TABLE assets(UUID,Name,Description,Type,Local,Temporary,Data); +INSERT INTO assets SELECT UUID,Name,Description,Type,Local,Temporary,Data FROM assets_backup; +DROP TABLE assets_backup; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql new file mode 100644 index 0000000..3237b68 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION; + +INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey) SELECT `UUID` AS UUID, `passwordHash` AS passwordHash, `passwordSalt` AS passwordSalt, `webLoginKey` AS webLoginKey FROM users; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/002_FriendsStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_FriendsStore.sql new file mode 100644 index 0000000..6733502 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/002_FriendsStore.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION; + +INSERT INTO `Friends` SELECT `ownerID`, `friendID`, `friendPerms`, 0 FROM `userfriends`; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/002_InventoryStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_InventoryStore.sql new file mode 100644 index 0000000..01951d6 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/002_InventoryStore.sql @@ -0,0 +1,8 @@ +BEGIN TRANSACTION; + +create index inventoryfolders_agentid on inventoryfolders(agentid); +create index inventoryfolders_parentid on inventoryfolders(parentid); +create index inventoryitems_parentfolderid on inventoryitems(parentfolderid); +create index inventoryitems_avatarid on inventoryitems(avatarid); + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/002_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_RegionStore.sql new file mode 100644 index 0000000..c5c7c99 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/002_RegionStore.sql @@ -0,0 +1,10 @@ +BEGIN TRANSACTION; + +CREATE TABLE regionban( + regionUUID varchar (255), + bannedUUID varchar (255), + bannedIp varchar (255), + bannedIpHostMask varchar (255) + ); + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/002_UserAccount.sql b/OpenSim/Data/SQLiteNG/Resources/002_UserAccount.sql new file mode 100644 index 0000000..c7a6293 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/002_UserAccount.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION; + +INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT `UUID` AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, username AS FirstName, surname AS LastName, '' as Email, '' AS ServiceURLs, created as Created FROM users; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql new file mode 100644 index 0000000..48fc680 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE users add homeRegionID varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql b/OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql new file mode 100644 index 0000000..f54f8d9 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql @@ -0,0 +1 @@ +DELETE FROM assets WHERE UUID = 'dc4b9f0bd00845c696a401dd947ac621' diff --git a/OpenSim/Data/SQLiteNG/Resources/003_InventoryStore.sql b/OpenSim/Data/SQLiteNG/Resources/003_InventoryStore.sql new file mode 100644 index 0000000..4c6da91 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/003_InventoryStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +alter table inventoryitems add column inventoryGroupPermissions integer unsigned not null default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/003_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/003_RegionStore.sql new file mode 100644 index 0000000..4db2f75 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/003_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE primitems add flags integer not null default 0; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql new file mode 100644 index 0000000..6f890ee --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE users add userFlags integer NOT NULL default 0; +ALTER TABLE users add godLevel integer NOT NULL default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql b/OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql new file mode 100644 index 0000000..39421c4 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql @@ -0,0 +1,7 @@ +BEGIN; + +update assets + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/004_InventoryStore.sql b/OpenSim/Data/SQLiteNG/Resources/004_InventoryStore.sql new file mode 100644 index 0000000..e8f4d46 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/004_InventoryStore.sql @@ -0,0 +1,36 @@ +BEGIN; + +update inventoryitems + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update inventoryitems + set assetID = substr(assetID, 1, 8) || "-" || substr(assetID, 9, 4) || "-" || substr(assetID, 13, 4) || "-" || substr(assetID, 17, 4) || "-" || substr(assetID, 21, 12) + where assetID not like '%-%'; + +update inventoryitems + set parentFolderID = substr(parentFolderID, 1, 8) || "-" || substr(parentFolderID, 9, 4) || "-" || substr(parentFolderID, 13, 4) || "-" || substr(parentFolderID, 17, 4) || "-" || substr(parentFolderID, 21, 12) + where parentFolderID not like '%-%'; + +update inventoryitems + set avatarID = substr(avatarID, 1, 8) || "-" || substr(avatarID, 9, 4) || "-" || substr(avatarID, 13, 4) || "-" || substr(avatarID, 17, 4) || "-" || substr(avatarID, 21, 12) + where avatarID not like '%-%'; + +update inventoryitems + set creatorsID = substr(creatorsID, 1, 8) || "-" || substr(creatorsID, 9, 4) || "-" || substr(creatorsID, 13, 4) || "-" || substr(creatorsID, 17, 4) || "-" || substr(creatorsID, 21, 12) + where creatorsID not like '%-%'; + + +update inventoryfolders + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update inventoryfolders + set agentID = substr(agentID, 1, 8) || "-" || substr(agentID, 9, 4) || "-" || substr(agentID, 13, 4) || "-" || substr(agentID, 17, 4) || "-" || substr(agentID, 21, 12) + where agentID not like '%-%'; + +update inventoryfolders + set parentID = substr(parentID, 1, 8) || "-" || substr(parentID, 9, 4) || "-" || substr(parentID, 13, 4) || "-" || substr(parentID, 17, 4) || "-" || substr(parentID, 21, 12) + where parentID not like '%-%'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/004_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/004_RegionStore.sql new file mode 100644 index 0000000..de328cb --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/004_RegionStore.sql @@ -0,0 +1,38 @@ +BEGIN; + +create table regionsettings ( + regionUUID char(36) not null, + block_terraform integer not null, + block_fly integer not null, + allow_damage integer not null, + restrict_pushing integer not null, + allow_land_resell integer not null, + allow_land_join_divide integer not null, + block_show_in_search integer not null, + agent_limit integer not null, + object_bonus float not null, + maturity integer not null, + disable_scripts integer not null, + disable_collisions integer not null, + disable_physics integer not null, + terrain_texture_1 char(36) not null, + terrain_texture_2 char(36) not null, + terrain_texture_3 char(36) not null, + terrain_texture_4 char(36) not null, + elevation_1_nw float not null, + elevation_2_nw float not null, + elevation_1_ne float not null, + elevation_2_ne float not null, + elevation_1_se float not null, + elevation_2_se float not null, + elevation_1_sw float not null, + elevation_2_sw float not null, + water_height float not null, + terrain_raise_limit float not null, + terrain_lower_limit float not null, + use_estate_sun integer not null, + fixed_sun integer not null, + sun_position float not null, + covenant char(36)); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql new file mode 100644 index 0000000..03142af --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE users add customType varchar(32) not null default ''; +ALTER TABLE users add partner char(36) not null default '00000000-0000-0000-0000-000000000000'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/005_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/005_RegionStore.sql new file mode 100644 index 0000000..1f6d1bd --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/005_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +delete from regionsettings; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql new file mode 100644 index 0000000..e45c09a --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +CREATE TABLE `avatarattachments` (`UUID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', `attachpoint` int(11) NOT NULL DEFAULT 0, `item` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', `asset` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/006_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/006_RegionStore.sql new file mode 100644 index 0000000..94ed818 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/006_RegionStore.sql @@ -0,0 +1,102 @@ +BEGIN TRANSACTION; + +CREATE TABLE estate_groups ( + EstateID int(10) NOT NULL, + uuid char(36) NOT NULL +); + +CREATE TABLE estate_managers ( + EstateID int(10) NOT NULL, + uuid char(36) NOT NULL +); + +CREATE TABLE estate_map ( + RegionID char(36) NOT NULL default '00000000-0000-0000-0000-000000000000', + EstateID int(11) NOT NULL +); + +CREATE TABLE estate_settings ( + EstateID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + EstateName varchar(64) default NULL, + AbuseEmailToEstateOwner tinyint(4) NOT NULL, + DenyAnonymous tinyint(4) NOT NULL, + ResetHomeOnTeleport tinyint(4) NOT NULL, + FixedSun tinyint(4) NOT NULL, + DenyTransacted tinyint(4) NOT NULL, + BlockDwell tinyint(4) NOT NULL, + DenyIdentified tinyint(4) NOT NULL, + AllowVoice tinyint(4) NOT NULL, + UseGlobalTime tinyint(4) NOT NULL, + PricePerMeter int(11) NOT NULL, + TaxFree tinyint(4) NOT NULL, + AllowDirectTeleport tinyint(4) NOT NULL, + RedirectGridX int(11) NOT NULL, + RedirectGridY int(11) NOT NULL, + ParentEstateID int(10) NOT NULL, + SunPosition double NOT NULL, + EstateSkipScripts tinyint(4) NOT NULL, + BillableFactor float NOT NULL, + PublicAccess tinyint(4) NOT NULL +); +insert into estate_settings (EstateID,EstateName,AbuseEmailToEstateOwner,DenyAnonymous,ResetHomeOnTeleport,FixedSun,DenyTransacted,BlockDwell,DenyIdentified,AllowVoice,UseGlobalTime,PricePerMeter,TaxFree,AllowDirectTeleport,RedirectGridX,RedirectGridY,ParentEstateID,SunPosition,PublicAccess,EstateSkipScripts,BillableFactor) values ( 99, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''); +delete from estate_settings; +CREATE TABLE estate_users ( + EstateID int(10) NOT NULL, + uuid char(36) NOT NULL +); + +CREATE TABLE estateban ( + EstateID int(10) NOT NULL, + bannedUUID varchar(36) NOT NULL, + bannedIp varchar(16) NOT NULL, + bannedIpHostMask varchar(16) NOT NULL, + bannedNameMask varchar(64) default NULL +); + +drop table regionsettings; +CREATE TABLE regionsettings ( + regionUUID char(36) NOT NULL, + block_terraform int(11) NOT NULL, + block_fly int(11) NOT NULL, + allow_damage int(11) NOT NULL, + restrict_pushing int(11) NOT NULL, + allow_land_resell int(11) NOT NULL, + allow_land_join_divide int(11) NOT NULL, + block_show_in_search int(11) NOT NULL, + agent_limit int(11) NOT NULL, + object_bonus float NOT NULL, + maturity int(11) NOT NULL, + disable_scripts int(11) NOT NULL, + disable_collisions int(11) NOT NULL, + disable_physics int(11) NOT NULL, + terrain_texture_1 char(36) NOT NULL, + terrain_texture_2 char(36) NOT NULL, + terrain_texture_3 char(36) NOT NULL, + terrain_texture_4 char(36) NOT NULL, + elevation_1_nw float NOT NULL, + elevation_2_nw float NOT NULL, + elevation_1_ne float NOT NULL, + elevation_2_ne float NOT NULL, + elevation_1_se float NOT NULL, + elevation_2_se float NOT NULL, + elevation_1_sw float NOT NULL, + elevation_2_sw float NOT NULL, + water_height float NOT NULL, + terrain_raise_limit float NOT NULL, + terrain_lower_limit float NOT NULL, + use_estate_sun int(11) NOT NULL, + fixed_sun int(11) NOT NULL, + sun_position float NOT NULL, + covenant char(36) default NULL, + Sandbox tinyint(4) NOT NULL, + PRIMARY KEY (regionUUID) +); + +CREATE INDEX estate_ban_estate_id on estateban(EstateID); +CREATE INDEX estate_groups_estate_id on estate_groups(EstateID); +CREATE INDEX estate_managers_estate_id on estate_managers(EstateID); +CREATE INDEX estate_map_estate_id on estate_map(EstateID); +CREATE UNIQUE INDEX estate_map_region_id on estate_map(RegionID); +CREATE INDEX estate_users_estate_id on estate_users(EstateID); + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql new file mode 100644 index 0000000..f9454c5 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql @@ -0,0 +1,20 @@ +BEGIN TRANSACTION; + +-- usersagents table +CREATE TABLE IF NOT EXISTS useragents( + UUID varchar(255) primary key, + agentIP varchar(255), + agentPort integer, + agentOnline boolean, + sessionID varchar(255), + secureSessionID varchar(255), + regionID varchar(255), + loginTime integer, + logoutTime integer, + currentRegion varchar(255), + currentHandle varchar(255), + currentPosX float, + currentPosY float, + currentPosZ float); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/007_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/007_RegionStore.sql new file mode 100644 index 0000000..1c813a0 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/007_RegionStore.sql @@ -0,0 +1,8 @@ +begin; + +alter table estate_settings add column AbuseEmail varchar(255) not null default ''; + +alter table estate_settings add column EstateOwner varchar(36) not null default ''; + +commit; + diff --git a/OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql new file mode 100644 index 0000000..8b0cd28 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql @@ -0,0 +1,7 @@ +BEGIN TRANSACTION; + +ALTER TABLE useragents add currentLookAtX float not null default 128; +ALTER TABLE useragents add currentLookAtY float not null default 128; +ALTER TABLE useragents add currentLookAtZ float not null default 70; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/008_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/008_RegionStore.sql new file mode 100644 index 0000000..28bfbf5 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/008_RegionStore.sql @@ -0,0 +1,6 @@ +begin; + +alter table estate_settings add column DenyMinors tinyint not null default 0; + +commit; + diff --git a/OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql new file mode 100644 index 0000000..97da818 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION; + +ALTER TABLE users add email varchar(250); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/009_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/009_RegionStore.sql new file mode 100644 index 0000000..1f40548 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/009_RegionStore.sql @@ -0,0 +1,8 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN ColorR integer not null default 0; +ALTER TABLE prims ADD COLUMN ColorG integer not null default 0; +ALTER TABLE prims ADD COLUMN ColorB integer not null default 0; +ALTER TABLE prims ADD COLUMN ColorA integer not null default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql new file mode 100644 index 0000000..8ab03ef --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql @@ -0,0 +1,11 @@ +BEGIN; + +update users + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update useragents + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/010_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/010_RegionStore.sql new file mode 100644 index 0000000..b91ccf0 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/010_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN ClickAction INTEGER NOT NULL default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql new file mode 100644 index 0000000..5f956da --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql @@ -0,0 +1,37 @@ +BEGIN TRANSACTION; + +CREATE TABLE IF NOT EXISTS avatarappearance( + Owner varchar(36) NOT NULL primary key, + BodyItem varchar(36) DEFAULT NULL, + BodyAsset varchar(36) DEFAULT NULL, + SkinItem varchar(36) DEFAULT NULL, + SkinAsset varchar(36) DEFAULT NULL, + HairItem varchar(36) DEFAULT NULL, + HairAsset varchar(36) DEFAULT NULL, + EyesItem varchar(36) DEFAULT NULL, + EyesAsset varchar(36) DEFAULT NULL, + ShirtItem varchar(36) DEFAULT NULL, + ShirtAsset varchar(36) DEFAULT NULL, + PantsItem varchar(36) DEFAULT NULL, + PantsAsset varchar(36) DEFAULT NULL, + ShoesItem varchar(36) DEFAULT NULL, + ShoesAsset varchar(36) DEFAULT NULL, + SocksItem varchar(36) DEFAULT NULL, + SocksAsset varchar(36) DEFAULT NULL, + JacketItem varchar(36) DEFAULT NULL, + JacketAsset varchar(36) DEFAULT NULL, + GlovesItem varchar(36) DEFAULT NULL, + GlovesAsset varchar(36) DEFAULT NULL, + UnderShirtItem varchar(36) DEFAULT NULL, + UnderShirtAsset varchar(36) DEFAULT NULL, + UnderPantsItem varchar(36) DEFAULT NULL, + UnderPantsAsset varchar(36) DEFAULT NULL, + SkirtItem varchar(36) DEFAULT NULL, + SkirtAsset varchar(36) DEFAULT NULL, + Texture blob, + VisualParams blob, + Serial int DEFAULT NULL, + AvatarHeight float DEFAULT NULL +); + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/011_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/011_RegionStore.sql new file mode 100644 index 0000000..42bef89 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/011_RegionStore.sql @@ -0,0 +1,28 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN PayPrice INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN PayButton1 INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN PayButton2 INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN PayButton3 INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN PayButton4 INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN LoopedSound varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'; +ALTER TABLE prims ADD COLUMN LoopedSoundGain float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN TextureAnimation string; +ALTER TABLE prims ADD COLUMN ParticleSystem string; +ALTER TABLE prims ADD COLUMN OmegaX float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN OmegaY float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN OmegaZ float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraEyeOffsetX float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraEyeOffsetY float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraEyeOffsetZ float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraAtOffsetX float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraAtOffsetY float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraAtOffsetZ float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN ForceMouselook string NOT NULL default 0; +ALTER TABLE prims ADD COLUMN ScriptAccessPin INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN AllowedDrop INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN DieAtEdge string NOT NULL default 0; +ALTER TABLE prims ADD COLUMN SalePrice INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN SaleType string NOT NULL default 0; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/012_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/012_RegionStore.sql new file mode 100644 index 0000000..d952b78 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/012_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN Material INTEGER NOT NULL default 3; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/013_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/013_RegionStore.sql new file mode 100644 index 0000000..11529cd --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/013_RegionStore.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE land ADD COLUMN OtherCleanTime INTEGER NOT NULL default 0; +ALTER TABLE land ADD COLUMN Dwell INTEGER NOT NULL default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/014_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/014_RegionStore.sql new file mode 100644 index 0000000..c59b27e --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/014_RegionStore.sql @@ -0,0 +1,8 @@ +begin; + +ALTER TABLE regionsettings ADD COLUMN sunvectorx double NOT NULL default 0; +ALTER TABLE regionsettings ADD COLUMN sunvectory double NOT NULL default 0; +ALTER TABLE regionsettings ADD COLUMN sunvectorz double NOT NULL default 0; + +commit; + diff --git a/OpenSim/Data/SQLiteNG/Resources/015_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/015_RegionStore.sql new file mode 100644 index 0000000..c43f356 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/015_RegionStore.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN CollisionSound varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'; +ALTER TABLE prims ADD COLUMN CollisionSoundVolume float NOT NULL default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/016_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/016_RegionStore.sql new file mode 100644 index 0000000..52f160c --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/016_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN VolumeDetect INTEGER NOT NULL DEFAULT 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/017_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/017_RegionStore.sql new file mode 100644 index 0000000..6c6b7b5 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/017_RegionStore.sql @@ -0,0 +1,8 @@ +BEGIN; +CREATE TEMPORARY TABLE prims_backup(UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect); +INSERT INTO prims_backup SELECT UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect FROM prims; +DROP TABLE prims; +CREATE TABLE prims(UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect); +INSERT INTO prims SELECT UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect FROM prims_backup; +DROP TABLE prims_backup; +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/018_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/018_RegionStore.sql new file mode 100644 index 0000000..6a390c2 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/018_RegionStore.sql @@ -0,0 +1,79 @@ +BEGIN; + +update terrain + set RegionUUID = substr(RegionUUID, 1, 8) || "-" || substr(RegionUUID, 9, 4) || "-" || substr(RegionUUID, 13, 4) || "-" || substr(RegionUUID, 17, 4) || "-" || substr(RegionUUID, 21, 12) + where RegionUUID not like '%-%'; + + +update landaccesslist + set LandUUID = substr(LandUUID, 1, 8) || "-" || substr(LandUUID, 9, 4) || "-" || substr(LandUUID, 13, 4) || "-" || substr(LandUUID, 17, 4) || "-" || substr(LandUUID, 21, 12) + where LandUUID not like '%-%'; + +update landaccesslist + set AccessUUID = substr(AccessUUID, 1, 8) || "-" || substr(AccessUUID, 9, 4) || "-" || substr(AccessUUID, 13, 4) || "-" || substr(AccessUUID, 17, 4) || "-" || substr(AccessUUID, 21, 12) + where AccessUUID not like '%-%'; + + +update prims + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update prims + set RegionUUID = substr(RegionUUID, 1, 8) || "-" || substr(RegionUUID, 9, 4) || "-" || substr(RegionUUID, 13, 4) || "-" || substr(RegionUUID, 17, 4) || "-" || substr(RegionUUID, 21, 12) + where RegionUUID not like '%-%'; + +update prims + set SceneGroupID = substr(SceneGroupID, 1, 8) || "-" || substr(SceneGroupID, 9, 4) || "-" || substr(SceneGroupID, 13, 4) || "-" || substr(SceneGroupID, 17, 4) || "-" || substr(SceneGroupID, 21, 12) + where SceneGroupID not like '%-%'; + +update prims + set CreatorID = substr(CreatorID, 1, 8) || "-" || substr(CreatorID, 9, 4) || "-" || substr(CreatorID, 13, 4) || "-" || substr(CreatorID, 17, 4) || "-" || substr(CreatorID, 21, 12) + where CreatorID not like '%-%'; + +update prims + set OwnerID = substr(OwnerID, 1, 8) || "-" || substr(OwnerID, 9, 4) || "-" || substr(OwnerID, 13, 4) || "-" || substr(OwnerID, 17, 4) || "-" || substr(OwnerID, 21, 12) + where OwnerID not like '%-%'; + +update prims + set GroupID = substr(GroupID, 1, 8) || "-" || substr(GroupID, 9, 4) || "-" || substr(GroupID, 13, 4) || "-" || substr(GroupID, 17, 4) || "-" || substr(GroupID, 21, 12) + where GroupID not like '%-%'; + +update prims + set LastOwnerID = substr(LastOwnerID, 1, 8) || "-" || substr(LastOwnerID, 9, 4) || "-" || substr(LastOwnerID, 13, 4) || "-" || substr(LastOwnerID, 17, 4) || "-" || substr(LastOwnerID, 21, 12) + where LastOwnerID not like '%-%'; + + +update primshapes + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + + +update land + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update land + set RegionUUID = substr(RegionUUID, 1, 8) || "-" || substr(RegionUUID, 9, 4) || "-" || substr(RegionUUID, 13, 4) || "-" || substr(RegionUUID, 17, 4) || "-" || substr(RegionUUID, 21, 12) + where RegionUUID not like '%-%'; + +update land + set OwnerUUID = substr(OwnerUUID, 1, 8) || "-" || substr(OwnerUUID, 9, 4) || "-" || substr(OwnerUUID, 13, 4) || "-" || substr(OwnerUUID, 17, 4) || "-" || substr(OwnerUUID, 21, 12) + where OwnerUUID not like '%-%'; + +update land + set GroupUUID = substr(GroupUUID, 1, 8) || "-" || substr(GroupUUID, 9, 4) || "-" || substr(GroupUUID, 13, 4) || "-" || substr(GroupUUID, 17, 4) || "-" || substr(GroupUUID, 21, 12) + where GroupUUID not like '%-%'; + +update land + set MediaTextureUUID = substr(MediaTextureUUID, 1, 8) || "-" || substr(MediaTextureUUID, 9, 4) || "-" || substr(MediaTextureUUID, 13, 4) || "-" || substr(MediaTextureUUID, 17, 4) || "-" || substr(MediaTextureUUID, 21, 12) + where MediaTextureUUID not like '%-%'; + +update land + set SnapshotUUID = substr(SnapshotUUID, 1, 8) || "-" || substr(SnapshotUUID, 9, 4) || "-" || substr(SnapshotUUID, 13, 4) || "-" || substr(SnapshotUUID, 17, 4) || "-" || substr(SnapshotUUID, 21, 12) + where SnapshotUUID not like '%-%'; + +update land + set AuthbuyerID = substr(AuthbuyerID, 1, 8) || "-" || substr(AuthbuyerID, 9, 4) || "-" || substr(AuthbuyerID, 13, 4) || "-" || substr(AuthbuyerID, 17, 4) || "-" || substr(AuthbuyerID, 21, 12) + where AuthbuyerID not like '%-%'; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/OpenSim.Data.SQLite.addin.xml b/OpenSim/Data/SQLiteNG/Resources/OpenSim.Data.SQLite.addin.xml new file mode 100644 index 0000000..e6764fa --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Resources/OpenSim.Data.SQLite.addin.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs b/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs new file mode 100644 index 0000000..a032670 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs @@ -0,0 +1,343 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Data; +using System.Reflection; +using System.Collections.Generic; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.SQLite +{ + /// + /// An asset storage interface for the SQLite database system + /// + public class SQLiteAssetData : AssetDataBase + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const string SelectAssetSQL = "select * from assets where UUID=:UUID"; + private const string SelectAssetMetadataSQL = "select Name, Description, Type, Temporary, UUID from assets limit :start, :count"; + private const string DeleteAssetSQL = "delete from assets where UUID=:UUID"; + private const string InsertAssetSQL = "insert into assets(UUID, Name, Description, Type, Local, Temporary, Data) values(:UUID, :Name, :Description, :Type, :Local, :Temporary, :Data)"; + private const string UpdateAssetSQL = "update assets set Name=:Name, Description=:Description, Type=:Type, Local=:Local, Temporary=:Temporary, Data=:Data where UUID=:UUID"; + private const string assetSelect = "select * from assets"; + + private SqliteConnection m_conn; + + override public void Dispose() + { + if (m_conn != null) + { + m_conn.Close(); + m_conn = null; + } + } + + /// + /// + /// Initialises AssetData interface + /// Loads and initialises a new SQLite connection and maintains it. + /// use default URI if connect string is empty. + /// + /// + /// connect string + override public void Initialise(string dbconnect) + { + if (dbconnect == string.Empty) + { + dbconnect = "URI=file:Asset.db,version=3"; + } + m_conn = new SqliteConnection(dbconnect); + m_conn.Open(); + + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_conn, assem, "AssetStore"); + m.Update(); + + return; + } + + /// + /// Fetch Asset + /// + /// UUID of ... ? + /// Asset base + override public AssetBase GetAsset(UUID uuid) + { + lock (this) + { + using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); + using (IDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + AssetBase asset = buildAsset(reader); + reader.Close(); + return asset; + } + else + { + reader.Close(); + return null; + } + } + } + } + } + + /// + /// Create an asset + /// + /// Asset Base + override public void StoreAsset(AssetBase asset) + { + //m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString()); + if (ExistsAsset(asset.FullID)) + { + //LogAssetLoad(asset); + + lock (this) + { + using (SqliteCommand cmd = new SqliteCommand(UpdateAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", asset.FullID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Name", asset.Name)); + cmd.Parameters.Add(new SqliteParameter(":Description", asset.Description)); + cmd.Parameters.Add(new SqliteParameter(":Type", asset.Type)); + cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); + cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); + cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); + + cmd.ExecuteNonQuery(); + } + } + } + else + { + lock (this) + { + using (SqliteCommand cmd = new SqliteCommand(InsertAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", asset.FullID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Name", asset.Name)); + cmd.Parameters.Add(new SqliteParameter(":Description", asset.Description)); + cmd.Parameters.Add(new SqliteParameter(":Type", asset.Type)); + cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); + cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); + cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); + + cmd.ExecuteNonQuery(); + } + } + } + } + +// /// +// /// Some... logging functionnality +// /// +// /// +// private static void LogAssetLoad(AssetBase asset) +// { +// string temporary = asset.Temporary ? "Temporary" : "Stored"; +// string local = asset.Local ? "Local" : "Remote"; +// +// int assetLength = (asset.Data != null) ? asset.Data.Length : 0; +// +// m_log.Debug("[ASSET DB]: " + +// string.Format("Loaded {5} {4} Asset: [{0}][{3}] \"{1}\":{2} ({6} bytes)", +// asset.FullID, asset.Name, asset.Description, asset.Type, +// temporary, local, assetLength)); +// } + + /// + /// Check if an asset exist in database + /// + /// The asset UUID + /// True if exist, or false. + override public bool ExistsAsset(UUID uuid) + { + lock (this) { + using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); + using (IDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + reader.Close(); + return true; + } + else + { + reader.Close(); + return false; + } + } + } + } + } + + /// + /// Delete an asset from database + /// + /// + public void DeleteAsset(UUID uuid) + { + using (SqliteCommand cmd = new SqliteCommand(DeleteAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); + + cmd.ExecuteNonQuery(); + } + } + + /// + /// + /// + /// + /// + private static AssetBase buildAsset(IDataReader row) + { + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + AssetBase asset = new AssetBase( + new UUID((String)row["UUID"]), + (String)row["Name"], + Convert.ToSByte(row["Type"]), + UUID.Zero.ToString() + ); + + asset.Description = (String) row["Description"]; + asset.Local = Convert.ToBoolean(row["Local"]); + asset.Temporary = Convert.ToBoolean(row["Temporary"]); + asset.Data = (byte[]) row["Data"]; + return asset; + } + + private static AssetMetadata buildAssetMetadata(IDataReader row) + { + AssetMetadata metadata = new AssetMetadata(); + + metadata.FullID = new UUID((string) row["UUID"]); + metadata.Name = (string) row["Name"]; + metadata.Description = (string) row["Description"]; + metadata.Type = Convert.ToSByte(row["Type"]); + metadata.Temporary = Convert.ToBoolean(row["Temporary"]); // Not sure if this is correct. + + // Current SHA1s are not stored/computed. + metadata.SHA1 = new byte[] {}; + + return metadata; + } + + /// + /// Returns a list of AssetMetadata objects. The list is a subset of + /// the entire data set offset by containing + /// elements. + /// + /// The number of results to discard from the total data set. + /// The number of rows the returned list should contain. + /// A list of AssetMetadata objects. + public override List FetchAssetMetadataSet(int start, int count) + { + List retList = new List(count); + + lock (this) + { + using (SqliteCommand cmd = new SqliteCommand(SelectAssetMetadataSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":start", start)); + cmd.Parameters.Add(new SqliteParameter(":count", count)); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + AssetMetadata metadata = buildAssetMetadata(reader); + retList.Add(metadata); + } + } + } + } + + return retList; + } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + #region IPlugin interface + + /// + /// + /// + override public string Version + { + get + { + Module module = GetType().Module; + // string dllName = module.Assembly.ManifestModule.Name; + Version dllVersion = module.Assembly.GetName().Version; + + return + string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, + dllVersion.Revision); + } + } + + /// + /// Initialise the AssetData interface using default URI + /// + override public void Initialise() + { + Initialise("URI=file:Asset.db,version=3"); + } + + /// + /// Name of this DB provider + /// + override public string Name + { + get { return "SQLite Asset storage engine"; } + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs new file mode 100644 index 0000000..aa10734 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs @@ -0,0 +1,262 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLite +{ + public class SQLiteAuthenticationData : SQLiteFramework, IAuthenticationData + { + private string m_Realm; + private List m_ColumnNames; + private int m_LastExpire; + private string m_connectionString; + + protected static SqliteConnection m_Connection; + private static bool m_initialized = false; + + public SQLiteAuthenticationData(string connectionString, string realm) + : base(connectionString) + { + m_Realm = realm; + m_connectionString = connectionString; + + if (!m_initialized) + { + m_Connection = new SqliteConnection(connectionString); + m_Connection.Open(); + + using (SqliteConnection dbcon = (SqliteConnection)((ICloneable)m_Connection).Clone()) + { + dbcon.Open(); + Migration m = new Migration(dbcon, GetType().Assembly, "AuthStore"); + m.Update(); + dbcon.Close(); + } + + m_initialized = true; + } + } + + public AuthenticationData Get(UUID principalID) + { + AuthenticationData ret = new AuthenticationData(); + ret.Data = new Dictionary(); + + SqliteCommand cmd = new SqliteCommand("select * from `" + m_Realm + "` where UUID = :PrincipalID"); + cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); + + IDataReader result = ExecuteReader(cmd, m_Connection); + + try + { + if (result.Read()) + { + ret.PrincipalID = principalID; + + if (m_ColumnNames == null) + { + m_ColumnNames = new List(); + + DataTable schemaTable = result.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + m_ColumnNames.Add(row["ColumnName"].ToString()); + } + + foreach (string s in m_ColumnNames) + { + if (s == "UUID") + continue; + + ret.Data[s] = result[s].ToString(); + } + + return ret; + } + else + { + return null; + } + } + catch + { + } + finally + { + CloseCommand(cmd); + } + + return null; + } + + public bool Store(AuthenticationData data) + { + if (data.Data.ContainsKey("UUID")) + data.Data.Remove("UUID"); + + string[] fields = new List(data.Data.Keys).ToArray(); + string[] values = new string[data.Data.Count]; + int i = 0; + foreach (object o in data.Data.Values) + values[i++] = o.ToString(); + + SqliteCommand cmd = new SqliteCommand(); + + if (Get(data.PrincipalID) != null) + { + + + string update = "update `" + m_Realm + "` set "; + bool first = true; + foreach (string field in fields) + { + if (!first) + update += ", "; + update += "`" + field + "` = :" + field; + cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); + + first = false; + } + + update += " where UUID = :UUID"; + cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); + + cmd.CommandText = update; + try + { + if (ExecuteNonQuery(cmd, m_Connection) < 1) + { + CloseCommand(cmd); + return false; + } + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + CloseCommand(cmd); + return false; + } + } + + else + { + string insert = "insert into `" + m_Realm + "` (`UUID`, `" + + String.Join("`, `", fields) + + "`) values (:UUID, :" + String.Join(", :", fields) + ")"; + + cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); + foreach (string field in fields) + cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); + + cmd.CommandText = insert; + + try + { + if (ExecuteNonQuery(cmd, m_Connection) < 1) + { + CloseCommand(cmd); + return false; + } + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + CloseCommand(cmd); + return false; + } + } + + CloseCommand(cmd); + + return true; + } + + public bool SetDataItem(UUID principalID, string item, string value) + { + SqliteCommand cmd = new SqliteCommand("update `" + m_Realm + + "` set `" + item + "` = " + value + " where UUID = '" + principalID.ToString() + "'"); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; + + return false; + } + + public bool SetToken(UUID principalID, string token, int lifetime) + { + if (System.Environment.TickCount - m_LastExpire > 30000) + DoExpire(); + + SqliteCommand cmd = new SqliteCommand("insert into tokens (UUID, token, validity) values ('" + principalID.ToString() + + "', '" + token + "', datetime('now', 'localtime', '+" + lifetime.ToString() + " minutes'))"); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + { + cmd.Dispose(); + return true; + } + + cmd.Dispose(); + return false; + } + + public bool CheckToken(UUID principalID, string token, int lifetime) + { + if (System.Environment.TickCount - m_LastExpire > 30000) + DoExpire(); + + SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now', 'localtime', '+" + lifetime.ToString() + + " minutes') where UUID = '" + principalID.ToString() + "' and token = '" + token + "' and validity > datetime('now', 'localtime')"); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + { + cmd.Dispose(); + return true; + } + + cmd.Dispose(); + + return false; + } + + private void DoExpire() + { + SqliteCommand cmd = new SqliteCommand("delete from tokens where validity < datetime('now', 'localtime')"); + ExecuteNonQuery(cmd, m_Connection); + + cmd.Dispose(); + + m_LastExpire = System.Environment.TickCount; + } + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs b/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs new file mode 100644 index 0000000..b3f4a4c --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs @@ -0,0 +1,74 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using System.Threading; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLite +{ + /// + /// A SQLite Interface for Avatar Data + /// + public class SQLiteAvatarData : SQLiteGenericTableHandler, + IAvatarData + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public SQLiteAvatarData(string connectionString, string realm) : + base(connectionString, realm, "Avatar") + { + } + + public bool Delete(UUID principalID, string name) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("delete from {0} where `PrincipalID` = :PrincipalID and `Name` = :Name", m_Realm); + cmd.Parameters.Add(":PrincipalID", principalID.ToString()); + cmd.Parameters.Add(":Name", name); + + try + { + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; + + return false; + } + finally + { + CloseCommand(cmd); + } + } + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs b/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs new file mode 100644 index 0000000..bd6b776 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs @@ -0,0 +1,387 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Data.SQLite +{ + public class SQLiteEstateStore : IEstateDataStore + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private SqliteConnection m_connection; + private string m_connectionString; + + private FieldInfo[] m_Fields; + private Dictionary m_FieldMap = + new Dictionary(); + + public void Initialise(string connectionString) + { + m_connectionString = connectionString; + + m_log.Info("[ESTATE DB]: Sqlite - connecting: "+m_connectionString); + + m_connection = new SqliteConnection(m_connectionString); + m_connection.Open(); + + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_connection, assem, "EstateStore"); + m.Update(); + + m_connection.Close(); + m_connection.Open(); + + Type t = typeof(EstateSettings); + m_Fields = t.GetFields(BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.DeclaredOnly); + + foreach (FieldInfo f in m_Fields) + if (f.Name.Substring(0, 2) == "m_") + m_FieldMap[f.Name.Substring(2)] = f; + } + + private string[] FieldList + { + get { return new List(m_FieldMap.Keys).ToArray(); } + } + + public EstateSettings LoadEstateSettings(UUID regionID, bool create) + { + string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = :RegionID"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + cmd.Parameters.Add(":RegionID", regionID.ToString()); + + return DoLoad(cmd, regionID, create); + } + + private EstateSettings DoLoad(SqliteCommand cmd, UUID regionID, bool create) + { + EstateSettings es = new EstateSettings(); + es.OnSave += StoreEstateSettings; + + IDataReader r = cmd.ExecuteReader(); + + if (r.Read()) + { + foreach (string name in FieldList) + { + if (m_FieldMap[name].GetValue(es) is bool) + { + int v = Convert.ToInt32(r[name]); + if (v != 0) + m_FieldMap[name].SetValue(es, true); + else + m_FieldMap[name].SetValue(es, false); + } + else if (m_FieldMap[name].GetValue(es) is UUID) + { + UUID uuid = UUID.Zero; + + UUID.TryParse(r[name].ToString(), out uuid); + m_FieldMap[name].SetValue(es, uuid); + } + else + { + m_FieldMap[name].SetValue(es, Convert.ChangeType(r[name], m_FieldMap[name].FieldType)); + } + } + r.Close(); + } + else if (create) + { + r.Close(); + + List names = new List(FieldList); + + names.Remove("EstateID"); + + string sql = "insert into estate_settings ("+String.Join(",", names.ToArray())+") values ( :"+String.Join(", :", names.ToArray())+")"; + + cmd.CommandText = sql; + cmd.Parameters.Clear(); + + foreach (string name in FieldList) + { + if (m_FieldMap[name].GetValue(es) is bool) + { + if ((bool)m_FieldMap[name].GetValue(es)) + cmd.Parameters.Add(":"+name, "1"); + else + cmd.Parameters.Add(":"+name, "0"); + } + else + { + cmd.Parameters.Add(":"+name, m_FieldMap[name].GetValue(es).ToString()); + } + } + + cmd.ExecuteNonQuery(); + + cmd.CommandText = "select LAST_INSERT_ROWID() as id"; + cmd.Parameters.Clear(); + + r = cmd.ExecuteReader(); + + r.Read(); + + es.EstateID = Convert.ToUInt32(r["id"]); + + r.Close(); + + cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; + cmd.Parameters.Add(":RegionID", regionID.ToString()); + cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + + // This will throw on dupe key + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception) + { + } + + es.Save(); + } + + LoadBanList(es); + + es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers"); + es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users"); + es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups"); + return es; + } + + public void StoreEstateSettings(EstateSettings es) + { + List fields = new List(FieldList); + fields.Remove("EstateID"); + + List terms = new List(); + + foreach (string f in fields) + terms.Add(f+" = :"+f); + + string sql = "update estate_settings set "+String.Join(", ", terms.ToArray())+" where EstateID = :EstateID"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + + foreach (string name in FieldList) + { + if (m_FieldMap[name].GetValue(es) is bool) + { + if ((bool)m_FieldMap[name].GetValue(es)) + cmd.Parameters.Add(":"+name, "1"); + else + cmd.Parameters.Add(":"+name, "0"); + } + else + { + cmd.Parameters.Add(":"+name, m_FieldMap[name].GetValue(es).ToString()); + } + } + + cmd.ExecuteNonQuery(); + + SaveBanList(es); + SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers); + SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess); + SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups); + } + + private void LoadBanList(EstateSettings es) + { + es.ClearBans(); + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "select bannedUUID from estateban where EstateID = :EstateID"; + cmd.Parameters.Add(":EstateID", es.EstateID); + + IDataReader r = cmd.ExecuteReader(); + + while (r.Read()) + { + EstateBan eb = new EstateBan(); + + UUID uuid = new UUID(); + UUID.TryParse(r["bannedUUID"].ToString(), out uuid); + + eb.BannedUserID = uuid; + eb.BannedHostAddress = "0.0.0.0"; + eb.BannedHostIPMask = "0.0.0.0"; + es.AddBan(eb); + } + r.Close(); + } + + private void SaveBanList(EstateSettings es) + { + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "delete from estateban where EstateID = :EstateID"; + cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + + cmd.ExecuteNonQuery(); + + cmd.Parameters.Clear(); + + cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( :EstateID, :bannedUUID, '', '', '' )"; + + foreach (EstateBan b in es.EstateBans) + { + cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + cmd.Parameters.Add(":bannedUUID", b.BannedUserID.ToString()); + + cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + } + } + + void SaveUUIDList(uint EstateID, string table, UUID[] data) + { + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "delete from "+table+" where EstateID = :EstateID"; + cmd.Parameters.Add(":EstateID", EstateID.ToString()); + + cmd.ExecuteNonQuery(); + + cmd.Parameters.Clear(); + + cmd.CommandText = "insert into "+table+" (EstateID, uuid) values ( :EstateID, :uuid )"; + + foreach (UUID uuid in data) + { + cmd.Parameters.Add(":EstateID", EstateID.ToString()); + cmd.Parameters.Add(":uuid", uuid.ToString()); + + cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + } + } + + UUID[] LoadUUIDList(uint EstateID, string table) + { + List uuids = new List(); + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "select uuid from "+table+" where EstateID = :EstateID"; + cmd.Parameters.Add(":EstateID", EstateID); + + IDataReader r = cmd.ExecuteReader(); + + while (r.Read()) + { + // EstateBan eb = new EstateBan(); + + UUID uuid = new UUID(); + UUID.TryParse(r["uuid"].ToString(), out uuid); + + uuids.Add(uuid); + } + r.Close(); + + return uuids.ToArray(); + } + + public EstateSettings LoadEstateSettings(int estateID) + { + string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID :EstateID"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + cmd.Parameters.Add(":EstateID", estateID.ToString()); + + return DoLoad(cmd, UUID.Zero, false); + } + + public List GetEstates(string search) + { + List result = new List(); + + string sql = "select EstateID from estate_settings where estate_settings.EstateName :EstateName"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + cmd.Parameters.Add(":EstateName", search); + + IDataReader r = cmd.ExecuteReader(); + + while (r.Read()) + { + result.Add(Convert.ToInt32(r["EstateID"])); + } + r.Close(); + + return result; + } + + public bool LinkRegion(UUID regionID, int estateID) + { + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; + cmd.Parameters.Add(":RegionID", regionID.ToString()); + cmd.Parameters.Add(":EstateID", estateID.ToString()); + + if (cmd.ExecuteNonQuery() == 0) + return false; + + return true; + } + + public List GetRegions(int estateID) + { + return new List(); + } + + public bool DeleteEstate(int estateID) + { + return false; + } + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteFramework.cs b/OpenSim/Data/SQLiteNG/SQLiteFramework.cs new file mode 100644 index 0000000..20b5085 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteFramework.cs @@ -0,0 +1,91 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLite +{ + /// + /// A database interface class to a user profile storage system + /// + public class SQLiteFramework + { + protected Object m_lockObject = new Object(); + + protected SQLiteFramework(string connectionString) + { + } + + ////////////////////////////////////////////////////////////// + // + // All non queries are funneled through one connection + // to increase performance a little + // + protected int ExecuteNonQuery(SqliteCommand cmd, SqliteConnection connection) + { + lock (connection) + { + SqliteConnection newConnection = + (SqliteConnection)((ICloneable)connection).Clone(); + newConnection.Open(); + + cmd.Connection = newConnection; + //Console.WriteLine("XXX " + cmd.CommandText); + + return cmd.ExecuteNonQuery(); + } + } + + protected IDataReader ExecuteReader(SqliteCommand cmd, SqliteConnection connection) + { + lock (connection) + { + SqliteConnection newConnection = + (SqliteConnection)((ICloneable)connection).Clone(); + newConnection.Open(); + + cmd.Connection = newConnection; + //Console.WriteLine("XXX " + cmd.CommandText); + + return cmd.ExecuteReader(); + } + } + + protected void CloseCommand(SqliteCommand cmd) + { + cmd.Connection.Close(); + cmd.Connection.Dispose(); + cmd.Dispose(); + } + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs b/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs new file mode 100644 index 0000000..0b12182 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs @@ -0,0 +1,70 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLite +{ + public class SQLiteFriendsData : SQLiteGenericTableHandler, IFriendsData + { + public SQLiteFriendsData(string connectionString, string realm) + : base(connectionString, realm, "FriendsStore") + { + } + + public FriendsData[] GetFriends(UUID userID) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = :PrincipalID", m_Realm); + cmd.Parameters.Add(":PrincipalID", userID.ToString()); + + return DoQuery(cmd); + + } + + public bool Delete(UUID principalID, string friend) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm); + cmd.Parameters.Add(":PrincipalID", principalID.ToString()); + cmd.Parameters.Add(":Friend", friend); + + ExecuteNonQuery(cmd, cmd.Connection); + + return true; + } + + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs new file mode 100644 index 0000000..b39bb19 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs @@ -0,0 +1,268 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Data.SQLite +{ + public class SQLiteGenericTableHandler : SQLiteFramework where T: class, new() + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Dictionary m_Fields = + new Dictionary(); + + protected List m_ColumnNames = null; + protected string m_Realm; + protected FieldInfo m_DataField = null; + + protected static SqliteConnection m_Connection; + private static bool m_initialized; + + public SQLiteGenericTableHandler(string connectionString, + string realm, string storeName) : base(connectionString) + { + m_Realm = realm; + + if (!m_initialized) + { + m_Connection = new SqliteConnection(connectionString); + m_Connection.Open(); + + if (storeName != String.Empty) + { + Assembly assem = GetType().Assembly; + SqliteConnection newConnection = + (SqliteConnection)((ICloneable)m_Connection).Clone(); + newConnection.Open(); + + Migration m = new Migration(newConnection, assem, storeName); + m.Update(); + newConnection.Close(); + newConnection.Dispose(); + } + + m_initialized = true; + } + + Type t = typeof(T); + FieldInfo[] fields = t.GetFields(BindingFlags.Public | + BindingFlags.Instance | + BindingFlags.DeclaredOnly); + + if (fields.Length == 0) + return; + + foreach (FieldInfo f in fields) + { + if (f.Name != "Data") + m_Fields[f.Name] = f; + else + m_DataField = f; + } + } + + private void CheckColumnNames(IDataReader reader) + { + if (m_ColumnNames != null) + return; + + m_ColumnNames = new List(); + + DataTable schemaTable = reader.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + { + if (row["ColumnName"] != null && + (!m_Fields.ContainsKey(row["ColumnName"].ToString()))) + m_ColumnNames.Add(row["ColumnName"].ToString()); + } + } + + public T[] Get(string field, string key) + { + return Get(new string[] { field }, new string[] { key }); + } + + public T[] Get(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return new T[0]; + + List terms = new List(); + + SqliteCommand cmd = new SqliteCommand(); + + for (int i = 0 ; i < fields.Length ; i++) + { + cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i])); + terms.Add("`" + fields[i] + "` = :" + fields[i]); + } + + string where = String.Join(" and ", terms.ToArray()); + + string query = String.Format("select * from {0} where {1}", + m_Realm, where); + + cmd.CommandText = query; + + return DoQuery(cmd); + } + + protected T[] DoQuery(SqliteCommand cmd) + { + IDataReader reader = ExecuteReader(cmd, m_Connection); + if (reader == null) + return new T[0]; + + CheckColumnNames(reader); + + List result = new List(); + + while (reader.Read()) + { + T row = new T(); + + foreach (string name in m_Fields.Keys) + { + if (m_Fields[name].GetValue(row) is bool) + { + int v = Convert.ToInt32(reader[name]); + m_Fields[name].SetValue(row, v != 0 ? true : false); + } + else if (m_Fields[name].GetValue(row) is UUID) + { + UUID uuid = UUID.Zero; + + UUID.TryParse(reader[name].ToString(), out uuid); + m_Fields[name].SetValue(row, uuid); + } + else if (m_Fields[name].GetValue(row) is int) + { + int v = Convert.ToInt32(reader[name]); + m_Fields[name].SetValue(row, v); + } + else + { + m_Fields[name].SetValue(row, reader[name]); + } + } + + if (m_DataField != null) + { + Dictionary data = + new Dictionary(); + + foreach (string col in m_ColumnNames) + { + data[col] = reader[col].ToString(); + if (data[col] == null) + data[col] = String.Empty; + } + + m_DataField.SetValue(row, data); + } + + result.Add(row); + } + + CloseCommand(cmd); + + return result.ToArray(); + } + + public T[] Get(string where) + { + SqliteCommand cmd = new SqliteCommand(); + + string query = String.Format("select * from {0} where {1}", + m_Realm, where); + + cmd.CommandText = query; + + return DoQuery(cmd); + } + + public bool Store(T row) + { + SqliteCommand cmd = new SqliteCommand(); + + string query = ""; + List names = new List(); + List values = new List(); + + foreach (FieldInfo fi in m_Fields.Values) + { + names.Add(fi.Name); + values.Add(":" + fi.Name); + cmd.Parameters.Add(new SqliteParameter(":" + fi.Name, fi.GetValue(row).ToString())); + } + + if (m_DataField != null) + { + Dictionary data = + (Dictionary)m_DataField.GetValue(row); + + foreach (KeyValuePair kvp in data) + { + names.Add(kvp.Key); + values.Add(":" + kvp.Key); + cmd.Parameters.Add(new SqliteParameter(":" + kvp.Key, kvp.Value)); + } + } + + query = String.Format("replace into {0} (`", m_Realm) + String.Join("`,`", names.ToArray()) + "`) values (" + String.Join(",", values.ToArray()) + ")"; + + cmd.CommandText = query; + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; + + return false; + } + + public bool Delete(string field, string val) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("delete from {0} where `{1}` = :{1}", m_Realm, field); + cmd.Parameters.Add(new SqliteParameter(field, val)); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; + + return false; + } + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs b/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs new file mode 100644 index 0000000..a5e0517 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs @@ -0,0 +1,898 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.SQLite +{ + /// + /// An Inventory Interface to the SQLite database + /// + public class SQLiteInventoryStore : SQLiteUtil, IInventoryDataPlugin + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const string invItemsSelect = "select * from inventoryitems"; + private const string invFoldersSelect = "select * from inventoryfolders"; + + private static SqliteConnection conn; + private static DataSet ds; + private static SqliteDataAdapter invItemsDa; + private static SqliteDataAdapter invFoldersDa; + + private static bool m_Initialized = false; + + public void Initialise() + { + m_log.Info("[SQLiteInventoryData]: " + Name + " cannot be default-initialized!"); + throw new PluginNotInitialisedException(Name); + } + + /// + /// + /// Initialises Inventory interface + /// Loads and initialises a new SQLite connection and maintains it. + /// use default URI if connect string string is empty. + /// + /// + /// connect string + public void Initialise(string dbconnect) + { + if (!m_Initialized) + { + m_Initialized = true; + + if (dbconnect == string.Empty) + { + dbconnect = "URI=file:inventoryStore.db,version=3"; + } + m_log.Info("[INVENTORY DB]: Sqlite - connecting: " + dbconnect); + conn = new SqliteConnection(dbconnect); + + conn.Open(); + + Assembly assem = GetType().Assembly; + Migration m = new Migration(conn, assem, "InventoryStore"); + m.Update(); + + SqliteCommand itemsSelectCmd = new SqliteCommand(invItemsSelect, conn); + invItemsDa = new SqliteDataAdapter(itemsSelectCmd); + // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + + SqliteCommand foldersSelectCmd = new SqliteCommand(invFoldersSelect, conn); + invFoldersDa = new SqliteDataAdapter(foldersSelectCmd); + + ds = new DataSet(); + + ds.Tables.Add(createInventoryFoldersTable()); + invFoldersDa.Fill(ds.Tables["inventoryfolders"]); + setupFoldersCommands(invFoldersDa, conn); + m_log.Info("[INVENTORY DB]: Populated Inventory Folders Definitions"); + + ds.Tables.Add(createInventoryItemsTable()); + invItemsDa.Fill(ds.Tables["inventoryitems"]); + setupItemsCommands(invItemsDa, conn); + m_log.Info("[INVENTORY DB]: Populated Inventory Items Definitions"); + + ds.AcceptChanges(); + } + } + + /// + /// Closes the inventory interface + /// + public void Dispose() + { + if (conn != null) + { + conn.Close(); + conn = null; + } + if (invItemsDa != null) + { + invItemsDa.Dispose(); + invItemsDa = null; + } + if (invFoldersDa != null) + { + invFoldersDa.Dispose(); + invFoldersDa = null; + } + if (ds != null) + { + ds.Dispose(); + ds = null; + } + } + + /// + /// + /// + /// + /// + public InventoryItemBase buildItem(DataRow row) + { + InventoryItemBase item = new InventoryItemBase(); + item.ID = new UUID((string) row["UUID"]); + item.AssetID = new UUID((string) row["assetID"]); + item.AssetType = Convert.ToInt32(row["assetType"]); + item.InvType = Convert.ToInt32(row["invType"]); + item.Folder = new UUID((string) row["parentFolderID"]); + item.Owner = new UUID((string) row["avatarID"]); + item.CreatorId = (string)row["creatorsID"]; + item.Name = (string) row["inventoryName"]; + item.Description = (string) row["inventoryDescription"]; + + item.NextPermissions = Convert.ToUInt32(row["inventoryNextPermissions"]); + item.CurrentPermissions = Convert.ToUInt32(row["inventoryCurrentPermissions"]); + item.BasePermissions = Convert.ToUInt32(row["inventoryBasePermissions"]); + item.EveryOnePermissions = Convert.ToUInt32(row["inventoryEveryOnePermissions"]); + item.GroupPermissions = Convert.ToUInt32(row["inventoryGroupPermissions"]); + + // new fields + if (!Convert.IsDBNull(row["salePrice"])) + item.SalePrice = Convert.ToInt32(row["salePrice"]); + + if (!Convert.IsDBNull(row["saleType"])) + item.SaleType = Convert.ToByte(row["saleType"]); + + if (!Convert.IsDBNull(row["creationDate"])) + item.CreationDate = Convert.ToInt32(row["creationDate"]); + + if (!Convert.IsDBNull(row["groupID"])) + item.GroupID = new UUID((string)row["groupID"]); + + if (!Convert.IsDBNull(row["groupOwned"])) + item.GroupOwned = Convert.ToBoolean(row["groupOwned"]); + + if (!Convert.IsDBNull(row["Flags"])) + item.Flags = Convert.ToUInt32(row["Flags"]); + + return item; + } + + /// + /// Fill a database row with item data + /// + /// + /// + private static void fillItemRow(DataRow row, InventoryItemBase item) + { + row["UUID"] = item.ID.ToString(); + row["assetID"] = item.AssetID.ToString(); + row["assetType"] = item.AssetType; + row["invType"] = item.InvType; + row["parentFolderID"] = item.Folder.ToString(); + row["avatarID"] = item.Owner.ToString(); + row["creatorsID"] = item.CreatorId.ToString(); + row["inventoryName"] = item.Name; + row["inventoryDescription"] = item.Description; + + row["inventoryNextPermissions"] = item.NextPermissions; + row["inventoryCurrentPermissions"] = item.CurrentPermissions; + row["inventoryBasePermissions"] = item.BasePermissions; + row["inventoryEveryOnePermissions"] = item.EveryOnePermissions; + row["inventoryGroupPermissions"] = item.GroupPermissions; + + // new fields + row["salePrice"] = item.SalePrice; + row["saleType"] = item.SaleType; + row["creationDate"] = item.CreationDate; + row["groupID"] = item.GroupID.ToString(); + row["groupOwned"] = item.GroupOwned; + row["flags"] = item.Flags; + } + + /// + /// Add inventory folder + /// + /// Folder base + /// true=create folder. false=update existing folder + /// nasty + private void addFolder(InventoryFolderBase folder, bool add) + { + lock (ds) + { + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + + DataRow inventoryRow = inventoryFolderTable.Rows.Find(folder.ID.ToString()); + if (inventoryRow == null) + { + if (! add) + m_log.ErrorFormat("Interface Misuse: Attempting to Update non-existant inventory folder: {0}", folder.ID); + + inventoryRow = inventoryFolderTable.NewRow(); + fillFolderRow(inventoryRow, folder); + inventoryFolderTable.Rows.Add(inventoryRow); + } + else + { + if (add) + m_log.ErrorFormat("Interface Misuse: Attempting to Add inventory folder that already exists: {0}", folder.ID); + + fillFolderRow(inventoryRow, folder); + } + + invFoldersDa.Update(ds, "inventoryfolders"); + } + } + + /// + /// Move an inventory folder + /// + /// folder base + private void moveFolder(InventoryFolderBase folder) + { + lock (ds) + { + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + + DataRow inventoryRow = inventoryFolderTable.Rows.Find(folder.ID.ToString()); + if (inventoryRow == null) + { + inventoryRow = inventoryFolderTable.NewRow(); + fillFolderRow(inventoryRow, folder); + inventoryFolderTable.Rows.Add(inventoryRow); + } + else + { + moveFolderRow(inventoryRow, folder); + } + + invFoldersDa.Update(ds, "inventoryfolders"); + } + } + + /// + /// add an item in inventory + /// + /// the item + /// true=add item ; false=update existing item + private void addItem(InventoryItemBase item, bool add) + { + lock (ds) + { + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + + DataRow inventoryRow = inventoryItemTable.Rows.Find(item.ID.ToString()); + if (inventoryRow == null) + { + if (!add) + m_log.ErrorFormat("[INVENTORY DB]: Interface Misuse: Attempting to Update non-existant inventory item: {0}", item.ID); + + inventoryRow = inventoryItemTable.NewRow(); + fillItemRow(inventoryRow, item); + inventoryItemTable.Rows.Add(inventoryRow); + } + else + { + if (add) + m_log.ErrorFormat("[INVENTORY DB]: Interface Misuse: Attempting to Add inventory item that already exists: {0}", item.ID); + + fillItemRow(inventoryRow, item); + } + + invItemsDa.Update(ds, "inventoryitems"); + + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + + inventoryRow = inventoryFolderTable.Rows.Find(item.Folder.ToString()); + if (inventoryRow != null) //MySQL doesn't throw an exception here, so sqlite shouldn't either. + inventoryRow["version"] = (int)inventoryRow["version"] + 1; + + invFoldersDa.Update(ds, "inventoryfolders"); + } + } + + /// + /// TODO : DataSet commit + /// + public void Shutdown() + { + // TODO: DataSet commit + } + + /// + /// The name of this DB provider + /// + /// Name of DB provider + public string Name + { + get { return "SQLite Inventory Data Interface"; } + } + + /// + /// Returns the version of this DB provider + /// + /// A string containing the DB provider version + public string Version + { + get + { + Module module = GetType().Module; + // string dllName = module.Assembly.ManifestModule.Name; + Version dllVersion = module.Assembly.GetName().Version; + + + return + string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, + dllVersion.Revision); + } + } + + /// + /// Returns a list of inventory items contained within the specified folder + /// + /// The UUID of the target folder + /// A List of InventoryItemBase items + public List getInventoryInFolder(UUID folderID) + { + lock (ds) + { + List retval = new List(); + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + string selectExp = "parentFolderID = '" + folderID + "'"; + DataRow[] rows = inventoryItemTable.Select(selectExp); + foreach (DataRow row in rows) + { + retval.Add(buildItem(row)); + } + + return retval; + } + } + + /// + /// Returns a list of the root folders within a users inventory + /// + /// The user whos inventory is to be searched + /// A list of folder objects + public List getUserRootFolders(UUID user) + { + return new List(); + } + + // see InventoryItemBase.getUserRootFolder + public InventoryFolderBase getUserRootFolder(UUID user) + { + lock (ds) + { + List folders = new List(); + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + string selectExp = "agentID = '" + user + "' AND parentID = '" + UUID.Zero + "'"; + DataRow[] rows = inventoryFolderTable.Select(selectExp); + foreach (DataRow row in rows) + { + folders.Add(buildFolder(row)); + } + + // There should only ever be one root folder for a user. However, if there's more + // than one we'll simply use the first one rather than failing. It would be even + // nicer to print some message to this effect, but this feels like it's too low a + // to put such a message out, and it's too minor right now to spare the time to + // suitably refactor. + if (folders.Count > 0) + { + return folders[0]; + } + + return null; + } + } + + /// + /// Append a list of all the child folders of a parent folder + /// + /// list where folders will be appended + /// ID of parent + protected void getInventoryFolders(ref List folders, UUID parentID) + { + lock (ds) + { + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + string selectExp = "parentID = '" + parentID + "'"; + DataRow[] rows = inventoryFolderTable.Select(selectExp); + foreach (DataRow row in rows) + { + folders.Add(buildFolder(row)); + } + + } + } + + /// + /// Returns a list of inventory folders contained in the folder 'parentID' + /// + /// The folder to get subfolders for + /// A list of inventory folders + public List getInventoryFolders(UUID parentID) + { + List folders = new List(); + getInventoryFolders(ref folders, parentID); + return folders; + } + + /// + /// See IInventoryDataPlugin + /// + /// + /// + public List getFolderHierarchy(UUID parentID) + { + /* Note: There are subtle changes between this implementation of getFolderHierarchy and the previous one + * - We will only need to hit the database twice instead of n times. + * - We assume the database is well-formed - no stranded/dangling folders, all folders in heirarchy owned + * by the same person, each user only has 1 inventory heirarchy + * - The returned list is not ordered, instead of breadth-first ordered + There are basically 2 usage cases for getFolderHeirarchy: + 1) Getting the user's entire inventory heirarchy when they log in + 2) Finding a subfolder heirarchy to delete when emptying the trash. + This implementation will pull all inventory folders from the database, and then prune away any folder that + is not part of the requested sub-heirarchy. The theory is that it is cheaper to make 1 request from the + database than to make n requests. This pays off only if requested heirarchy is large. + By making this choice, we are making the worst case better at the cost of making the best case worse + - Francis + */ + + List folders = new List(); + DataRow[] folderRows = null, parentRow; + InventoryFolderBase parentFolder = null; + lock (ds) + { + /* Fetch the parent folder from the database to determine the agent ID. + * Then fetch all inventory folders for that agent from the agent ID. + */ + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + string selectExp = "UUID = '" + parentID + "'"; + parentRow = inventoryFolderTable.Select(selectExp); // Assume at most 1 result + if (parentRow.GetLength(0) >= 1) // No result means parent folder does not exist + { + parentFolder = buildFolder(parentRow[0]); + UUID agentID = parentFolder.Owner; + selectExp = "agentID = '" + agentID + "'"; + folderRows = inventoryFolderTable.Select(selectExp); + } + + if (folderRows != null && folderRows.GetLength(0) >= 1) // No result means parent folder does not exist + { // or has no children + /* if we're querying the root folder, just return an unordered list of all folders in the user's + * inventory + */ + if (parentFolder.ParentID == UUID.Zero) + { + foreach (DataRow row in folderRows) + { + InventoryFolderBase curFolder = buildFolder(row); + if (curFolder.ID != parentID) // Return all folders except the parent folder of heirarchy + folders.Add(buildFolder(row)); + } + } // If requesting root folder + /* else we are querying a non-root folder. We currently have a list of all of the user's folders, + * we must construct a list of all folders in the heirarchy below parentID. + * Our first step will be to construct a hash table of all folders, indexed by parent ID. + * Once we have constructed the hash table, we will do a breadth-first traversal on the tree using the + * hash table to find child folders. + */ + else + { // Querying a non-root folder + + // Build a hash table of all user's inventory folders, indexed by each folder's parent ID + Dictionary> hashtable = + new Dictionary>(folderRows.GetLength(0)); + + foreach (DataRow row in folderRows) + { + InventoryFolderBase curFolder = buildFolder(row); + if (curFolder.ParentID != UUID.Zero) // Discard root of tree - not needed + { + if (hashtable.ContainsKey(curFolder.ParentID)) + { + // Current folder already has a sibling - append to sibling list + hashtable[curFolder.ParentID].Add(curFolder); + } + else + { + List siblingList = new List(); + siblingList.Add(curFolder); + // Current folder has no known (yet) siblings + hashtable.Add(curFolder.ParentID, siblingList); + } + } + } // For all inventory folders + + // Note: Could release the ds lock here - we don't access folderRows or the database anymore. + // This is somewhat of a moot point as the callers of this function usually lock db anyways. + + if (hashtable.ContainsKey(parentID)) // if requested folder does have children + folders.AddRange(hashtable[parentID]); + + // BreadthFirstSearch build inventory tree **Note: folders.Count is *not* static + for (int i = 0; i < folders.Count; i++) + if (hashtable.ContainsKey(folders[i].ID)) + folders.AddRange(hashtable[folders[i].ID]); + + } // if requesting a subfolder heirarchy + } // if folder parentID exists and has children + } // lock ds + return folders; + } + + /// + /// Returns an inventory item by its UUID + /// + /// The UUID of the item to be returned + /// A class containing item information + public InventoryItemBase getInventoryItem(UUID item) + { + lock (ds) + { + DataRow row = ds.Tables["inventoryitems"].Rows.Find(item.ToString()); + if (row != null) + { + return buildItem(row); + } + else + { + return null; + } + } + } + + /// + /// Returns a specified inventory folder by its UUID + /// + /// The UUID of the folder to be returned + /// A class containing folder information + public InventoryFolderBase getInventoryFolder(UUID folder) + { + // TODO: Deep voodoo here. If you enable this code then + // multi region breaks. No idea why, but I figured it was + // better to leave multi region at this point. It does mean + // that you don't get to see system textures why creating + // clothes and the like. :( + lock (ds) + { + DataRow row = ds.Tables["inventoryfolders"].Rows.Find(folder.ToString()); + if (row != null) + { + return buildFolder(row); + } + else + { + return null; + } + } + } + + /// + /// Creates a new inventory item based on item + /// + /// The item to be created + public void addInventoryItem(InventoryItemBase item) + { + addItem(item, true); + } + + /// + /// Updates an inventory item with item (updates based on ID) + /// + /// The updated item + public void updateInventoryItem(InventoryItemBase item) + { + addItem(item, false); + } + + /// + /// Delete an inventory item + /// + /// The item UUID + public void deleteInventoryItem(UUID itemID) + { + lock (ds) + { + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + + DataRow inventoryRow = inventoryItemTable.Rows.Find(itemID.ToString()); + if (inventoryRow != null) + { + inventoryRow.Delete(); + } + + invItemsDa.Update(ds, "inventoryitems"); + } + } + + public InventoryItemBase queryInventoryItem(UUID itemID) + { + return getInventoryItem(itemID); + } + + public InventoryFolderBase queryInventoryFolder(UUID folderID) + { + return getInventoryFolder(folderID); + } + + /// + /// Delete all items in the specified folder + /// + /// id of the folder, whose item content should be deleted + /// this is horribly inefficient, but I don't want to ruin the overall structure of this implementation + private void deleteItemsInFolder(UUID folderId) + { + List items = getInventoryInFolder(folderId); + + foreach (InventoryItemBase i in items) + deleteInventoryItem(i.ID); + } + + /// + /// Adds a new folder specified by folder + /// + /// The inventory folder + public void addInventoryFolder(InventoryFolderBase folder) + { + addFolder(folder, true); + } + + /// + /// Updates a folder based on its ID with folder + /// + /// The inventory folder + public void updateInventoryFolder(InventoryFolderBase folder) + { + addFolder(folder, false); + } + + /// + /// Moves a folder based on its ID with folder + /// + /// The inventory folder + public void moveInventoryFolder(InventoryFolderBase folder) + { + moveFolder(folder); + } + + /// + /// Delete a folder + /// + /// + /// This will clean-up any child folders and child items as well + /// + /// the folder UUID + public void deleteInventoryFolder(UUID folderID) + { + lock (ds) + { + List subFolders = getFolderHierarchy(folderID); + + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + DataRow inventoryRow; + + //Delete all sub-folders + foreach (InventoryFolderBase f in subFolders) + { + inventoryRow = inventoryFolderTable.Rows.Find(f.ID.ToString()); + if (inventoryRow != null) + { + deleteItemsInFolder(f.ID); + inventoryRow.Delete(); + } + } + + //Delete the actual row + inventoryRow = inventoryFolderTable.Rows.Find(folderID.ToString()); + if (inventoryRow != null) + { + deleteItemsInFolder(folderID); + inventoryRow.Delete(); + } + + invFoldersDa.Update(ds, "inventoryfolders"); + } + } + + /*********************************************************************** + * + * Data Table definitions + * + **********************************************************************/ + + /// + /// Create the "inventoryitems" table + /// + private static DataTable createInventoryItemsTable() + { + DataTable inv = new DataTable("inventoryitems"); + + createCol(inv, "UUID", typeof (String)); //inventoryID + createCol(inv, "assetID", typeof (String)); + createCol(inv, "assetType", typeof (Int32)); + createCol(inv, "invType", typeof (Int32)); + createCol(inv, "parentFolderID", typeof (String)); + createCol(inv, "avatarID", typeof (String)); + createCol(inv, "creatorsID", typeof (String)); + + createCol(inv, "inventoryName", typeof (String)); + createCol(inv, "inventoryDescription", typeof (String)); + // permissions + createCol(inv, "inventoryNextPermissions", typeof (Int32)); + createCol(inv, "inventoryCurrentPermissions", typeof (Int32)); + createCol(inv, "inventoryBasePermissions", typeof (Int32)); + createCol(inv, "inventoryEveryOnePermissions", typeof (Int32)); + createCol(inv, "inventoryGroupPermissions", typeof (Int32)); + + // sale info + createCol(inv, "salePrice", typeof(Int32)); + createCol(inv, "saleType", typeof(Byte)); + + // creation date + createCol(inv, "creationDate", typeof(Int32)); + + // group info + createCol(inv, "groupID", typeof(String)); + createCol(inv, "groupOwned", typeof(Boolean)); + + // Flags + createCol(inv, "flags", typeof(UInt32)); + + inv.PrimaryKey = new DataColumn[] { inv.Columns["UUID"] }; + return inv; + } + + /// + /// Creates the "inventoryfolders" table + /// + /// + private static DataTable createInventoryFoldersTable() + { + DataTable fol = new DataTable("inventoryfolders"); + + createCol(fol, "UUID", typeof (String)); //folderID + createCol(fol, "name", typeof (String)); + createCol(fol, "agentID", typeof (String)); + createCol(fol, "parentID", typeof (String)); + createCol(fol, "type", typeof (Int32)); + createCol(fol, "version", typeof (Int32)); + + fol.PrimaryKey = new DataColumn[] {fol.Columns["UUID"]}; + return fol; + } + + /// + /// + /// + /// + /// + private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + lock (ds) + { + da.InsertCommand = createInsertCommand("inventoryitems", ds.Tables["inventoryitems"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("inventoryitems", "UUID=:UUID", ds.Tables["inventoryitems"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from inventoryitems where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + } + + /// + /// + /// + /// + /// + private void setupFoldersCommands(SqliteDataAdapter da, SqliteConnection conn) + { + lock (ds) + { + da.InsertCommand = createInsertCommand("inventoryfolders", ds.Tables["inventoryfolders"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("inventoryfolders", "UUID=:UUID", ds.Tables["inventoryfolders"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from inventoryfolders where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + } + + /// + /// + /// + /// + /// + private static InventoryFolderBase buildFolder(DataRow row) + { + InventoryFolderBase folder = new InventoryFolderBase(); + folder.ID = new UUID((string) row["UUID"]); + folder.Name = (string) row["name"]; + folder.Owner = new UUID((string) row["agentID"]); + folder.ParentID = new UUID((string) row["parentID"]); + folder.Type = Convert.ToInt16(row["type"]); + folder.Version = Convert.ToUInt16(row["version"]); + return folder; + } + + /// + /// + /// + /// + /// + private static void fillFolderRow(DataRow row, InventoryFolderBase folder) + { + row["UUID"] = folder.ID.ToString(); + row["name"] = folder.Name; + row["agentID"] = folder.Owner.ToString(); + row["parentID"] = folder.ParentID.ToString(); + row["type"] = folder.Type; + row["version"] = folder.Version; + } + + /// + /// + /// + /// + /// + private static void moveFolderRow(DataRow row, InventoryFolderBase folder) + { + row["UUID"] = folder.ID.ToString(); + row["parentID"] = folder.ParentID.ToString(); + } + + public List fetchActiveGestures (UUID avatarID) + { + lock (ds) + { + List items = new List(); + + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + string selectExp + = "avatarID = '" + avatarID + "' AND assetType = " + (int)AssetType.Gesture + " AND flags = 1"; + //m_log.DebugFormat("[SQL]: sql = " + selectExp); + DataRow[] rows = inventoryItemTable.Select(selectExp); + foreach (DataRow row in rows) + { + items.Add(buildItem(row)); + } + return items; + } + } + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs b/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs new file mode 100644 index 0000000..d2ba9ae --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs @@ -0,0 +1,2264 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Drawing; +using System.IO; +using System.Reflection; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Data.SQLite +{ + /// + /// A RegionData Interface to the SQLite database + /// + public class SQLiteRegionData : IRegionDataStore + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const string primSelect = "select * from prims"; + private const string shapeSelect = "select * from primshapes"; + private const string itemsSelect = "select * from primitems"; + private const string terrainSelect = "select * from terrain limit 1"; + private const string landSelect = "select * from land"; + private const string landAccessListSelect = "select distinct * from landaccesslist"; + private const string regionbanListSelect = "select * from regionban"; + private const string regionSettingsSelect = "select * from regionsettings"; + + private DataSet ds; + private SqliteDataAdapter primDa; + private SqliteDataAdapter shapeDa; + private SqliteDataAdapter itemsDa; + private SqliteDataAdapter terrainDa; + private SqliteDataAdapter landDa; + private SqliteDataAdapter landAccessListDa; + private SqliteDataAdapter regionSettingsDa; + + private SqliteConnection m_conn; + + private String m_connectionString; + + // Temporary attribute while this is experimental + + /*********************************************************************** + * + * Public Interface Functions + * + **********************************************************************/ + + /// + /// See IRegionDataStore + /// + /// Initialises RegionData Interface + /// Loads and initialises a new SQLite connection and maintains it. + /// + /// + /// the connection string + public void Initialise(string connectionString) + { + m_connectionString = connectionString; + + ds = new DataSet(); + + m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); + m_conn = new SqliteConnection(m_connectionString); + m_conn.Open(); + + + + SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); + primDa = new SqliteDataAdapter(primSelectCmd); + // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + + SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); + shapeDa = new SqliteDataAdapter(shapeSelectCmd); + // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); + + SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); + itemsDa = new SqliteDataAdapter(itemsSelectCmd); + + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); + terrainDa = new SqliteDataAdapter(terrainSelectCmd); + + SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); + landDa = new SqliteDataAdapter(landSelectCmd); + + SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); + landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); + + SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); + regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); + // This actually does the roll forward assembly stuff + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_conn, assem, "RegionStore"); + m.Update(); + + lock (ds) + { + ds.Tables.Add(createPrimTable()); + setupPrimCommands(primDa, m_conn); + primDa.Fill(ds.Tables["prims"]); + + ds.Tables.Add(createShapeTable()); + setupShapeCommands(shapeDa, m_conn); + + ds.Tables.Add(createItemsTable()); + setupItemsCommands(itemsDa, m_conn); + itemsDa.Fill(ds.Tables["primitems"]); + + ds.Tables.Add(createTerrainTable()); + setupTerrainCommands(terrainDa, m_conn); + + ds.Tables.Add(createLandTable()); + setupLandCommands(landDa, m_conn); + + ds.Tables.Add(createLandAccessListTable()); + setupLandAccessCommands(landAccessListDa, m_conn); + + ds.Tables.Add(createRegionSettingsTable()); + + setupRegionSettingsCommands(regionSettingsDa, m_conn); + + // WORKAROUND: This is a work around for sqlite on + // windows, which gets really unhappy with blob columns + // that have no sample data in them. At some point we + // need to actually find a proper way to handle this. + try + { + shapeDa.Fill(ds.Tables["primshapes"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on primshapes table"); + } + + try + { + terrainDa.Fill(ds.Tables["terrain"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on terrain table"); + } + + try + { + landDa.Fill(ds.Tables["land"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on land table"); + } + + try + { + landAccessListDa.Fill(ds.Tables["landaccesslist"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); + } + + try + { + regionSettingsDa.Fill(ds.Tables["regionsettings"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); + } + return; + } + } + + public void Dispose() + { + if (m_conn != null) + { + m_conn.Close(); + m_conn = null; + } + if (ds != null) + { + ds.Dispose(); + ds = null; + } + if (primDa != null) + { + primDa.Dispose(); + primDa = null; + } + if (shapeDa != null) + { + shapeDa.Dispose(); + shapeDa = null; + } + if (itemsDa != null) + { + itemsDa.Dispose(); + itemsDa = null; + } + if (terrainDa != null) + { + terrainDa.Dispose(); + terrainDa = null; + } + if (landDa != null) + { + landDa.Dispose(); + landDa = null; + } + if (landAccessListDa != null) + { + landAccessListDa.Dispose(); + landAccessListDa = null; + } + if (regionSettingsDa != null) + { + regionSettingsDa.Dispose(); + regionSettingsDa = null; + } + } + + public void StoreRegionSettings(RegionSettings rs) + { + lock (ds) + { + DataTable regionsettings = ds.Tables["regionsettings"]; + + DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString()); + if (settingsRow == null) + { + settingsRow = regionsettings.NewRow(); + fillRegionSettingsRow(settingsRow, rs); + regionsettings.Rows.Add(settingsRow); + } + else + { + fillRegionSettingsRow(settingsRow, rs); + } + + Commit(); + } + } + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionLightShareData(); + } + public void StoreRegionWindlightSettings(RegionLightShareData wl) + { + //This connector doesn't support the windlight module yet + } + public RegionSettings LoadRegionSettings(UUID regionUUID) + { + lock (ds) + { + DataTable regionsettings = ds.Tables["regionsettings"]; + + string searchExp = "regionUUID = '" + regionUUID.ToString() + "'"; + DataRow[] rawsettings = regionsettings.Select(searchExp); + if (rawsettings.Length == 0) + { + RegionSettings rs = new RegionSettings(); + rs.RegionUUID = regionUUID; + rs.OnSave += StoreRegionSettings; + + StoreRegionSettings(rs); + + return rs; + } + DataRow row = rawsettings[0]; + + RegionSettings newSettings = buildRegionSettings(row); + newSettings.OnSave += StoreRegionSettings; + + return newSettings; + } + } + + /// + /// Adds an object into region storage + /// + /// the object + /// the region UUID + public void StoreObject(SceneObjectGroup obj, UUID regionUUID) + { + uint flags = obj.RootPart.GetEffectiveObjectFlags(); + + // Eligibility check + // + if ((flags & (uint)PrimFlags.Temporary) != 0) + return; + if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) + return; + + lock (ds) + { + foreach (SceneObjectPart prim in obj.Children.Values) + { +// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); + addPrim(prim, obj.UUID, regionUUID); + } + } + + Commit(); + // m_log.Info("[Dump of prims]: " + ds.GetXml()); + } + + /// + /// Removes an object from region storage + /// + /// the object + /// the region UUID + public void RemoveObject(UUID obj, UUID regionUUID) + { + // m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.Guid, regionUUID); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string selectExp = "SceneGroupID = '" + obj + "' and RegionUUID = '" + regionUUID + "'"; + lock (ds) + { + DataRow[] primRows = prims.Select(selectExp); + foreach (DataRow row in primRows) + { + // Remove shape rows + UUID uuid = new UUID((string) row["UUID"]); + DataRow shapeRow = shapes.Rows.Find(uuid.ToString()); + if (shapeRow != null) + { + shapeRow.Delete(); + } + + RemoveItems(uuid); + + // Remove prim row + row.Delete(); + } + } + + Commit(); + } + + /// + /// Remove all persisted items of the given prim. + /// The caller must acquire the necessrary synchronization locks and commit or rollback changes. + /// + /// The item UUID + private void RemoveItems(UUID uuid) + { + DataTable items = ds.Tables["primitems"]; + + String sql = String.Format("primID = '{0}'", uuid); + DataRow[] itemRows = items.Select(sql); + + foreach (DataRow itemRow in itemRows) + { + itemRow.Delete(); + } + } + + /// + /// Load persisted objects from region storage. + /// + /// The region UUID + /// List of loaded groups + public List LoadObjects(UUID regionUUID) + { + Dictionary createdObjects = new Dictionary(); + + List retvals = new List(); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string byRegion = "RegionUUID = '" + regionUUID + "'"; + + lock (ds) + { + DataRow[] primsForRegion = prims.Select(byRegion); + m_log.Info("[REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); + + // First, create all groups + foreach (DataRow primRow in primsForRegion) + { + try + { + SceneObjectPart prim = null; + + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + + if (uuid == objID) //is new SceneObjectGroup ? + { + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Info( + "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + + SceneObjectGroup group = new SceneObjectGroup(prim); + createdObjects.Add(group.UUID, group); + retvals.Add(group); + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[REGION DB]: Failed create prim object in new group, exception and data follows"); + m_log.Info("[REGION DB]: " + e.ToString()); + foreach (DataColumn col in prims.Columns) + { + m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + + // Now fill the groups with part data + foreach (DataRow primRow in primsForRegion) + { + try + { + SceneObjectPart prim = null; + + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + if (uuid != objID) //is new SceneObjectGroup ? + { + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Warn( + "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + + createdObjects[new UUID(objID)].AddPart(prim); + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[REGION DB]: Failed create prim object in group, exception and data follows"); + m_log.Info("[REGION DB]: " + e.ToString()); + foreach (DataColumn col in prims.Columns) + { + m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + } + return retvals; + } + + /// + /// Load in a prim's persisted inventory. + /// + /// the prim + private void LoadItems(SceneObjectPart prim) + { + //m_log.DebugFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); + + DataTable dbItems = ds.Tables["primitems"]; + String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); + DataRow[] dbItemRows = dbItems.Select(sql); + IList inventory = new List(); + + foreach (DataRow row in dbItemRows) + { + TaskInventoryItem item = buildItem(row); + inventory.Add(item); + + //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); + } + + prim.Inventory.RestoreInventoryItems(inventory); + } + + /// + /// Store a terrain revision in region storage + /// + /// terrain heightfield + /// region UUID + public void StoreTerrain(double[,] ter, UUID regionID) + { + lock (ds) + { + int revision = Util.UnixTimeSinceEpoch(); + + // This is added to get rid of the infinitely growing + // terrain databases which negatively impact on SQLite + // over time. Before reenabling this feature there + // needs to be a limitter put on the number of + // revisions in the database, as this old + // implementation is a DOS attack waiting to happen. + + using ( + SqliteCommand cmd = + new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision", + m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.ExecuteNonQuery(); + } + + // the following is an work around for .NET. The perf + // issues associated with it aren't as bad as you think. + m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString()); + String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + + " values(:RegionUUID, :Revision, :Heightfield)"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter))); + cmd.ExecuteNonQuery(); + } + } + } + + /// + /// Load the latest terrain revision from region storage + /// + /// the region UUID + /// Heightfield data + public double[,] LoadTerrain(UUID regionID) + { + lock (ds) + { + double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; + terret.Initialize(); + + String sql = "select RegionUUID, Revision, Heightfield from terrain" + + " where RegionUUID=:RegionUUID order by Revision desc"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + + using (IDataReader row = cmd.ExecuteReader()) + { + int rev = 0; + if (row.Read()) + { + // TODO: put this into a function + using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"])) + { + using (BinaryReader br = new BinaryReader(str)) + { + for (int x = 0; x < (int)Constants.RegionSize; x++) + { + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + terret[x, y] = br.ReadDouble(); + } + } + } + } + rev = (int) row["Revision"]; + } + else + { + m_log.Info("[REGION DB]: No terrain found for region"); + return null; + } + + m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString()); + } + } + return terret; + } + } + + /// + /// + /// + /// + public void RemoveLandObject(UUID globalID) + { + lock (ds) + { + // Can't use blanket SQL statements when using SqlAdapters unless you re-read the data into the adapter + // after you're done. + // replaced below code with the SqliteAdapter version. + //using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); + // cmd.ExecuteNonQuery(); + //} + + //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); + // cmd.ExecuteNonQuery(); + //} + + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + DataRow landRow = land.Rows.Find(globalID.ToString()); + if (landRow != null) + { + land.Rows.Remove(landRow); + } + List rowsToDelete = new List(); + foreach (DataRow rowToCheck in landaccesslist.Rows) + { + if (rowToCheck["LandUUID"].ToString() == globalID.ToString()) + rowsToDelete.Add(rowToCheck); + } + for (int iter = 0; iter < rowsToDelete.Count; iter++) + { + landaccesslist.Rows.Remove(rowsToDelete[iter]); + } + + + } + Commit(); + } + + /// + /// + /// + /// + public void StoreLandObject(ILandObject parcel) + { + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + + DataRow landRow = land.Rows.Find(parcel.LandData.GlobalID.ToString()); + if (landRow == null) + { + landRow = land.NewRow(); + fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); + land.Rows.Add(landRow); + } + else + { + fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); + } + + // I know this caused someone issues before, but OpenSim is unusable if we leave this stuff around + //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":LandUUID", parcel.LandData.GlobalID.ToString())); + // cmd.ExecuteNonQuery(); + +// } + + // This is the slower.. but more appropriate thing to do + + // We can't modify the table with direct queries before calling Commit() and re-filling them. + List rowsToDelete = new List(); + foreach (DataRow rowToCheck in landaccesslist.Rows) + { + if (rowToCheck["LandUUID"].ToString() == parcel.LandData.GlobalID.ToString()) + rowsToDelete.Add(rowToCheck); + } + for (int iter = 0; iter < rowsToDelete.Count; iter++) + { + landaccesslist.Rows.Remove(rowsToDelete[iter]); + } + rowsToDelete.Clear(); + foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList) + { + DataRow newAccessRow = landaccesslist.NewRow(); + fillLandAccessRow(newAccessRow, entry, parcel.LandData.GlobalID); + landaccesslist.Rows.Add(newAccessRow); + } + } + + Commit(); + } + + /// + /// + /// + /// + /// + public List LoadLandObjects(UUID regionUUID) + { + List landDataForRegion = new List(); + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + string searchExp = "RegionUUID = '" + regionUUID + "'"; + DataRow[] rawDataForRegion = land.Select(searchExp); + foreach (DataRow rawDataLand in rawDataForRegion) + { + LandData newLand = buildLandData(rawDataLand); + string accessListSearchExp = "LandUUID = '" + newLand.GlobalID + "'"; + DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); + foreach (DataRow rawDataLandAccess in rawDataForLandAccessList) + { + newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); + } + + landDataForRegion.Add(newLand); + } + } + return landDataForRegion; + } + + /// + /// + /// + public void Commit() + { + lock (ds) + { + primDa.Update(ds, "prims"); + shapeDa.Update(ds, "primshapes"); + + itemsDa.Update(ds, "primitems"); + + terrainDa.Update(ds, "terrain"); + landDa.Update(ds, "land"); + landAccessListDa.Update(ds, "landaccesslist"); + try + { + regionSettingsDa.Update(ds, "regionsettings"); + } + catch (SqliteExecutionException SqlEx) + { + if (SqlEx.Message.Contains("logic error")) + { + throw new Exception( + "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", + SqlEx); + } + else + { + throw SqlEx; + } + } + ds.AcceptChanges(); + } + } + + /// + /// See + /// + public void Shutdown() + { + Commit(); + } + + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + /// + /// + /// + /// + /// + /// + private static void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + /// + /// Creates the "terrain" table + /// + /// terrain table DataTable + private static DataTable createTerrainTable() + { + DataTable terrain = new DataTable("terrain"); + + createCol(terrain, "RegionUUID", typeof (String)); + createCol(terrain, "Revision", typeof (Int32)); + createCol(terrain, "Heightfield", typeof (Byte[])); + + return terrain; + } + + /// + /// Creates the "prims" table + /// + /// prim table DataTable + private static DataTable createPrimTable() + { + DataTable prims = new DataTable("prims"); + + createCol(prims, "UUID", typeof (String)); + createCol(prims, "RegionUUID", typeof (String)); + createCol(prims, "CreationDate", typeof (Int32)); + createCol(prims, "Name", typeof (String)); + createCol(prims, "SceneGroupID", typeof (String)); + // various text fields + createCol(prims, "Text", typeof (String)); + createCol(prims, "ColorR", typeof (Int32)); + createCol(prims, "ColorG", typeof (Int32)); + createCol(prims, "ColorB", typeof (Int32)); + createCol(prims, "ColorA", typeof (Int32)); + createCol(prims, "Description", typeof (String)); + createCol(prims, "SitName", typeof (String)); + createCol(prims, "TouchName", typeof (String)); + // permissions + createCol(prims, "ObjectFlags", typeof (Int32)); + createCol(prims, "CreatorID", typeof (String)); + createCol(prims, "OwnerID", typeof (String)); + createCol(prims, "GroupID", typeof (String)); + createCol(prims, "LastOwnerID", typeof (String)); + createCol(prims, "OwnerMask", typeof (Int32)); + createCol(prims, "NextOwnerMask", typeof (Int32)); + createCol(prims, "GroupMask", typeof (Int32)); + createCol(prims, "EveryoneMask", typeof (Int32)); + createCol(prims, "BaseMask", typeof (Int32)); + // vectors + createCol(prims, "PositionX", typeof (Double)); + createCol(prims, "PositionY", typeof (Double)); + createCol(prims, "PositionZ", typeof (Double)); + createCol(prims, "GroupPositionX", typeof (Double)); + createCol(prims, "GroupPositionY", typeof (Double)); + createCol(prims, "GroupPositionZ", typeof (Double)); + createCol(prims, "VelocityX", typeof (Double)); + createCol(prims, "VelocityY", typeof (Double)); + createCol(prims, "VelocityZ", typeof (Double)); + createCol(prims, "AngularVelocityX", typeof (Double)); + createCol(prims, "AngularVelocityY", typeof (Double)); + createCol(prims, "AngularVelocityZ", typeof (Double)); + createCol(prims, "AccelerationX", typeof (Double)); + createCol(prims, "AccelerationY", typeof (Double)); + createCol(prims, "AccelerationZ", typeof (Double)); + // quaternions + createCol(prims, "RotationX", typeof (Double)); + createCol(prims, "RotationY", typeof (Double)); + createCol(prims, "RotationZ", typeof (Double)); + createCol(prims, "RotationW", typeof (Double)); + + // sit target + createCol(prims, "SitTargetOffsetX", typeof (Double)); + createCol(prims, "SitTargetOffsetY", typeof (Double)); + createCol(prims, "SitTargetOffsetZ", typeof (Double)); + + createCol(prims, "SitTargetOrientW", typeof (Double)); + createCol(prims, "SitTargetOrientX", typeof (Double)); + createCol(prims, "SitTargetOrientY", typeof (Double)); + createCol(prims, "SitTargetOrientZ", typeof (Double)); + + createCol(prims, "PayPrice", typeof(Int32)); + createCol(prims, "PayButton1", typeof(Int32)); + createCol(prims, "PayButton2", typeof(Int32)); + createCol(prims, "PayButton3", typeof(Int32)); + createCol(prims, "PayButton4", typeof(Int32)); + + createCol(prims, "LoopedSound", typeof(String)); + createCol(prims, "LoopedSoundGain", typeof(Double)); + createCol(prims, "TextureAnimation", typeof(String)); + createCol(prims, "ParticleSystem", typeof(String)); + + createCol(prims, "OmegaX", typeof(Double)); + createCol(prims, "OmegaY", typeof(Double)); + createCol(prims, "OmegaZ", typeof(Double)); + + createCol(prims, "CameraEyeOffsetX", typeof(Double)); + createCol(prims, "CameraEyeOffsetY", typeof(Double)); + createCol(prims, "CameraEyeOffsetZ", typeof(Double)); + + createCol(prims, "CameraAtOffsetX", typeof(Double)); + createCol(prims, "CameraAtOffsetY", typeof(Double)); + createCol(prims, "CameraAtOffsetZ", typeof(Double)); + + createCol(prims, "ForceMouselook", typeof(Int16)); + + createCol(prims, "ScriptAccessPin", typeof(Int32)); + + createCol(prims, "AllowedDrop", typeof(Int16)); + createCol(prims, "DieAtEdge", typeof(Int16)); + + createCol(prims, "SalePrice", typeof(Int32)); + createCol(prims, "SaleType", typeof(Int16)); + + // click action + createCol(prims, "ClickAction", typeof (Byte)); + + createCol(prims, "Material", typeof(Byte)); + + createCol(prims, "CollisionSound", typeof(String)); + createCol(prims, "CollisionSoundVolume", typeof(Double)); + + createCol(prims, "VolumeDetect", typeof(Int16)); + + // Add in contraints + prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; + + return prims; + } + + /// + /// Creates "primshapes" table + /// + /// shape table DataTable + private static DataTable createShapeTable() + { + DataTable shapes = new DataTable("primshapes"); + createCol(shapes, "UUID", typeof (String)); + // shape is an enum + createCol(shapes, "Shape", typeof (Int32)); + // vectors + createCol(shapes, "ScaleX", typeof (Double)); + createCol(shapes, "ScaleY", typeof (Double)); + createCol(shapes, "ScaleZ", typeof (Double)); + // paths + createCol(shapes, "PCode", typeof (Int32)); + createCol(shapes, "PathBegin", typeof (Int32)); + createCol(shapes, "PathEnd", typeof (Int32)); + createCol(shapes, "PathScaleX", typeof (Int32)); + createCol(shapes, "PathScaleY", typeof (Int32)); + createCol(shapes, "PathShearX", typeof (Int32)); + createCol(shapes, "PathShearY", typeof (Int32)); + createCol(shapes, "PathSkew", typeof (Int32)); + createCol(shapes, "PathCurve", typeof (Int32)); + createCol(shapes, "PathRadiusOffset", typeof (Int32)); + createCol(shapes, "PathRevolutions", typeof (Int32)); + createCol(shapes, "PathTaperX", typeof (Int32)); + createCol(shapes, "PathTaperY", typeof (Int32)); + createCol(shapes, "PathTwist", typeof (Int32)); + createCol(shapes, "PathTwistBegin", typeof (Int32)); + // profile + createCol(shapes, "ProfileBegin", typeof (Int32)); + createCol(shapes, "ProfileEnd", typeof (Int32)); + createCol(shapes, "ProfileCurve", typeof (Int32)); + createCol(shapes, "ProfileHollow", typeof (Int32)); + createCol(shapes, "State", typeof(Int32)); + // text TODO: this isn't right, but I'm not sure the right + // way to specify this as a blob atm + createCol(shapes, "Texture", typeof (Byte[])); + createCol(shapes, "ExtraParams", typeof (Byte[])); + + shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; + + return shapes; + } + + /// + /// creates "primitems" table + /// + /// item table DataTable + private static DataTable createItemsTable() + { + DataTable items = new DataTable("primitems"); + + createCol(items, "itemID", typeof (String)); + createCol(items, "primID", typeof (String)); + createCol(items, "assetID", typeof (String)); + createCol(items, "parentFolderID", typeof (String)); + + createCol(items, "invType", typeof (Int32)); + createCol(items, "assetType", typeof (Int32)); + + createCol(items, "name", typeof (String)); + createCol(items, "description", typeof (String)); + + createCol(items, "creationDate", typeof (Int64)); + createCol(items, "creatorID", typeof (String)); + createCol(items, "ownerID", typeof (String)); + createCol(items, "lastOwnerID", typeof (String)); + createCol(items, "groupID", typeof (String)); + + createCol(items, "nextPermissions", typeof (UInt32)); + createCol(items, "currentPermissions", typeof (UInt32)); + createCol(items, "basePermissions", typeof (UInt32)); + createCol(items, "everyonePermissions", typeof (UInt32)); + createCol(items, "groupPermissions", typeof (UInt32)); + createCol(items, "flags", typeof (UInt32)); + + items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] }; + + return items; + } + + /// + /// Creates "land" table + /// + /// land table DataTable + private static DataTable createLandTable() + { + DataTable land = new DataTable("land"); + createCol(land, "UUID", typeof (String)); + createCol(land, "RegionUUID", typeof (String)); + createCol(land, "LocalLandID", typeof (UInt32)); + + // Bitmap is a byte[512] + createCol(land, "Bitmap", typeof (Byte[])); + + createCol(land, "Name", typeof (String)); + createCol(land, "Desc", typeof (String)); + createCol(land, "OwnerUUID", typeof (String)); + createCol(land, "IsGroupOwned", typeof (Boolean)); + createCol(land, "Area", typeof (Int32)); + createCol(land, "AuctionID", typeof (Int32)); //Unemplemented + createCol(land, "Category", typeof (Int32)); //Enum OpenMetaverse.Parcel.ParcelCategory + createCol(land, "ClaimDate", typeof (Int32)); + createCol(land, "ClaimPrice", typeof (Int32)); + createCol(land, "GroupUUID", typeof (string)); + createCol(land, "SalePrice", typeof (Int32)); + createCol(land, "LandStatus", typeof (Int32)); //Enum. OpenMetaverse.Parcel.ParcelStatus + createCol(land, "LandFlags", typeof (UInt32)); + createCol(land, "LandingType", typeof (Byte)); + createCol(land, "MediaAutoScale", typeof (Byte)); + createCol(land, "MediaTextureUUID", typeof (String)); + createCol(land, "MediaURL", typeof (String)); + createCol(land, "MusicURL", typeof (String)); + createCol(land, "PassHours", typeof (Double)); + createCol(land, "PassPrice", typeof (UInt32)); + createCol(land, "SnapshotUUID", typeof (String)); + createCol(land, "UserLocationX", typeof (Double)); + createCol(land, "UserLocationY", typeof (Double)); + createCol(land, "UserLocationZ", typeof (Double)); + createCol(land, "UserLookAtX", typeof (Double)); + createCol(land, "UserLookAtY", typeof (Double)); + createCol(land, "UserLookAtZ", typeof (Double)); + createCol(land, "AuthbuyerID", typeof(String)); + createCol(land, "OtherCleanTime", typeof(Int32)); + createCol(land, "Dwell", typeof(Int32)); + + land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; + + return land; + } + + /// + /// create "landaccesslist" table + /// + /// Landacceslist DataTable + private static DataTable createLandAccessListTable() + { + DataTable landaccess = new DataTable("landaccesslist"); + createCol(landaccess, "LandUUID", typeof (String)); + createCol(landaccess, "AccessUUID", typeof (String)); + createCol(landaccess, "Flags", typeof (UInt32)); + + return landaccess; + } + + private static DataTable createRegionSettingsTable() + { + DataTable regionsettings = new DataTable("regionsettings"); + createCol(regionsettings, "regionUUID", typeof(String)); + createCol(regionsettings, "block_terraform", typeof (Int32)); + createCol(regionsettings, "block_fly", typeof (Int32)); + createCol(regionsettings, "allow_damage", typeof (Int32)); + createCol(regionsettings, "restrict_pushing", typeof (Int32)); + createCol(regionsettings, "allow_land_resell", typeof (Int32)); + createCol(regionsettings, "allow_land_join_divide", typeof (Int32)); + createCol(regionsettings, "block_show_in_search", typeof (Int32)); + createCol(regionsettings, "agent_limit", typeof (Int32)); + createCol(regionsettings, "object_bonus", typeof (Double)); + createCol(regionsettings, "maturity", typeof (Int32)); + createCol(regionsettings, "disable_scripts", typeof (Int32)); + createCol(regionsettings, "disable_collisions", typeof (Int32)); + createCol(regionsettings, "disable_physics", typeof (Int32)); + createCol(regionsettings, "terrain_texture_1", typeof(String)); + createCol(regionsettings, "terrain_texture_2", typeof(String)); + createCol(regionsettings, "terrain_texture_3", typeof(String)); + createCol(regionsettings, "terrain_texture_4", typeof(String)); + createCol(regionsettings, "elevation_1_nw", typeof (Double)); + createCol(regionsettings, "elevation_2_nw", typeof (Double)); + createCol(regionsettings, "elevation_1_ne", typeof (Double)); + createCol(regionsettings, "elevation_2_ne", typeof (Double)); + createCol(regionsettings, "elevation_1_se", typeof (Double)); + createCol(regionsettings, "elevation_2_se", typeof (Double)); + createCol(regionsettings, "elevation_1_sw", typeof (Double)); + createCol(regionsettings, "elevation_2_sw", typeof (Double)); + createCol(regionsettings, "water_height", typeof (Double)); + createCol(regionsettings, "terrain_raise_limit", typeof (Double)); + createCol(regionsettings, "terrain_lower_limit", typeof (Double)); + createCol(regionsettings, "use_estate_sun", typeof (Int32)); + createCol(regionsettings, "sandbox", typeof (Int32)); + createCol(regionsettings, "sunvectorx",typeof (Double)); + createCol(regionsettings, "sunvectory",typeof (Double)); + createCol(regionsettings, "sunvectorz",typeof (Double)); + createCol(regionsettings, "fixed_sun", typeof (Int32)); + createCol(regionsettings, "sun_position", typeof (Double)); + createCol(regionsettings, "covenant", typeof(String)); + regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] }; + return regionsettings; + } + + /*********************************************************************** + * + * Convert between ADO.NET <=> OpenSim Objects + * + * These should be database independant + * + **********************************************************************/ + + /// + /// + /// + /// + /// + private SceneObjectPart buildPrim(DataRow row) + { + // Code commented. Uncomment to test the unit test inline. + + // The unit test mentions this commented code for the purposes + // of debugging a unit test failure + + // SceneObjectGroup sog = new SceneObjectGroup(); + // SceneObjectPart sop = new SceneObjectPart(); + // sop.LocalId = 1; + // sop.Name = "object1"; + // sop.Description = "object1"; + // sop.Text = ""; + // sop.SitName = ""; + // sop.TouchName = ""; + // sop.UUID = UUID.Random(); + // sop.Shape = PrimitiveBaseShape.Default; + // sog.SetRootPart(sop); + // Add breakpoint in above line. Check sop fields. + + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + + SceneObjectPart prim = new SceneObjectPart(); + prim.UUID = new UUID((String) row["UUID"]); + // explicit conversion of integers is required, which sort + // of sucks. No idea if there is a shortcut here or not. + prim.CreationDate = Convert.ToInt32(row["CreationDate"]); + prim.Name = row["Name"] == DBNull.Value ? string.Empty : (string)row["Name"]; + // various text fields + prim.Text = (String) row["Text"]; + prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), + Convert.ToInt32(row["ColorR"]), + Convert.ToInt32(row["ColorG"]), + Convert.ToInt32(row["ColorB"])); + prim.Description = (String) row["Description"]; + prim.SitName = (String) row["SitName"]; + prim.TouchName = (String) row["TouchName"]; + // permissions + prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); + prim.CreatorID = new UUID((String) row["CreatorID"]); + prim.OwnerID = new UUID((String) row["OwnerID"]); + prim.GroupID = new UUID((String) row["GroupID"]); + prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); + prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); + prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); + prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); + prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); + prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); + // vectors + prim.OffsetPosition = new Vector3( + Convert.ToSingle(row["PositionX"]), + Convert.ToSingle(row["PositionY"]), + Convert.ToSingle(row["PositionZ"]) + ); + prim.GroupPosition = new Vector3( + Convert.ToSingle(row["GroupPositionX"]), + Convert.ToSingle(row["GroupPositionY"]), + Convert.ToSingle(row["GroupPositionZ"]) + ); + prim.Velocity = new Vector3( + Convert.ToSingle(row["VelocityX"]), + Convert.ToSingle(row["VelocityY"]), + Convert.ToSingle(row["VelocityZ"]) + ); + prim.AngularVelocity = new Vector3( + Convert.ToSingle(row["AngularVelocityX"]), + Convert.ToSingle(row["AngularVelocityY"]), + Convert.ToSingle(row["AngularVelocityZ"]) + ); + prim.Acceleration = new Vector3( + Convert.ToSingle(row["AccelerationX"]), + Convert.ToSingle(row["AccelerationY"]), + Convert.ToSingle(row["AccelerationZ"]) + ); + // quaternions + prim.RotationOffset = new Quaternion( + Convert.ToSingle(row["RotationX"]), + Convert.ToSingle(row["RotationY"]), + Convert.ToSingle(row["RotationZ"]), + Convert.ToSingle(row["RotationW"]) + ); + + prim.SitTargetPositionLL = new Vector3( + Convert.ToSingle(row["SitTargetOffsetX"]), + Convert.ToSingle(row["SitTargetOffsetY"]), + Convert.ToSingle(row["SitTargetOffsetZ"])); + prim.SitTargetOrientationLL = new Quaternion( + Convert.ToSingle( + row["SitTargetOrientX"]), + Convert.ToSingle( + row["SitTargetOrientY"]), + Convert.ToSingle( + row["SitTargetOrientZ"]), + Convert.ToSingle( + row["SitTargetOrientW"])); + + prim.ClickAction = Convert.ToByte(row["ClickAction"]); + prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); + prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); + prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); + prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); + prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); + + prim.Sound = new UUID(row["LoopedSound"].ToString()); + prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); + prim.SoundFlags = 1; // If it's persisted at all, it's looped + + if (!row.IsNull("TextureAnimation")) + prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString()); + if (!row.IsNull("ParticleSystem")) + prim.ParticleSystem = Convert.FromBase64String(row["ParticleSystem"].ToString()); + + prim.AngularVelocity = new Vector3( + Convert.ToSingle(row["OmegaX"]), + Convert.ToSingle(row["OmegaY"]), + Convert.ToSingle(row["OmegaZ"]) + ); + + prim.SetCameraEyeOffset(new Vector3( + Convert.ToSingle(row["CameraEyeOffsetX"]), + Convert.ToSingle(row["CameraEyeOffsetY"]), + Convert.ToSingle(row["CameraEyeOffsetZ"]) + )); + + prim.SetCameraAtOffset(new Vector3( + Convert.ToSingle(row["CameraAtOffsetX"]), + Convert.ToSingle(row["CameraAtOffsetY"]), + Convert.ToSingle(row["CameraAtOffsetZ"]) + )); + + if (Convert.ToInt16(row["ForceMouselook"]) != 0) + prim.SetForceMouselook(true); + + prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); + + if (Convert.ToInt16(row["AllowedDrop"]) != 0) + prim.AllowedDrop = true; + + if (Convert.ToInt16(row["DieAtEdge"]) != 0) + prim.DIE_AT_EDGE = true; + + prim.SalePrice = Convert.ToInt32(row["SalePrice"]); + prim.ObjectSaleType = Convert.ToByte(row["SaleType"]); + + prim.Material = Convert.ToByte(row["Material"]); + + prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); + prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); + + if (Convert.ToInt16(row["VolumeDetect"]) != 0) + prim.VolumeDetectActive = true; + + return prim; + } + + /// + /// Build a prim inventory item from the persisted data. + /// + /// + /// + private static TaskInventoryItem buildItem(DataRow row) + { + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = new UUID((String)row["itemID"]); + taskItem.ParentPartID = new UUID((String)row["primID"]); + taskItem.AssetID = new UUID((String)row["assetID"]); + taskItem.ParentID = new UUID((String)row["parentFolderID"]); + + taskItem.InvType = Convert.ToInt32(row["invType"]); + taskItem.Type = Convert.ToInt32(row["assetType"]); + + taskItem.Name = (String)row["name"]; + taskItem.Description = (String)row["description"]; + taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); + taskItem.CreatorID = new UUID((String)row["creatorID"]); + taskItem.OwnerID = new UUID((String)row["ownerID"]); + taskItem.LastOwnerID = new UUID((String)row["lastOwnerID"]); + taskItem.GroupID = new UUID((String)row["groupID"]); + + taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); + taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); + taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); + taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); + taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); + taskItem.Flags = Convert.ToUInt32(row["flags"]); + + return taskItem; + } + + /// + /// Build a Land Data from the persisted data. + /// + /// + /// + private LandData buildLandData(DataRow row) + { + LandData newData = new LandData(); + + newData.GlobalID = new UUID((String) row["UUID"]); + newData.LocalID = Convert.ToInt32(row["LocalLandID"]); + + // Bitmap is a byte[512] + newData.Bitmap = (Byte[]) row["Bitmap"]; + + newData.Name = (String) row["Name"]; + newData.Description = (String) row["Desc"]; + newData.OwnerID = (UUID)(String) row["OwnerUUID"]; + newData.IsGroupOwned = (Boolean) row["IsGroupOwned"]; + newData.Area = Convert.ToInt32(row["Area"]); + newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented + newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]); + //Enum OpenMetaverse.Parcel.ParcelCategory + newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); + newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); + newData.GroupID = new UUID((String) row["GroupUUID"]); + newData.SalePrice = Convert.ToInt32(row["SalePrice"]); + newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]); + //Enum. OpenMetaverse.Parcel.ParcelStatus + newData.Flags = Convert.ToUInt32(row["LandFlags"]); + newData.LandingType = (Byte) row["LandingType"]; + newData.MediaAutoScale = (Byte) row["MediaAutoScale"]; + newData.MediaID = new UUID((String) row["MediaTextureUUID"]); + newData.MediaURL = (String) row["MediaURL"]; + newData.MusicURL = (String) row["MusicURL"]; + newData.PassHours = Convert.ToSingle(row["PassHours"]); + newData.PassPrice = Convert.ToInt32(row["PassPrice"]); + newData.SnapshotID = (UUID)(String) row["SnapshotUUID"]; + try + { + + newData.UserLocation = + new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), + Convert.ToSingle(row["UserLocationZ"])); + newData.UserLookAt = + new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), + Convert.ToSingle(row["UserLookAtZ"])); + + } + catch (InvalidCastException) + { + m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); + newData.UserLocation = Vector3.Zero; + newData.UserLookAt = Vector3.Zero; + } + newData.ParcelAccessList = new List(); + UUID authBuyerID = UUID.Zero; + + UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID); + + newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); + newData.Dwell = Convert.ToInt32(row["Dwell"]); + + return newData; + } + + private RegionSettings buildRegionSettings(DataRow row) + { + RegionSettings newSettings = new RegionSettings(); + + newSettings.RegionUUID = new UUID((string) row["regionUUID"]); + newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); + newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); + newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); + newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); + newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); + newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); + newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); + newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); + newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); + newSettings.Maturity = Convert.ToInt32(row["maturity"]); + newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); + newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); + newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); + newSettings.TerrainTexture1 = new UUID((String) row["terrain_texture_1"]); + newSettings.TerrainTexture2 = new UUID((String) row["terrain_texture_2"]); + newSettings.TerrainTexture3 = new UUID((String) row["terrain_texture_3"]); + newSettings.TerrainTexture4 = new UUID((String) row["terrain_texture_4"]); + newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); + newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); + newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); + newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); + newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); + newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); + newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); + newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); + newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); + newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); + newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); + newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); + newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); + newSettings.SunVector = new Vector3 ( + Convert.ToSingle(row["sunvectorx"]), + Convert.ToSingle(row["sunvectory"]), + Convert.ToSingle(row["sunvectorz"]) + ); + newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); + newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); + newSettings.Covenant = new UUID((String) row["covenant"]); + + return newSettings; + } + + /// + /// Build a land access entry from the persisted data. + /// + /// + /// + private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = new UUID((string) row["AccessUUID"]); + entry.Flags = (AccessList) row["Flags"]; + entry.Time = new DateTime(); + return entry; + } + + /// + /// + /// + /// + /// + private static Array serializeTerrain(double[,] val) + { + MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); + BinaryWriter bw = new BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < (int)Constants.RegionSize; x++) + for (int y = 0; y < (int)Constants.RegionSize; y++) + bw.Write(val[x, y]); + + return str.ToArray(); + } + +// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val) +// { +// row["RegionUUID"] = regionUUID; +// row["Revision"] = rev; + + // MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double)); +// BinaryWriter bw = new BinaryWriter(str); + +// // TODO: COMPATIBILITY - Add byte-order conversions + // for (int x = 0; x < (int)Constants.RegionSize; x++) + // for (int y = 0; y < (int)Constants.RegionSize; y++) +// bw.Write(val[x, y]); + +// row["Heightfield"] = str.ToArray(); +// } + + /// + /// + /// + /// + /// + /// + /// + private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + row["UUID"] = prim.UUID.ToString(); + row["RegionUUID"] = regionUUID.ToString(); + row["CreationDate"] = prim.CreationDate; + row["Name"] = prim.Name; + row["SceneGroupID"] = sceneGroupID.ToString(); + // the UUID of the root part for this SceneObjectGroup + // various text fields + row["Text"] = prim.Text; + row["Description"] = prim.Description; + row["SitName"] = prim.SitName; + row["TouchName"] = prim.TouchName; + // permissions + row["ObjectFlags"] = prim.ObjectFlags; + row["CreatorID"] = prim.CreatorID.ToString(); + row["OwnerID"] = prim.OwnerID.ToString(); + row["GroupID"] = prim.GroupID.ToString(); + row["LastOwnerID"] = prim.LastOwnerID.ToString(); + row["OwnerMask"] = prim.OwnerMask; + row["NextOwnerMask"] = prim.NextOwnerMask; + row["GroupMask"] = prim.GroupMask; + row["EveryoneMask"] = prim.EveryoneMask; + row["BaseMask"] = prim.BaseMask; + // vectors + row["PositionX"] = prim.OffsetPosition.X; + row["PositionY"] = prim.OffsetPosition.Y; + row["PositionZ"] = prim.OffsetPosition.Z; + row["GroupPositionX"] = prim.GroupPosition.X; + row["GroupPositionY"] = prim.GroupPosition.Y; + row["GroupPositionZ"] = prim.GroupPosition.Z; + row["VelocityX"] = prim.Velocity.X; + row["VelocityY"] = prim.Velocity.Y; + row["VelocityZ"] = prim.Velocity.Z; + row["AngularVelocityX"] = prim.AngularVelocity.X; + row["AngularVelocityY"] = prim.AngularVelocity.Y; + row["AngularVelocityZ"] = prim.AngularVelocity.Z; + row["AccelerationX"] = prim.Acceleration.X; + row["AccelerationY"] = prim.Acceleration.Y; + row["AccelerationZ"] = prim.Acceleration.Z; + // quaternions + row["RotationX"] = prim.RotationOffset.X; + row["RotationY"] = prim.RotationOffset.Y; + row["RotationZ"] = prim.RotationOffset.Z; + row["RotationW"] = prim.RotationOffset.W; + + // Sit target + Vector3 sitTargetPos = prim.SitTargetPositionLL; + row["SitTargetOffsetX"] = sitTargetPos.X; + row["SitTargetOffsetY"] = sitTargetPos.Y; + row["SitTargetOffsetZ"] = sitTargetPos.Z; + + Quaternion sitTargetOrient = prim.SitTargetOrientationLL; + row["SitTargetOrientW"] = sitTargetOrient.W; + row["SitTargetOrientX"] = sitTargetOrient.X; + row["SitTargetOrientY"] = sitTargetOrient.Y; + row["SitTargetOrientZ"] = sitTargetOrient.Z; + row["ColorR"] = Convert.ToInt32(prim.Color.R); + row["ColorG"] = Convert.ToInt32(prim.Color.G); + row["ColorB"] = Convert.ToInt32(prim.Color.B); + row["ColorA"] = Convert.ToInt32(prim.Color.A); + row["PayPrice"] = prim.PayPrice[0]; + row["PayButton1"] = prim.PayPrice[1]; + row["PayButton2"] = prim.PayPrice[2]; + row["PayButton3"] = prim.PayPrice[3]; + row["PayButton4"] = prim.PayPrice[4]; + + + row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation); + row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem); + + row["OmegaX"] = prim.AngularVelocity.X; + row["OmegaY"] = prim.AngularVelocity.Y; + row["OmegaZ"] = prim.AngularVelocity.Z; + + row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X; + row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y; + row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z; + + row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X; + row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y; + row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z; + + + if ((prim.SoundFlags & 1) != 0) // Looped + { + row["LoopedSound"] = prim.Sound.ToString(); + row["LoopedSoundGain"] = prim.SoundGain; + } + else + { + row["LoopedSound"] = UUID.Zero.ToString(); + row["LoopedSoundGain"] = 0.0f; + } + + if (prim.GetForceMouselook()) + row["ForceMouselook"] = 1; + else + row["ForceMouselook"] = 0; + + row["ScriptAccessPin"] = prim.ScriptAccessPin; + + if (prim.AllowedDrop) + row["AllowedDrop"] = 1; + else + row["AllowedDrop"] = 0; + + if (prim.DIE_AT_EDGE) + row["DieAtEdge"] = 1; + else + row["DieAtEdge"] = 0; + + row["SalePrice"] = prim.SalePrice; + row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType); + + // click action + row["ClickAction"] = prim.ClickAction; + + row["SalePrice"] = prim.SalePrice; + row["Material"] = prim.Material; + + row["CollisionSound"] = prim.CollisionSound.ToString(); + row["CollisionSoundVolume"] = prim.CollisionSoundVolume; + if (prim.VolumeDetectActive) + row["VolumeDetect"] = 1; + else + row["VolumeDetect"] = 0; + + } + + /// + /// + /// + /// + /// + private static void fillItemRow(DataRow row, TaskInventoryItem taskItem) + { + row["itemID"] = taskItem.ItemID.ToString(); + row["primID"] = taskItem.ParentPartID.ToString(); + row["assetID"] = taskItem.AssetID.ToString(); + row["parentFolderID"] = taskItem.ParentID.ToString(); + + row["invType"] = taskItem.InvType; + row["assetType"] = taskItem.Type; + + row["name"] = taskItem.Name; + row["description"] = taskItem.Description; + row["creationDate"] = taskItem.CreationDate; + row["creatorID"] = taskItem.CreatorID.ToString(); + row["ownerID"] = taskItem.OwnerID.ToString(); + row["lastOwnerID"] = taskItem.LastOwnerID.ToString(); + row["groupID"] = taskItem.GroupID.ToString(); + row["nextPermissions"] = taskItem.NextPermissions; + row["currentPermissions"] = taskItem.CurrentPermissions; + row["basePermissions"] = taskItem.BasePermissions; + row["everyonePermissions"] = taskItem.EveryonePermissions; + row["groupPermissions"] = taskItem.GroupPermissions; + row["flags"] = taskItem.Flags; + } + + /// + /// + /// + /// + /// + /// + private static void fillLandRow(DataRow row, LandData land, UUID regionUUID) + { + row["UUID"] = land.GlobalID.ToString(); + row["RegionUUID"] = regionUUID.ToString(); + row["LocalLandID"] = land.LocalID; + + // Bitmap is a byte[512] + row["Bitmap"] = land.Bitmap; + + row["Name"] = land.Name; + row["Desc"] = land.Description; + row["OwnerUUID"] = land.OwnerID.ToString(); + row["IsGroupOwned"] = land.IsGroupOwned; + row["Area"] = land.Area; + row["AuctionID"] = land.AuctionID; //Unemplemented + row["Category"] = land.Category; //Enum OpenMetaverse.Parcel.ParcelCategory + row["ClaimDate"] = land.ClaimDate; + row["ClaimPrice"] = land.ClaimPrice; + row["GroupUUID"] = land.GroupID.ToString(); + row["SalePrice"] = land.SalePrice; + row["LandStatus"] = land.Status; //Enum. OpenMetaverse.Parcel.ParcelStatus + row["LandFlags"] = land.Flags; + row["LandingType"] = land.LandingType; + row["MediaAutoScale"] = land.MediaAutoScale; + row["MediaTextureUUID"] = land.MediaID.ToString(); + row["MediaURL"] = land.MediaURL; + row["MusicURL"] = land.MusicURL; + row["PassHours"] = land.PassHours; + row["PassPrice"] = land.PassPrice; + row["SnapshotUUID"] = land.SnapshotID.ToString(); + row["UserLocationX"] = land.UserLocation.X; + row["UserLocationY"] = land.UserLocation.Y; + row["UserLocationZ"] = land.UserLocation.Z; + row["UserLookAtX"] = land.UserLookAt.X; + row["UserLookAtY"] = land.UserLookAt.Y; + row["UserLookAtZ"] = land.UserLookAt.Z; + row["AuthbuyerID"] = land.AuthBuyerID.ToString(); + row["OtherCleanTime"] = land.OtherCleanTime; + row["Dwell"] = land.Dwell; + } + + /// + /// + /// + /// + /// + /// + private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID) + { + row["LandUUID"] = parcelID.ToString(); + row["AccessUUID"] = entry.AgentID.ToString(); + row["Flags"] = entry.Flags; + } + + private static void fillRegionSettingsRow(DataRow row, RegionSettings settings) + { + row["regionUUID"] = settings.RegionUUID.ToString(); + row["block_terraform"] = settings.BlockTerraform; + row["block_fly"] = settings.BlockFly; + row["allow_damage"] = settings.AllowDamage; + row["restrict_pushing"] = settings.RestrictPushing; + row["allow_land_resell"] = settings.AllowLandResell; + row["allow_land_join_divide"] = settings.AllowLandJoinDivide; + row["block_show_in_search"] = settings.BlockShowInSearch; + row["agent_limit"] = settings.AgentLimit; + row["object_bonus"] = settings.ObjectBonus; + row["maturity"] = settings.Maturity; + row["disable_scripts"] = settings.DisableScripts; + row["disable_collisions"] = settings.DisableCollisions; + row["disable_physics"] = settings.DisablePhysics; + row["terrain_texture_1"] = settings.TerrainTexture1.ToString(); + row["terrain_texture_2"] = settings.TerrainTexture2.ToString(); + row["terrain_texture_3"] = settings.TerrainTexture3.ToString(); + row["terrain_texture_4"] = settings.TerrainTexture4.ToString(); + row["elevation_1_nw"] = settings.Elevation1NW; + row["elevation_2_nw"] = settings.Elevation2NW; + row["elevation_1_ne"] = settings.Elevation1NE; + row["elevation_2_ne"] = settings.Elevation2NE; + row["elevation_1_se"] = settings.Elevation1SE; + row["elevation_2_se"] = settings.Elevation2SE; + row["elevation_1_sw"] = settings.Elevation1SW; + row["elevation_2_sw"] = settings.Elevation2SW; + row["water_height"] = settings.WaterHeight; + row["terrain_raise_limit"] = settings.TerrainRaiseLimit; + row["terrain_lower_limit"] = settings.TerrainLowerLimit; + row["use_estate_sun"] = settings.UseEstateSun; + row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox + row["sunvectorx"] = settings.SunVector.X; + row["sunvectory"] = settings.SunVector.Y; + row["sunvectorz"] = settings.SunVector.Z; + row["fixed_sun"] = settings.FixedSun; + row["sun_position"] = settings.SunPosition; + row["covenant"] = settings.Covenant.ToString(); + } + + /// + /// + /// + /// + /// + private PrimitiveBaseShape buildShape(DataRow row) + { + PrimitiveBaseShape s = new PrimitiveBaseShape(); + s.Scale = new Vector3( + Convert.ToSingle(row["ScaleX"]), + Convert.ToSingle(row["ScaleY"]), + Convert.ToSingle(row["ScaleZ"]) + ); + // paths + s.PCode = Convert.ToByte(row["PCode"]); + s.PathBegin = Convert.ToUInt16(row["PathBegin"]); + s.PathEnd = Convert.ToUInt16(row["PathEnd"]); + s.PathScaleX = Convert.ToByte(row["PathScaleX"]); + s.PathScaleY = Convert.ToByte(row["PathScaleY"]); + s.PathShearX = Convert.ToByte(row["PathShearX"]); + s.PathShearY = Convert.ToByte(row["PathShearY"]); + s.PathSkew = Convert.ToSByte(row["PathSkew"]); + s.PathCurve = Convert.ToByte(row["PathCurve"]); + s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); + s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); + s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); + s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); + s.PathTwist = Convert.ToSByte(row["PathTwist"]); + s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); + // profile + s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); + s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); + s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); + s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); + s.State = Convert.ToByte(row["State"]); + + byte[] textureEntry = (byte[])row["Texture"]; + s.TextureEntry = textureEntry; + + s.ExtraParams = (byte[]) row["ExtraParams"]; + return s; + } + + /// + /// + /// + /// + /// + private static void fillShapeRow(DataRow row, SceneObjectPart prim) + { + PrimitiveBaseShape s = prim.Shape; + row["UUID"] = prim.UUID.ToString(); + // shape is an enum + row["Shape"] = 0; + // vectors + row["ScaleX"] = s.Scale.X; + row["ScaleY"] = s.Scale.Y; + row["ScaleZ"] = s.Scale.Z; + // paths + row["PCode"] = s.PCode; + row["PathBegin"] = s.PathBegin; + row["PathEnd"] = s.PathEnd; + row["PathScaleX"] = s.PathScaleX; + row["PathScaleY"] = s.PathScaleY; + row["PathShearX"] = s.PathShearX; + row["PathShearY"] = s.PathShearY; + row["PathSkew"] = s.PathSkew; + row["PathCurve"] = s.PathCurve; + row["PathRadiusOffset"] = s.PathRadiusOffset; + row["PathRevolutions"] = s.PathRevolutions; + row["PathTaperX"] = s.PathTaperX; + row["PathTaperY"] = s.PathTaperY; + row["PathTwist"] = s.PathTwist; + row["PathTwistBegin"] = s.PathTwistBegin; + // profile + row["ProfileBegin"] = s.ProfileBegin; + row["ProfileEnd"] = s.ProfileEnd; + row["ProfileCurve"] = s.ProfileCurve; + row["ProfileHollow"] = s.ProfileHollow; + row["State"] = s.State; + + row["Texture"] = s.TextureEntry; + row["ExtraParams"] = s.ExtraParams; + } + + /// + /// + /// + /// + /// + /// + private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + DataRow primRow = prims.Rows.Find(prim.UUID.ToString()); + if (primRow == null) + { + primRow = prims.NewRow(); + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + prims.Rows.Add(primRow); + } + else + { + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + } + + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow == null) + { + shapeRow = shapes.NewRow(); + fillShapeRow(shapeRow, prim); + shapes.Rows.Add(shapeRow); + } + else + { + fillShapeRow(shapeRow, prim); + } + } + + /// + /// see IRegionDatastore + /// + /// + /// + public void StorePrimInventory(UUID primID, ICollection items) + { + m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); + + DataTable dbItems = ds.Tables["primitems"]; + + // For now, we're just going to crudely remove all the previous inventory items + // no matter whether they have changed or not, and replace them with the current set. + lock (ds) + { + RemoveItems(primID); + + // repalce with current inventory details + foreach (TaskInventoryItem newItem in items) + { +// m_log.InfoFormat( +// "[DATASTORE]: ", +// "Adding item {0}, {1} to prim ID {2}", +// newItem.Name, newItem.ItemID, newItem.ParentPartID); + + DataRow newItemRow = dbItems.NewRow(); + fillItemRow(newItemRow, newItem); + dbItems.Rows.Add(newItemRow); + } + } + + Commit(); + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + /// + /// Create an insert command + /// + /// table name + /// data table + /// the created command + /// + /// This is subtle enough to deserve some commentary. + /// Instead of doing *lots* and *lots of hardcoded strings + /// for database definitions we'll use the fact that + /// realistically all insert statements look like "insert + /// into A(b, c) values(:b, :c) on the parameterized query + /// front. If we just have a list of b, c, etc... we can + /// generate these strings instead of typing them out. + /// + private static SqliteCommand createInsertCommand(string table, DataTable dt) + { + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (:"; + sql += String.Join(", :", cols); + sql += ")"; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + private static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + private static SqliteCommand createUpdateCommand(string table, string pk1, string pk2, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk1 + " and " + pk2; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// + /// + /// Data Table + /// + // private static string defineTable(DataTable dt) + // { + // string sql = "create table " + dt.TableName + "("; + // string subsql = String.Empty; + // foreach (DataColumn col in dt.Columns) + // { + // if (subsql.Length > 0) + // { + // // a map function would rock so much here + // subsql += ",\n"; + // } + // subsql += col.ColumnName + " " + sqliteType(col.DataType); + // if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) + // { + // subsql += " primary key"; + // } + // } + // sql += subsql; + // sql += ")"; + // return sql; + // } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining SqliteParameters to 2 parameters: + /// column name and database type. + /// + /// It assumes certain conventions like :param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + ///a built sqlite parameter + private static SqliteParameter createSqliteParameter(string name, Type type) + { + SqliteParameter param = new SqliteParameter(); + param.ParameterName = ":" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + /// + /// + /// + /// + /// + private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /// + /// + /// + /// + /// + private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID"); + delete.Parameters.Add(createSqliteParameter("itemID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /// + /// + /// + /// + /// + private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); + da.InsertCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("land", ds.Tables["land"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from land where UUID=:UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); + da.DeleteCommand = delete; + da.DeleteCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("landaccesslist", "LandUUID=:landUUID", "AccessUUID=:AccessUUID", ds.Tables["landaccesslist"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from landaccesslist where LandUUID= :LandUUID and AccessUUID= :AccessUUID"); + delete.Parameters.Add(createSqliteParameter("LandUUID", typeof(String))); + delete.Parameters.Add(createSqliteParameter("AccessUUID", typeof(String))); + da.DeleteCommand = delete; + da.DeleteCommand.Connection = conn; + + } + + private void setupRegionSettingsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("regionsettings", ds.Tables["regionsettings"]); + da.InsertCommand.Connection = conn; + da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID=:regionUUID", ds.Tables["regionsettings"]); + da.UpdateCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + /// + /// Type conversion function + /// + /// + /// + private static DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte)) + { + return DbType.Byte; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs b/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs new file mode 100644 index 0000000..67cf716 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs @@ -0,0 +1,81 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLite +{ + public class SQLiteUserAccountData : SQLiteGenericTableHandler, IUserAccountData + { + public SQLiteUserAccountData(string connectionString, string realm) + : base(connectionString, realm, "UserAccount") + { + } + + public UserAccountData[] GetUsers(UUID scopeID, string query) + { + string[] words = query.Split(new char[] {' '}); + + for (int i = 0 ; i < words.Length ; i++) + { + if (words[i].Length < 3) + { + if (i != words.Length - 1) + Array.Copy(words, i + 1, words, i, words.Length - i - 1); + Array.Resize(ref words, words.Length - 1); + } + } + + if (words.Length == 0) + return new UserAccountData[0]; + + if (words.Length > 2) + return new UserAccountData[0]; + + SqliteCommand cmd = new SqliteCommand(); + + if (words.Length == 1) + { + cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", + m_Realm, scopeID.ToString(), words[0]); + } + else + { + cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{3}%')", + m_Realm, scopeID.ToString(), words[0], words[1]); + } + + return DoQuery(cmd); + } + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteUtils.cs b/OpenSim/Data/SQLiteNG/SQLiteUtils.cs new file mode 100644 index 0000000..4a835ce --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteUtils.cs @@ -0,0 +1,307 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Data; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLite +{ + /// + /// A base class for methods needed by all SQLite database classes + /// + public class SQLiteUtil + { + /*********************************************************************** + * + * Database Definition Helper Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + /// + /// + /// + /// + /// + /// + public static void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + /// + /// Create an insert command + /// + /// table name + /// data table + /// the created command + /// + /// This is subtle enough to deserve some commentary. + /// Instead of doing *lots* and *lots of hardcoded strings + /// for database definitions we'll use the fact that + /// realistically all insert statements look like "insert + /// into A(b, c) values(:b, :c) on the parameterized query + /// front. If we just have a list of b, c, etc... we can + /// generate these strings instead of typing them out. + /// + public static SqliteCommand createInsertCommand(string table, DataTable dt) + { + + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (:"; + sql += String.Join(", :", cols); + sql += ")"; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + public static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// + /// + /// Data Table + /// + public static string defineTable(DataTable dt) + { + string sql = "create table " + dt.TableName + "("; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ",\n"; + } + subsql += col.ColumnName + " " + sqliteType(col.DataType); + if (dt.PrimaryKey.Length > 0) + { + if (col == dt.PrimaryKey[0]) + { + subsql += " primary key"; + } + } + } + sql += subsql; + sql += ")"; + return sql; + } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining SqliteParameters to 2 parameters: + /// column name and database type. + /// + /// + /// + /// It assumes certain conventions like :param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + /// + /// + /// + ///a built sqlite parameter + public static SqliteParameter createSqliteParameter(string name, Type type) + { + SqliteParameter param = new SqliteParameter(); + param.ParameterName = ":" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + /// + /// Type conversion function + /// + /// a type + /// a DbType + public static DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (UInt32)) + { + return DbType.UInt32; + } + else if (type == typeof (Int64)) + { + return DbType.Int64; + } + else if (type == typeof (UInt64)) + { + return DbType.UInt64; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Boolean)) + { + return DbType.Boolean; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + /// + /// + /// a Type + /// a string + /// this is something we'll need to implement for each db slightly differently. + public static string sqliteType(Type type) + { + if (type == typeof (String)) + { + return "varchar(255)"; + } + else if (type == typeof (Int32)) + { + return "integer"; + } + else if (type == typeof (UInt32)) + { + return "integer"; + } + else if (type == typeof (Int64)) + { + return "varchar(255)"; + } + else if (type == typeof (UInt64)) + { + return "varchar(255)"; + } + else if (type == typeof (Double)) + { + return "float"; + } + else if (type == typeof (Boolean)) + { + return "integer"; + } + else if (type == typeof (Byte[])) + { + return "blob"; + } + else + { + return "string"; + } + } + } +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs b/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs new file mode 100644 index 0000000..a66e0c6 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs @@ -0,0 +1,155 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Data; +using System.Reflection; +using System.Collections.Generic; +using Mono.Data.SqliteClient; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.SQLite +{ + /// + /// A MySQL Interface for the Asset Server + /// + public class SQLiteXInventoryData : IXInventoryData + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private SQLiteGenericTableHandler m_Folders; + private SqliteItemHandler m_Items; + + public SQLiteXInventoryData(string conn, string realm) + { + m_Folders = new SQLiteGenericTableHandler( + conn, "inventoryfolders", "InventoryStore"); + m_Items = new SqliteItemHandler( + conn, "inventoryitems", String.Empty); + } + + public XInventoryFolder[] GetFolders(string[] fields, string[] vals) + { + return m_Folders.Get(fields, vals); + } + + public XInventoryItem[] GetItems(string[] fields, string[] vals) + { + return m_Items.Get(fields, vals); + } + + public bool StoreFolder(XInventoryFolder folder) + { + return m_Folders.Store(folder); + } + + public bool StoreItem(XInventoryItem item) + { + return m_Items.Store(item); + } + + public bool DeleteFolders(string field, string val) + { + return m_Folders.Delete(field, val); + } + + public bool DeleteItems(string field, string val) + { + return m_Items.Delete(field, val); + } + + public bool MoveItem(string id, string newParent) + { + return m_Items.MoveItem(id, newParent); + } + + public XInventoryItem[] GetActiveGestures(UUID principalID) + { + return m_Items.GetActiveGestures(principalID); + } + + public int GetAssetPermissions(UUID principalID, UUID assetID) + { + return m_Items.GetAssetPermissions(principalID, assetID); + } + } + + public class SqliteItemHandler : SQLiteGenericTableHandler + { + public SqliteItemHandler(string c, string t, string m) : + base(c, t, m) + { + } + + public bool MoveItem(string id, string newParent) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("update {0} set parentFolderID = :ParentFolderID where inventoryID = :InventoryID", m_Realm); + cmd.Parameters.Add(new SqliteParameter(":ParentFolderID", newParent)); + cmd.Parameters.Add(new SqliteParameter(":InventoryID", id)); + + return ExecuteNonQuery(cmd, m_Connection) == 0 ? false : true; + } + + public XInventoryItem[] GetActiveGestures(UUID principalID) + { + SqliteCommand cmd = new SqliteCommand(); + cmd.CommandText = String.Format("select * from inventoryitems where avatarId = :uuid and assetType = :type and flags = 1", m_Realm); + + cmd.Parameters.Add(new SqliteParameter(":uuid", principalID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":type", (int)AssetType.Gesture)); + + return DoQuery(cmd); + } + + public int GetAssetPermissions(UUID principalID, UUID assetID) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("select inventoryCurrentPermissions from inventoryitems where avatarID = :PrincipalID and assetID = :AssetID", m_Realm); + cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":AssetID", assetID.ToString())); + + IDataReader reader = ExecuteReader(cmd, m_Connection); + + int perms = 0; + + while (reader.Read()) + { + perms |= Convert.ToInt32(reader["inventoryCurrentPermissions"]); + } + + reader.Close(); + CloseCommand(cmd); + + return perms; + } + } +} diff --git a/OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs b/OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs new file mode 100644 index 0000000..0c2f5df --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs @@ -0,0 +1,64 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.IO; +using NUnit.Framework; +using OpenSim.Data.Tests; +using OpenSim.Tests.Common; + +namespace OpenSim.Data.SQLite.Tests +{ + [TestFixture, DatabaseTest] + public class SQLiteAssetTest : BasicAssetTest + { + public string file; + public string connect; + + [TestFixtureSetUp] + public void Init() + { + // SQLite doesn't work on power or z linux + if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd")) + { + Assert.Ignore(); + } + + SuperInit(); + file = Path.GetTempFileName() + ".db"; + connect = "URI=file:" + file + ",version=3"; + db = new SQLiteAssetData(); + db.Initialise(connect); + } + + [TestFixtureTearDown] + public void Cleanup() + { + db.Dispose(); + File.Delete(file); + } + } +} diff --git a/OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs b/OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs new file mode 100644 index 0000000..30f6641 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs @@ -0,0 +1,65 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.IO; +using NUnit.Framework; +using OpenSim.Data.Tests; +using OpenSim.Tests.Common; + +namespace OpenSim.Data.SQLite.Tests +{ + [TestFixture, DatabaseTest] + public class SQLiteEstateTest : BasicEstateTest + { + public string file = "regiontest.db"; + public string connect; + + [TestFixtureSetUp] + public void Init() + { + // SQLite doesn't work on power or z linux + if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd")) + { + Assert.Ignore(); + } + + SuperInit(); + file = Path.GetTempFileName() + ".db"; + connect = "URI=file:" + file + ",version=3"; + db = new SQLiteEstateStore(); + db.Initialise(connect); + regionDb = new SQLiteRegionData(); + regionDb.Initialise(connect); + } + + [TestFixtureTearDown] + public void Cleanup() + { + regionDb.Dispose(); + } + } +} diff --git a/OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs b/OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs new file mode 100644 index 0000000..98458a3 --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs @@ -0,0 +1,66 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.IO; +using NUnit.Framework; +using OpenSim.Data.Tests; +using OpenSim.Tests.Common; + +namespace OpenSim.Data.SQLite.Tests +{ + [TestFixture, DatabaseTest] + public class SQLiteInventoryTest : BasicInventoryTest + { + public string file; + public string connect; + + [TestFixtureSetUp] + public void Init() + { + // SQLite doesn't work on power or z linux + if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd")) + { + Assert.Ignore(); + } + + SuperInit(); + + file = Path.GetTempFileName() + ".db"; + connect = "URI=file:" + file + ",version=3"; + + db = new SQLiteInventoryStore(); + db.Initialise(connect); + } + + [TestFixtureTearDown] + public void Cleanup() + { + db.Dispose(); + File.Delete(file); + } + } +} diff --git a/OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs b/OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs new file mode 100644 index 0000000..abb97cf --- /dev/null +++ b/OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs @@ -0,0 +1,64 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.IO; +using NUnit.Framework; +using OpenSim.Data.Tests; +using OpenSim.Tests.Common; + +namespace OpenSim.Data.SQLite.Tests +{ + [TestFixture, DatabaseTest] + public class SQLiteRegionTest : BasicRegionTest + { + public string file = "regiontest.db"; + public string connect; + + [TestFixtureSetUp] + public void Init() + { + // SQLite doesn't work on power or z linux + if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd")) + { + Assert.Ignore(); + } + + SuperInit(); + file = Path.GetTempFileName() + ".db"; + connect = "URI=file:" + file + ",version=3"; + db = new SQLiteRegionData(); + db.Initialise(connect); + } + + [TestFixtureTearDown] + public void Cleanup() + { + db.Dispose(); + File.Delete(file); + } + } +} diff --git a/prebuild.xml b/prebuild.xml index 6b25792..9db30ff 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2510,6 +2510,43 @@ + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.1 From 7ce0ec874a31d2567bee43afa0cdec24e002dc1d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Apr 2010 18:56:50 +0100 Subject: Change SQLiteNG to work with mono 2.6 and above using the Mono.Data.Sqlite.dll Include the library so that Windows builds correctly It appears that Windows is okay with either SQLite or SQLiteNG Incorporate the latest fixes made by Diva to OpenSim.Data.SQLite --- OpenSim/Data/SQLiteNG/SQLiteAssetData.cs | 6 +- OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs | 23 +- OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs | 8 +- OpenSim/Data/SQLiteNG/SQLiteEstateData.cs | 48 ++-- OpenSim/Data/SQLiteNG/SQLiteFramework.cs | 14 +- OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs | 8 +- OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs | 18 +- OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs | 13 +- OpenSim/Data/SQLiteNG/SQLiteRegionData.cs | 258 +++++++++++++-------- OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs | 4 +- OpenSim/Data/SQLiteNG/SQLiteUtils.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs | 4 +- OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs | 64 ----- OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs | 65 ------ OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs | 66 ------ OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs | 64 ----- prebuild.xml | 3 +- 17 files changed, 237 insertions(+), 431 deletions(-) delete mode 100644 OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs delete mode 100644 OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs delete mode 100644 OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs delete mode 100644 OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs diff --git a/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs b/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs index a032670..636bf86 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs @@ -30,7 +30,7 @@ using System.Data; using System.Reflection; using System.Collections.Generic; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; @@ -137,7 +137,7 @@ namespace OpenSim.Data.SQLite cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); - + cmd.ExecuteNonQuery(); } } @@ -340,4 +340,4 @@ namespace OpenSim.Data.SQLite #endregion } -} \ No newline at end of file +} diff --git a/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs index aa10734..086ac0a 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs @@ -31,7 +31,7 @@ using System.Collections.Generic; using System.Data; using OpenMetaverse; using OpenSim.Framework; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; namespace OpenSim.Data.SQLite { @@ -56,13 +56,8 @@ namespace OpenSim.Data.SQLite m_Connection = new SqliteConnection(connectionString); m_Connection.Open(); - using (SqliteConnection dbcon = (SqliteConnection)((ICloneable)m_Connection).Clone()) - { - dbcon.Open(); - Migration m = new Migration(dbcon, GetType().Assembly, "AuthStore"); - m.Update(); - dbcon.Close(); - } + Migration m = new Migration(m_Connection, GetType().Assembly, "AuthStore"); + m.Update(); m_initialized = true; } @@ -113,7 +108,7 @@ namespace OpenSim.Data.SQLite } finally { - CloseCommand(cmd); + //CloseCommand(cmd); } return null; @@ -156,14 +151,14 @@ namespace OpenSim.Data.SQLite { if (ExecuteNonQuery(cmd, m_Connection) < 1) { - CloseCommand(cmd); + //CloseCommand(cmd); return false; } } catch (Exception e) { Console.WriteLine(e.ToString()); - CloseCommand(cmd); + //CloseCommand(cmd); return false; } } @@ -184,19 +179,19 @@ namespace OpenSim.Data.SQLite { if (ExecuteNonQuery(cmd, m_Connection) < 1) { - CloseCommand(cmd); + //CloseCommand(cmd); return false; } } catch (Exception e) { Console.WriteLine(e.ToString()); - CloseCommand(cmd); + //CloseCommand(cmd); return false; } } - CloseCommand(cmd); + //CloseCommand(cmd); return true; } diff --git a/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs b/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs index b3f4a4c..c093884 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs @@ -33,7 +33,7 @@ using System.Threading; using log4net; using OpenMetaverse; using OpenSim.Framework; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; namespace OpenSim.Data.SQLite { @@ -55,8 +55,8 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = new SqliteCommand(); cmd.CommandText = String.Format("delete from {0} where `PrincipalID` = :PrincipalID and `Name` = :Name", m_Realm); - cmd.Parameters.Add(":PrincipalID", principalID.ToString()); - cmd.Parameters.Add(":Name", name); + cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString()); + cmd.Parameters.AddWithValue(":Name", name); try { @@ -67,7 +67,7 @@ namespace OpenSim.Data.SQLite } finally { - CloseCommand(cmd); + //CloseCommand(cmd); } } } diff --git a/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs b/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs index bd6b776..9dd4a2e 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs @@ -30,7 +30,7 @@ using System.Collections.Generic; using System.Data; using System.Reflection; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -62,8 +62,8 @@ namespace OpenSim.Data.SQLite Migration m = new Migration(m_connection, assem, "EstateStore"); m.Update(); - m_connection.Close(); - m_connection.Open(); + //m_connection.Close(); + // m_connection.Open(); Type t = typeof(EstateSettings); m_Fields = t.GetFields(BindingFlags.NonPublic | @@ -87,7 +87,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = sql; - cmd.Parameters.Add(":RegionID", regionID.ToString()); + cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); return DoLoad(cmd, regionID, create); } @@ -143,13 +143,13 @@ namespace OpenSim.Data.SQLite if (m_FieldMap[name].GetValue(es) is bool) { if ((bool)m_FieldMap[name].GetValue(es)) - cmd.Parameters.Add(":"+name, "1"); + cmd.Parameters.AddWithValue(":"+name, "1"); else - cmd.Parameters.Add(":"+name, "0"); + cmd.Parameters.AddWithValue(":"+name, "0"); } else { - cmd.Parameters.Add(":"+name, m_FieldMap[name].GetValue(es).ToString()); + cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString()); } } @@ -167,8 +167,8 @@ namespace OpenSim.Data.SQLite r.Close(); cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; - cmd.Parameters.Add(":RegionID", regionID.ToString()); - cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); // This will throw on dupe key try @@ -211,13 +211,13 @@ namespace OpenSim.Data.SQLite if (m_FieldMap[name].GetValue(es) is bool) { if ((bool)m_FieldMap[name].GetValue(es)) - cmd.Parameters.Add(":"+name, "1"); + cmd.Parameters.AddWithValue(":"+name, "1"); else - cmd.Parameters.Add(":"+name, "0"); + cmd.Parameters.AddWithValue(":"+name, "0"); } else { - cmd.Parameters.Add(":"+name, m_FieldMap[name].GetValue(es).ToString()); + cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString()); } } @@ -236,7 +236,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = "select bannedUUID from estateban where EstateID = :EstateID"; - cmd.Parameters.Add(":EstateID", es.EstateID); + cmd.Parameters.AddWithValue(":EstateID", es.EstateID); IDataReader r = cmd.ExecuteReader(); @@ -260,7 +260,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = "delete from estateban where EstateID = :EstateID"; - cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); cmd.ExecuteNonQuery(); @@ -270,8 +270,8 @@ namespace OpenSim.Data.SQLite foreach (EstateBan b in es.EstateBans) { - cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); - cmd.Parameters.Add(":bannedUUID", b.BannedUserID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); + cmd.Parameters.AddWithValue(":bannedUUID", b.BannedUserID.ToString()); cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); @@ -283,7 +283,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = "delete from "+table+" where EstateID = :EstateID"; - cmd.Parameters.Add(":EstateID", EstateID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString()); cmd.ExecuteNonQuery(); @@ -293,8 +293,8 @@ namespace OpenSim.Data.SQLite foreach (UUID uuid in data) { - cmd.Parameters.Add(":EstateID", EstateID.ToString()); - cmd.Parameters.Add(":uuid", uuid.ToString()); + cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString()); + cmd.Parameters.AddWithValue(":uuid", uuid.ToString()); cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); @@ -308,7 +308,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = "select uuid from "+table+" where EstateID = :EstateID"; - cmd.Parameters.Add(":EstateID", EstateID); + cmd.Parameters.AddWithValue(":EstateID", EstateID); IDataReader r = cmd.ExecuteReader(); @@ -333,7 +333,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = sql; - cmd.Parameters.Add(":EstateID", estateID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); return DoLoad(cmd, UUID.Zero, false); } @@ -347,7 +347,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = sql; - cmd.Parameters.Add(":EstateName", search); + cmd.Parameters.AddWithValue(":EstateName", search); IDataReader r = cmd.ExecuteReader(); @@ -365,8 +365,8 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; - cmd.Parameters.Add(":RegionID", regionID.ToString()); - cmd.Parameters.Add(":EstateID", estateID.ToString()); + cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); if (cmd.ExecuteNonQuery() == 0) return false; diff --git a/OpenSim/Data/SQLiteNG/SQLiteFramework.cs b/OpenSim/Data/SQLiteNG/SQLiteFramework.cs index 20b5085..cf114d1 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteFramework.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteFramework.cs @@ -31,7 +31,7 @@ using System.Collections.Generic; using System.Data; using OpenMetaverse; using OpenSim.Framework; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; namespace OpenSim.Data.SQLite { @@ -55,11 +55,14 @@ namespace OpenSim.Data.SQLite { lock (connection) { +/* SqliteConnection newConnection = (SqliteConnection)((ICloneable)connection).Clone(); newConnection.Open(); cmd.Connection = newConnection; +*/ + cmd.Connection = connection; //Console.WriteLine("XXX " + cmd.CommandText); return cmd.ExecuteNonQuery(); @@ -70,11 +73,12 @@ namespace OpenSim.Data.SQLite { lock (connection) { - SqliteConnection newConnection = - (SqliteConnection)((ICloneable)connection).Clone(); - newConnection.Open(); + //SqliteConnection newConnection = + // (SqliteConnection)((ICloneable)connection).Clone(); + //newConnection.Open(); - cmd.Connection = newConnection; + //cmd.Connection = newConnection; + cmd.Connection = connection; //Console.WriteLine("XXX " + cmd.CommandText); return cmd.ExecuteReader(); diff --git a/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs b/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs index 0b12182..b06853c 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs @@ -31,7 +31,7 @@ using System.Collections.Generic; using System.Data; using OpenMetaverse; using OpenSim.Framework; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; namespace OpenSim.Data.SQLite { @@ -47,7 +47,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = new SqliteCommand(); cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = :PrincipalID", m_Realm); - cmd.Parameters.Add(":PrincipalID", userID.ToString()); + cmd.Parameters.AddWithValue(":PrincipalID", userID.ToString()); return DoQuery(cmd); @@ -58,8 +58,8 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = new SqliteCommand(); cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm); - cmd.Parameters.Add(":PrincipalID", principalID.ToString()); - cmd.Parameters.Add(":Friend", friend); + cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString()); + cmd.Parameters.AddWithValue(":Friend", friend); ExecuteNonQuery(cmd, cmd.Connection); diff --git a/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs index b39bb19..3c70aef 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs @@ -30,7 +30,7 @@ using System.Collections.Generic; using System.Data; using System.Reflection; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -59,19 +59,21 @@ namespace OpenSim.Data.SQLite if (!m_initialized) { m_Connection = new SqliteConnection(connectionString); + Console.WriteLine(string.Format("OPENING CONNECTION FOR {0} USING {1}", storeName, connectionString)); m_Connection.Open(); if (storeName != String.Empty) { Assembly assem = GetType().Assembly; - SqliteConnection newConnection = - (SqliteConnection)((ICloneable)m_Connection).Clone(); - newConnection.Open(); + //SqliteConnection newConnection = + // (SqliteConnection)((ICloneable)m_Connection).Clone(); + //newConnection.Open(); - Migration m = new Migration(newConnection, assem, storeName); + //Migration m = new Migration(newConnection, assem, storeName); + Migration m = new Migration(m_Connection, assem, storeName); m.Update(); - newConnection.Close(); - newConnection.Dispose(); + //newConnection.Close(); + //newConnection.Dispose(); } m_initialized = true; @@ -197,7 +199,7 @@ namespace OpenSim.Data.SQLite result.Add(row); } - CloseCommand(cmd); + //CloseCommand(cmd); return result.ToArray(); } diff --git a/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs b/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs index a5e0517..ece2495 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs @@ -30,7 +30,7 @@ using System.Collections.Generic; using System.Data; using System.Reflection; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; @@ -98,11 +98,13 @@ namespace OpenSim.Data.SQLite ds.Tables.Add(createInventoryFoldersTable()); invFoldersDa.Fill(ds.Tables["inventoryfolders"]); setupFoldersCommands(invFoldersDa, conn); + CreateDataSetMapping(invFoldersDa, "inventoryfolders"); m_log.Info("[INVENTORY DB]: Populated Inventory Folders Definitions"); ds.Tables.Add(createInventoryItemsTable()); invItemsDa.Fill(ds.Tables["inventoryitems"]); setupItemsCommands(invItemsDa, conn); + CreateDataSetMapping(invItemsDa, "inventoryitems"); m_log.Info("[INVENTORY DB]: Populated Inventory Items Definitions"); ds.AcceptChanges(); @@ -728,6 +730,15 @@ namespace OpenSim.Data.SQLite * **********************************************************************/ + protected void CreateDataSetMapping(IDataAdapter da, string tableName) + { + ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName); + foreach (DataColumn col in ds.Tables[tableName].Columns) + { + dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName); + } + } + /// /// Create the "inventoryitems" table /// diff --git a/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs b/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs index d2ba9ae..bad8adc 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs @@ -32,7 +32,7 @@ using System.Drawing; using System.IO; using System.Reflection; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -87,119 +87,139 @@ namespace OpenSim.Data.SQLite /// the connection string public void Initialise(string connectionString) { - m_connectionString = connectionString; + try + { + m_connectionString = connectionString; - ds = new DataSet(); + ds = new DataSet("Region"); - m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); - m_conn = new SqliteConnection(m_connectionString); - m_conn.Open(); + m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); + m_conn = new SqliteConnection(m_connectionString); + m_conn.Open(); + SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); + //SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); + //primDa = new SqliteDataAdapter(primSelectCmd); + primDa = new SqliteDataAdapter(primSelect, m_connectionString); + // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); + shapeDa = new SqliteDataAdapter(shapeSelectCmd); + // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); - SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); - primDa = new SqliteDataAdapter(primSelectCmd); - // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); + itemsDa = new SqliteDataAdapter(itemsSelectCmd); - SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); - shapeDa = new SqliteDataAdapter(shapeSelectCmd); - // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); + terrainDa = new SqliteDataAdapter(terrainSelectCmd); - SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); - itemsDa = new SqliteDataAdapter(itemsSelectCmd); + SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); + landDa = new SqliteDataAdapter(landSelectCmd); - SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); - terrainDa = new SqliteDataAdapter(terrainSelectCmd); + SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); + landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); - SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); - landDa = new SqliteDataAdapter(landSelectCmd); + SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); + regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); + // This actually does the roll forward assembly stuff + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_conn, assem, "RegionStore"); + m.Update(); - SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); - landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); + lock (ds) + { + //ds.Tables.Add(createPrimTable()); + //setupPrimCommands(primDa, m_conn); + //primDa.Fill(ds.Tables["prims"]); + primDa.Fill(ds, "prims"); - SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); - regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); - // This actually does the roll forward assembly stuff - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_conn, assem, "RegionStore"); - m.Update(); + ds.Tables.Add(createShapeTable()); + setupShapeCommands(shapeDa, m_conn); - lock (ds) - { - ds.Tables.Add(createPrimTable()); - setupPrimCommands(primDa, m_conn); - primDa.Fill(ds.Tables["prims"]); + ds.Tables.Add(createItemsTable()); + setupItemsCommands(itemsDa, m_conn); + itemsDa.Fill(ds.Tables["primitems"]); - ds.Tables.Add(createShapeTable()); - setupShapeCommands(shapeDa, m_conn); + ds.Tables.Add(createTerrainTable()); + setupTerrainCommands(terrainDa, m_conn); - ds.Tables.Add(createItemsTable()); - setupItemsCommands(itemsDa, m_conn); - itemsDa.Fill(ds.Tables["primitems"]); + ds.Tables.Add(createLandTable()); + setupLandCommands(landDa, m_conn); - ds.Tables.Add(createTerrainTable()); - setupTerrainCommands(terrainDa, m_conn); + ds.Tables.Add(createLandAccessListTable()); + setupLandAccessCommands(landAccessListDa, m_conn); - ds.Tables.Add(createLandTable()); - setupLandCommands(landDa, m_conn); + ds.Tables.Add(createRegionSettingsTable()); + + setupRegionSettingsCommands(regionSettingsDa, m_conn); - ds.Tables.Add(createLandAccessListTable()); - setupLandAccessCommands(landAccessListDa, m_conn); - - ds.Tables.Add(createRegionSettingsTable()); - - setupRegionSettingsCommands(regionSettingsDa, m_conn); + // WORKAROUND: This is a work around for sqlite on + // windows, which gets really unhappy with blob columns + // that have no sample data in them. At some point we + // need to actually find a proper way to handle this. + try + { + shapeDa.Fill(ds.Tables["primshapes"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on primshapes table"); + } - // WORKAROUND: This is a work around for sqlite on - // windows, which gets really unhappy with blob columns - // that have no sample data in them. At some point we - // need to actually find a proper way to handle this. - try - { - shapeDa.Fill(ds.Tables["primshapes"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on primshapes table"); - } + try + { + terrainDa.Fill(ds.Tables["terrain"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on terrain table"); + } - try - { - terrainDa.Fill(ds.Tables["terrain"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on terrain table"); - } + try + { + landDa.Fill(ds.Tables["land"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on land table"); + } - try - { - landDa.Fill(ds.Tables["land"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on land table"); - } + try + { + landAccessListDa.Fill(ds.Tables["landaccesslist"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); + } - try - { - landAccessListDa.Fill(ds.Tables["landaccesslist"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); - } + try + { + regionSettingsDa.Fill(ds.Tables["regionsettings"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); + } - try - { - regionSettingsDa.Fill(ds.Tables["regionsettings"]); + // We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values! + // Not sure exactly why this is - this kind of thing was not necessary before - justincc 20100409 + CreateDataSetMapping(primDa, "prims"); + CreateDataSetMapping(shapeDa, "primshapes"); + CreateDataSetMapping(itemsDa, "primitems"); + CreateDataSetMapping(terrainDa, "terrain"); + CreateDataSetMapping(landDa, "land"); + CreateDataSetMapping(landAccessListDa, "landaccesslist"); + CreateDataSetMapping(regionSettingsDa, "regionsettings"); } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); - } - return; } + catch (Exception e) + { + m_log.Error(e); + Environment.Exit(23); + } + + return; } public void Dispose() @@ -603,7 +623,7 @@ namespace OpenSim.Data.SQLite } } } - rev = (int) row["Revision"]; + rev = Convert.ToInt32(row["Revision"]); } else { @@ -755,6 +775,7 @@ namespace OpenSim.Data.SQLite /// public void Commit() { + m_log.Debug("[SQLITE]: Starting commit"); lock (ds) { primDa.Update(ds, "prims"); @@ -769,18 +790,11 @@ namespace OpenSim.Data.SQLite { regionSettingsDa.Update(ds, "regionsettings"); } - catch (SqliteExecutionException SqlEx) + catch (SqliteException SqlEx) { - if (SqlEx.Message.Contains("logic error")) - { - throw new Exception( - "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", - SqlEx); - } - else - { - throw SqlEx; - } + throw new Exception( + "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", + SqlEx); } ds.AcceptChanges(); } @@ -802,6 +816,15 @@ namespace OpenSim.Data.SQLite * **********************************************************************/ + protected void CreateDataSetMapping(IDataAdapter da, string tableName) + { + ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName); + foreach (DataColumn col in ds.Tables[tableName].Columns) + { + dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName); + } + } + /// /// /// @@ -1964,6 +1987,7 @@ namespace OpenSim.Data.SQLite sql += ") values (:"; sql += String.Join(", :", cols); sql += ")"; + m_log.DebugFormat("[SQLITE]: Created insert command {0}", sql); SqliteCommand cmd = new SqliteCommand(sql); // this provides the binding for all our parameters, so @@ -2259,6 +2283,36 @@ namespace OpenSim.Data.SQLite return DbType.String; } } + + static void PrintDataSet(DataSet ds) + { + // Print out any name and extended properties. + Console.WriteLine("DataSet is named: {0}", ds.DataSetName); + foreach (System.Collections.DictionaryEntry de in ds.ExtendedProperties) + { + Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value); + } + Console.WriteLine(); + foreach (DataTable dt in ds.Tables) + { + Console.WriteLine("=> {0} Table:", dt.TableName); + // Print out the column names. + for (int curCol = 0; curCol < dt.Columns.Count; curCol++) + { + Console.Write(dt.Columns[curCol].ColumnName + "\t"); + } + Console.WriteLine("\n----------------------------------"); + // Print the DataTable. + for (int curRow = 0; curRow < dt.Rows.Count; curRow++) + { + for (int curCol = 0; curCol < dt.Columns.Count; curCol++) + { + Console.Write(dt.Rows[curRow][curCol].ToString() + "\t"); + } + Console.WriteLine(); + } + } + } } } diff --git a/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs b/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs index 67cf716..893f105 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs @@ -31,7 +31,7 @@ using System.Collections.Generic; using System.Data; using OpenMetaverse; using OpenSim.Framework; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; namespace OpenSim.Data.SQLite { @@ -66,7 +66,7 @@ namespace OpenSim.Data.SQLite if (words.Length == 1) { - cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", + cmd.CommandText = String.Format("select * from {0} where ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", m_Realm, scopeID.ToString(), words[0]); } else diff --git a/OpenSim/Data/SQLiteNG/SQLiteUtils.cs b/OpenSim/Data/SQLiteNG/SQLiteUtils.cs index 4a835ce..07c6b69 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteUtils.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteUtils.cs @@ -27,7 +27,7 @@ using System; using System.Data; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; namespace OpenSim.Data.SQLite { diff --git a/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs b/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs index a66e0c6..be1d041 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs @@ -29,7 +29,7 @@ using System; using System.Data; using System.Reflection; using System.Collections.Generic; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using log4net; using OpenMetaverse; using OpenSim.Framework; @@ -147,7 +147,7 @@ namespace OpenSim.Data.SQLite } reader.Close(); - CloseCommand(cmd); + //CloseCommand(cmd); return perms; } diff --git a/OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs b/OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs deleted file mode 100644 index 0c2f5df..0000000 --- a/OpenSim/Data/SQLiteNG/Tests/SQLiteAssetTest.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.IO; -using NUnit.Framework; -using OpenSim.Data.Tests; -using OpenSim.Tests.Common; - -namespace OpenSim.Data.SQLite.Tests -{ - [TestFixture, DatabaseTest] - public class SQLiteAssetTest : BasicAssetTest - { - public string file; - public string connect; - - [TestFixtureSetUp] - public void Init() - { - // SQLite doesn't work on power or z linux - if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd")) - { - Assert.Ignore(); - } - - SuperInit(); - file = Path.GetTempFileName() + ".db"; - connect = "URI=file:" + file + ",version=3"; - db = new SQLiteAssetData(); - db.Initialise(connect); - } - - [TestFixtureTearDown] - public void Cleanup() - { - db.Dispose(); - File.Delete(file); - } - } -} diff --git a/OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs b/OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs deleted file mode 100644 index 30f6641..0000000 --- a/OpenSim/Data/SQLiteNG/Tests/SQLiteEstateTest.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.IO; -using NUnit.Framework; -using OpenSim.Data.Tests; -using OpenSim.Tests.Common; - -namespace OpenSim.Data.SQLite.Tests -{ - [TestFixture, DatabaseTest] - public class SQLiteEstateTest : BasicEstateTest - { - public string file = "regiontest.db"; - public string connect; - - [TestFixtureSetUp] - public void Init() - { - // SQLite doesn't work on power or z linux - if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd")) - { - Assert.Ignore(); - } - - SuperInit(); - file = Path.GetTempFileName() + ".db"; - connect = "URI=file:" + file + ",version=3"; - db = new SQLiteEstateStore(); - db.Initialise(connect); - regionDb = new SQLiteRegionData(); - regionDb.Initialise(connect); - } - - [TestFixtureTearDown] - public void Cleanup() - { - regionDb.Dispose(); - } - } -} diff --git a/OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs b/OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs deleted file mode 100644 index 98458a3..0000000 --- a/OpenSim/Data/SQLiteNG/Tests/SQLiteInventoryTest.cs +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.IO; -using NUnit.Framework; -using OpenSim.Data.Tests; -using OpenSim.Tests.Common; - -namespace OpenSim.Data.SQLite.Tests -{ - [TestFixture, DatabaseTest] - public class SQLiteInventoryTest : BasicInventoryTest - { - public string file; - public string connect; - - [TestFixtureSetUp] - public void Init() - { - // SQLite doesn't work on power or z linux - if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd")) - { - Assert.Ignore(); - } - - SuperInit(); - - file = Path.GetTempFileName() + ".db"; - connect = "URI=file:" + file + ",version=3"; - - db = new SQLiteInventoryStore(); - db.Initialise(connect); - } - - [TestFixtureTearDown] - public void Cleanup() - { - db.Dispose(); - File.Delete(file); - } - } -} diff --git a/OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs b/OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs deleted file mode 100644 index abb97cf..0000000 --- a/OpenSim/Data/SQLiteNG/Tests/SQLiteRegionTest.cs +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.IO; -using NUnit.Framework; -using OpenSim.Data.Tests; -using OpenSim.Tests.Common; - -namespace OpenSim.Data.SQLite.Tests -{ - [TestFixture, DatabaseTest] - public class SQLiteRegionTest : BasicRegionTest - { - public string file = "regiontest.db"; - public string connect; - - [TestFixtureSetUp] - public void Init() - { - // SQLite doesn't work on power or z linux - if (Directory.Exists("/proc/ppc64") || Directory.Exists("/proc/dasd")) - { - Assert.Ignore(); - } - - SuperInit(); - file = Path.GetTempFileName() + ".db"; - connect = "URI=file:" + file + ",version=3"; - db = new SQLiteRegionData(); - db.Initialise(connect); - } - - [TestFixtureTearDown] - public void Cleanup() - { - db.Dispose(); - File.Delete(file); - } - } -} diff --git a/prebuild.xml b/prebuild.xml index 9db30ff..7c7e3c7 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2526,7 +2526,6 @@ - @@ -2534,7 +2533,7 @@ - + -- cgit v1.1 From 362007e5d352d3eafcc260a2270fa8833d2bbf05 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Apr 2010 19:14:43 +0100 Subject: minor: correct the assembly information for SQLiteNG --- OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs index d45ab50..4aeb67b 100644 --- a/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs +++ b/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs @@ -32,11 +32,11 @@ using System.Runtime.InteropServices; // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly : AssemblyTitle("OpenSim.Data.SQLite")] +[assembly : AssemblyTitle("OpenSim.Data.SQLiteNG")] [assembly : AssemblyDescription("")] [assembly : AssemblyConfiguration("")] [assembly : AssemblyCompany("http://opensimulator.org")] -[assembly : AssemblyProduct("OpenSim.Data.SQLite")] +[assembly : AssemblyProduct("OpenSim.Data.SQLiteNG")] [assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] [assembly : AssemblyTrademark("")] [assembly : AssemblyCulture("")] -- cgit v1.1 From a90054aa16c8e968a6866cf850d16fde0b20957d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey Date: Fri, 23 Apr 2010 19:40:15 +0100 Subject: put SQLiteNG classes in their own namespace to avoid confusion --- OpenSim/Data/SQLiteNG/SQLiteAssetData.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteEstateData.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteFramework.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteRegionData.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteUtils.cs | 2 +- OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs b/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs index 636bf86..9b34a21 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs @@ -34,7 +34,7 @@ using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { /// /// An asset storage interface for the SQLite database system diff --git a/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs index 086ac0a..4a5dc2e 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs @@ -33,7 +33,7 @@ using OpenMetaverse; using OpenSim.Framework; using Mono.Data.Sqlite; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { public class SQLiteAuthenticationData : SQLiteFramework, IAuthenticationData { diff --git a/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs b/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs index c093884..d0fd49c 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs @@ -35,7 +35,7 @@ using OpenMetaverse; using OpenSim.Framework; using Mono.Data.Sqlite; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { /// /// A SQLite Interface for Avatar Data diff --git a/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs b/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs index 9dd4a2e..2e2d717 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs @@ -35,7 +35,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { public class SQLiteEstateStore : IEstateDataStore { diff --git a/OpenSim/Data/SQLiteNG/SQLiteFramework.cs b/OpenSim/Data/SQLiteNG/SQLiteFramework.cs index cf114d1..f0ddc59 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteFramework.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteFramework.cs @@ -33,7 +33,7 @@ using OpenMetaverse; using OpenSim.Framework; using Mono.Data.Sqlite; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { /// /// A database interface class to a user profile storage system diff --git a/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs b/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs index b06853c..702a1d8 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs @@ -33,7 +33,7 @@ using OpenMetaverse; using OpenSim.Framework; using Mono.Data.Sqlite; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { public class SQLiteFriendsData : SQLiteGenericTableHandler, IFriendsData { diff --git a/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs index 3c70aef..632c5bf 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs @@ -35,7 +35,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { public class SQLiteGenericTableHandler : SQLiteFramework where T: class, new() { diff --git a/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs b/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs index ece2495..9207ca3 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs @@ -34,7 +34,7 @@ using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { /// /// An Inventory Interface to the SQLite database diff --git a/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs b/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs index bad8adc..ee454db 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs @@ -38,7 +38,7 @@ using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { /// /// A RegionData Interface to the SQLite database diff --git a/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs b/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs index 893f105..f77159c 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs @@ -33,7 +33,7 @@ using OpenMetaverse; using OpenSim.Framework; using Mono.Data.Sqlite; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { public class SQLiteUserAccountData : SQLiteGenericTableHandler, IUserAccountData { diff --git a/OpenSim/Data/SQLiteNG/SQLiteUtils.cs b/OpenSim/Data/SQLiteNG/SQLiteUtils.cs index 07c6b69..82a2e37 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteUtils.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteUtils.cs @@ -29,7 +29,7 @@ using System; using System.Data; using Mono.Data.Sqlite; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { /// /// A base class for methods needed by all SQLite database classes diff --git a/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs b/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs index be1d041..a0c17f8 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs @@ -34,7 +34,7 @@ using log4net; using OpenMetaverse; using OpenSim.Framework; -namespace OpenSim.Data.SQLite +namespace OpenSim.Data.SQLiteNG { /// /// A MySQL Interface for the Asset Server -- cgit v1.1 From b46380e373d9757174738ea3bb7dc2be6dbcb68b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Apr 2010 20:08:24 +0100 Subject: dispose of the DbCommand used to execute migrations after we've finished with it rather than within the loop disposing of it within the loop causes Mono.Data.Sqlite.dll to get upset, and it's the wrong behaviour anyway --- OpenSim/Data/Migration.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Data/Migration.cs b/OpenSim/Data/Migration.cs index e51dc22..2878fd0 100644 --- a/OpenSim/Data/Migration.cs +++ b/OpenSim/Data/Migration.cs @@ -149,8 +149,9 @@ namespace OpenSim.Data UpdateVersion(_type, newversion); } version = newversion; - cmd.Dispose(); } + + cmd.Dispose(); } // private int MaxVersion() -- cgit v1.1 From 705b675d281aa9e93e2ad9929783822a4fe234fc Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 23 Apr 2010 20:56:24 +0100 Subject: get region prim saving working properly in SQLiteNG it wasn't working because of debug work that I'd forgotton to take out --- OpenSim/Data/SQLiteNG/SQLiteRegionData.cs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs b/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs index ee454db..289d626 100644 --- a/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs @@ -98,10 +98,7 @@ namespace OpenSim.Data.SQLiteNG m_conn.Open(); SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); - //SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); - //primDa = new SqliteDataAdapter(primSelectCmd); - primDa = new SqliteDataAdapter(primSelect, m_connectionString); - // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + primDa = new SqliteDataAdapter(primSelectCmd); SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); shapeDa = new SqliteDataAdapter(shapeSelectCmd); @@ -128,17 +125,14 @@ namespace OpenSim.Data.SQLiteNG lock (ds) { - //ds.Tables.Add(createPrimTable()); - //setupPrimCommands(primDa, m_conn); - //primDa.Fill(ds.Tables["prims"]); - primDa.Fill(ds, "prims"); + ds.Tables.Add(createPrimTable()); + setupPrimCommands(primDa, m_conn); ds.Tables.Add(createShapeTable()); setupShapeCommands(shapeDa, m_conn); ds.Tables.Add(createItemsTable()); setupItemsCommands(itemsDa, m_conn); - itemsDa.Fill(ds.Tables["primitems"]); ds.Tables.Add(createTerrainTable()); setupTerrainCommands(terrainDa, m_conn); @@ -150,7 +144,6 @@ namespace OpenSim.Data.SQLiteNG setupLandAccessCommands(landAccessListDa, m_conn); ds.Tables.Add(createRegionSettingsTable()); - setupRegionSettingsCommands(regionSettingsDa, m_conn); // WORKAROUND: This is a work around for sqlite on @@ -159,6 +152,15 @@ namespace OpenSim.Data.SQLiteNG // need to actually find a proper way to handle this. try { + primDa.Fill(ds.Tables["prims"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on prims table"); + } + + try + { shapeDa.Fill(ds.Tables["primshapes"]); } catch (Exception) @@ -204,6 +206,7 @@ namespace OpenSim.Data.SQLiteNG // We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values! // Not sure exactly why this is - this kind of thing was not necessary before - justincc 20100409 + // Possibly because we manually set up our own DataTables before connecting to the database CreateDataSetMapping(primDa, "prims"); CreateDataSetMapping(shapeDa, "primshapes"); CreateDataSetMapping(itemsDa, "primitems"); -- cgit v1.1 From 955db6e4bee8973def97340018316825fb46abb3 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 30 Apr 2010 19:12:47 +0100 Subject: add Mono.Data.Sqlite.dll --- bin/Mono.Data.Sqlite.dll | Bin 0 -> 169984 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 bin/Mono.Data.Sqlite.dll diff --git a/bin/Mono.Data.Sqlite.dll b/bin/Mono.Data.Sqlite.dll new file mode 100644 index 0000000..4f69e0d Binary files /dev/null and b/bin/Mono.Data.Sqlite.dll differ -- cgit v1.1 From 56fe4c24b8c67ec3b6a5a897c35ab19507bd1077 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 30 Apr 2010 17:45:00 +0100 Subject: rename SQLiteNG to SQLite and SQLite to SQLiteLegacy this seems the least evil way forward since mono 2.6 and later will see increasing usage, and this only works with what was SQLiteNG MAC USERS WILL NEED TO CHANGE REFERENCES TO "OpenSim.Data.SQLite.dll" to "OpenSim.Data.SQLiteLegacy.dll" in OpenSim.ini and config-include/StandaloneCommon.ini (if using standalone) See the OpenSim.ini.example and StandaloneCommon.ini.example files for more details This commit also temporarily changes unsigned ParentEstateID values in the OpenSim.Data.Tests to signed temporarily, since the new plugin enforces creation of signed fields in the database (which is what the SQL actually specifies). And change data columns in sqlite is a pita. --- OpenSim/Data/SQLite/SQLiteAssetData.cs | 4 +- OpenSim/Data/SQLite/SQLiteAuthenticationData.cs | 257 +++ OpenSim/Data/SQLite/SQLiteEstateData.cs | 101 +- OpenSim/Data/SQLite/SQLiteFramework.cs | 29 +- OpenSim/Data/SQLite/SQLiteFriendsData.cs | 70 + OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs | 26 +- OpenSim/Data/SQLite/SQLiteInventoryStore.cs | 25 +- OpenSim/Data/SQLite/SQLiteRegionData.cs | 259 ++- OpenSim/Data/SQLite/SQLiteUserAccountData.cs | 81 + OpenSim/Data/SQLite/SQLiteUtils.cs | 2 +- OpenSim/Data/SQLite/SQLiteXInventoryData.cs | 6 +- .../Data/SQLiteLegacy/Properties/AssemblyInfo.cs | 65 + .../Data/SQLiteLegacy/Resources/001_AssetStore.sql | 12 + .../Data/SQLiteLegacy/Resources/001_AuthStore.sql | 18 + OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql | 9 + .../SQLiteLegacy/Resources/001_FriendsStore.sql | 10 + .../SQLiteLegacy/Resources/001_InventoryStore.sql | 32 + .../SQLiteLegacy/Resources/001_RegionStore.sql | 144 ++ .../SQLiteLegacy/Resources/001_UserAccount.sql | 17 + .../Data/SQLiteLegacy/Resources/001_UserStore.sql | 39 + .../Data/SQLiteLegacy/Resources/002_AssetStore.sql | 10 + .../Data/SQLiteLegacy/Resources/002_AuthStore.sql | 5 + .../SQLiteLegacy/Resources/002_FriendsStore.sql | 5 + .../SQLiteLegacy/Resources/002_InventoryStore.sql | 8 + .../SQLiteLegacy/Resources/002_RegionStore.sql | 10 + .../SQLiteLegacy/Resources/002_UserAccount.sql | 5 + .../Data/SQLiteLegacy/Resources/002_UserStore.sql | 5 + .../Data/SQLiteLegacy/Resources/003_AssetStore.sql | 1 + .../SQLiteLegacy/Resources/003_InventoryStore.sql | 5 + .../SQLiteLegacy/Resources/003_RegionStore.sql | 5 + .../Data/SQLiteLegacy/Resources/003_UserStore.sql | 6 + .../Data/SQLiteLegacy/Resources/004_AssetStore.sql | 7 + .../SQLiteLegacy/Resources/004_InventoryStore.sql | 36 + .../SQLiteLegacy/Resources/004_RegionStore.sql | 38 + .../Data/SQLiteLegacy/Resources/004_UserStore.sql | 6 + .../SQLiteLegacy/Resources/005_RegionStore.sql | 5 + .../Data/SQLiteLegacy/Resources/005_UserStore.sql | 5 + .../SQLiteLegacy/Resources/006_RegionStore.sql | 102 + .../Data/SQLiteLegacy/Resources/006_UserStore.sql | 20 + .../SQLiteLegacy/Resources/007_RegionStore.sql | 8 + .../Data/SQLiteLegacy/Resources/007_UserStore.sql | 7 + .../SQLiteLegacy/Resources/008_RegionStore.sql | 6 + .../Data/SQLiteLegacy/Resources/008_UserStore.sql | 5 + .../SQLiteLegacy/Resources/009_RegionStore.sql | 8 + .../Data/SQLiteLegacy/Resources/009_UserStore.sql | 11 + .../SQLiteLegacy/Resources/010_RegionStore.sql | 5 + .../Data/SQLiteLegacy/Resources/010_UserStore.sql | 37 + .../SQLiteLegacy/Resources/011_RegionStore.sql | 28 + .../SQLiteLegacy/Resources/012_RegionStore.sql | 5 + .../SQLiteLegacy/Resources/013_RegionStore.sql | 6 + .../SQLiteLegacy/Resources/014_RegionStore.sql | 8 + .../SQLiteLegacy/Resources/015_RegionStore.sql | 6 + .../SQLiteLegacy/Resources/016_RegionStore.sql | 5 + .../SQLiteLegacy/Resources/017_RegionStore.sql | 8 + .../SQLiteLegacy/Resources/018_RegionStore.sql | 79 + .../Resources/OpenSim.Data.SQLite.addin.xml | 20 + OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs | 343 +++ .../Data/SQLiteLegacy/SQLiteAuthenticationData.cs | 262 +++ OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs | 74 + OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs | 387 ++++ OpenSim/Data/SQLiteLegacy/SQLiteFramework.cs | 91 + OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs | 70 + .../Data/SQLiteLegacy/SQLiteGenericTableHandler.cs | 268 +++ OpenSim/Data/SQLiteLegacy/SQLiteInventoryStore.cs | 898 ++++++++ OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs | 2264 +++++++++++++++++++ OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs | 81 + OpenSim/Data/SQLiteLegacy/SQLiteUtils.cs | 307 +++ OpenSim/Data/SQLiteLegacy/SQLiteXInventoryData.cs | 155 ++ OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs | 65 - OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql | 12 - OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql | 18 - OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql | 9 - .../Data/SQLiteNG/Resources/001_FriendsStore.sql | 10 - .../Data/SQLiteNG/Resources/001_InventoryStore.sql | 32 - .../Data/SQLiteNG/Resources/001_RegionStore.sql | 144 -- .../Data/SQLiteNG/Resources/001_UserAccount.sql | 17 - OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql | 39 - OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql | 10 - OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql | 5 - .../Data/SQLiteNG/Resources/002_FriendsStore.sql | 5 - .../Data/SQLiteNG/Resources/002_InventoryStore.sql | 8 - .../Data/SQLiteNG/Resources/002_RegionStore.sql | 10 - .../Data/SQLiteNG/Resources/002_UserAccount.sql | 5 - OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql | 5 - OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql | 1 - .../Data/SQLiteNG/Resources/003_InventoryStore.sql | 5 - .../Data/SQLiteNG/Resources/003_RegionStore.sql | 5 - OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql | 6 - OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql | 7 - .../Data/SQLiteNG/Resources/004_InventoryStore.sql | 36 - .../Data/SQLiteNG/Resources/004_RegionStore.sql | 38 - OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql | 6 - .../Data/SQLiteNG/Resources/005_RegionStore.sql | 5 - OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql | 5 - .../Data/SQLiteNG/Resources/006_RegionStore.sql | 102 - OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql | 20 - .../Data/SQLiteNG/Resources/007_RegionStore.sql | 8 - OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql | 7 - .../Data/SQLiteNG/Resources/008_RegionStore.sql | 6 - OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql | 5 - .../Data/SQLiteNG/Resources/009_RegionStore.sql | 8 - OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql | 11 - .../Data/SQLiteNG/Resources/010_RegionStore.sql | 5 - OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql | 37 - .../Data/SQLiteNG/Resources/011_RegionStore.sql | 28 - .../Data/SQLiteNG/Resources/012_RegionStore.sql | 5 - .../Data/SQLiteNG/Resources/013_RegionStore.sql | 6 - .../Data/SQLiteNG/Resources/014_RegionStore.sql | 8 - .../Data/SQLiteNG/Resources/015_RegionStore.sql | 6 - .../Data/SQLiteNG/Resources/016_RegionStore.sql | 5 - .../Data/SQLiteNG/Resources/017_RegionStore.sql | 8 - .../Data/SQLiteNG/Resources/018_RegionStore.sql | 79 - .../Resources/OpenSim.Data.SQLite.addin.xml | 20 - OpenSim/Data/SQLiteNG/SQLiteAssetData.cs | 343 --- OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs | 257 --- OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs | 74 - OpenSim/Data/SQLiteNG/SQLiteEstateData.cs | 387 ---- OpenSim/Data/SQLiteNG/SQLiteFramework.cs | 95 - OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs | 70 - OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs | 270 --- OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs | 909 -------- OpenSim/Data/SQLiteNG/SQLiteRegionData.cs | 2321 -------------------- OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs | 81 - OpenSim/Data/SQLiteNG/SQLiteUtils.cs | 307 --- OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs | 155 -- OpenSim/Data/Tests/DataTestUtil.cs | 3 +- bin/OpenSim.ini.example | 10 +- bin/config-include/StandaloneCommon.ini.example | 12 +- prebuild.xml | 4 +- 129 files changed, 6836 insertions(+), 6286 deletions(-) create mode 100644 OpenSim/Data/SQLite/SQLiteAuthenticationData.cs create mode 100644 OpenSim/Data/SQLite/SQLiteFriendsData.cs create mode 100644 OpenSim/Data/SQLite/SQLiteUserAccountData.cs create mode 100644 OpenSim/Data/SQLiteLegacy/Properties/AssemblyInfo.cs create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_AssetStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_AuthStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_FriendsStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_InventoryStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_UserAccount.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_AssetStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_AuthStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_FriendsStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_InventoryStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_UserAccount.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/003_AssetStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/003_InventoryStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/003_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/003_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/004_AssetStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/004_InventoryStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/004_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/004_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/005_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/005_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/006_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/006_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/007_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/007_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/008_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/008_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/009_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/009_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/010_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/010_UserStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/011_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/012_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/013_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/014_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/015_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/016_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/017_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/018_RegionStore.sql create mode 100644 OpenSim/Data/SQLiteLegacy/Resources/OpenSim.Data.SQLite.addin.xml create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteAuthenticationData.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteFramework.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteGenericTableHandler.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteInventoryStore.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteUtils.cs create mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteXInventoryData.cs delete mode 100644 OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs delete mode 100644 OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/001_FriendsStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/001_InventoryStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/001_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/001_UserAccount.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/002_FriendsStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/002_InventoryStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/002_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/002_UserAccount.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/003_InventoryStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/003_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/004_InventoryStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/004_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/005_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/006_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/007_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/008_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/009_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/010_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/011_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/012_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/013_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/014_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/015_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/016_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/017_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/018_RegionStore.sql delete mode 100644 OpenSim/Data/SQLiteNG/Resources/OpenSim.Data.SQLite.addin.xml delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteAssetData.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteEstateData.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteFramework.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteRegionData.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteUtils.cs delete mode 100644 OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs index c52f60b..373c903 100644 --- a/OpenSim/Data/SQLite/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs @@ -30,7 +30,7 @@ using System.Data; using System.Reflection; using System.Collections.Generic; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; @@ -339,4 +339,4 @@ namespace OpenSim.Data.SQLite #endregion } -} \ No newline at end of file +} diff --git a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs new file mode 100644 index 0000000..086ac0a --- /dev/null +++ b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs @@ -0,0 +1,257 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.Sqlite; + +namespace OpenSim.Data.SQLite +{ + public class SQLiteAuthenticationData : SQLiteFramework, IAuthenticationData + { + private string m_Realm; + private List m_ColumnNames; + private int m_LastExpire; + private string m_connectionString; + + protected static SqliteConnection m_Connection; + private static bool m_initialized = false; + + public SQLiteAuthenticationData(string connectionString, string realm) + : base(connectionString) + { + m_Realm = realm; + m_connectionString = connectionString; + + if (!m_initialized) + { + m_Connection = new SqliteConnection(connectionString); + m_Connection.Open(); + + Migration m = new Migration(m_Connection, GetType().Assembly, "AuthStore"); + m.Update(); + + m_initialized = true; + } + } + + public AuthenticationData Get(UUID principalID) + { + AuthenticationData ret = new AuthenticationData(); + ret.Data = new Dictionary(); + + SqliteCommand cmd = new SqliteCommand("select * from `" + m_Realm + "` where UUID = :PrincipalID"); + cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); + + IDataReader result = ExecuteReader(cmd, m_Connection); + + try + { + if (result.Read()) + { + ret.PrincipalID = principalID; + + if (m_ColumnNames == null) + { + m_ColumnNames = new List(); + + DataTable schemaTable = result.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + m_ColumnNames.Add(row["ColumnName"].ToString()); + } + + foreach (string s in m_ColumnNames) + { + if (s == "UUID") + continue; + + ret.Data[s] = result[s].ToString(); + } + + return ret; + } + else + { + return null; + } + } + catch + { + } + finally + { + //CloseCommand(cmd); + } + + return null; + } + + public bool Store(AuthenticationData data) + { + if (data.Data.ContainsKey("UUID")) + data.Data.Remove("UUID"); + + string[] fields = new List(data.Data.Keys).ToArray(); + string[] values = new string[data.Data.Count]; + int i = 0; + foreach (object o in data.Data.Values) + values[i++] = o.ToString(); + + SqliteCommand cmd = new SqliteCommand(); + + if (Get(data.PrincipalID) != null) + { + + + string update = "update `" + m_Realm + "` set "; + bool first = true; + foreach (string field in fields) + { + if (!first) + update += ", "; + update += "`" + field + "` = :" + field; + cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); + + first = false; + } + + update += " where UUID = :UUID"; + cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); + + cmd.CommandText = update; + try + { + if (ExecuteNonQuery(cmd, m_Connection) < 1) + { + //CloseCommand(cmd); + return false; + } + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + //CloseCommand(cmd); + return false; + } + } + + else + { + string insert = "insert into `" + m_Realm + "` (`UUID`, `" + + String.Join("`, `", fields) + + "`) values (:UUID, :" + String.Join(", :", fields) + ")"; + + cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); + foreach (string field in fields) + cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); + + cmd.CommandText = insert; + + try + { + if (ExecuteNonQuery(cmd, m_Connection) < 1) + { + //CloseCommand(cmd); + return false; + } + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + //CloseCommand(cmd); + return false; + } + } + + //CloseCommand(cmd); + + return true; + } + + public bool SetDataItem(UUID principalID, string item, string value) + { + SqliteCommand cmd = new SqliteCommand("update `" + m_Realm + + "` set `" + item + "` = " + value + " where UUID = '" + principalID.ToString() + "'"); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; + + return false; + } + + public bool SetToken(UUID principalID, string token, int lifetime) + { + if (System.Environment.TickCount - m_LastExpire > 30000) + DoExpire(); + + SqliteCommand cmd = new SqliteCommand("insert into tokens (UUID, token, validity) values ('" + principalID.ToString() + + "', '" + token + "', datetime('now', 'localtime', '+" + lifetime.ToString() + " minutes'))"); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + { + cmd.Dispose(); + return true; + } + + cmd.Dispose(); + return false; + } + + public bool CheckToken(UUID principalID, string token, int lifetime) + { + if (System.Environment.TickCount - m_LastExpire > 30000) + DoExpire(); + + SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now', 'localtime', '+" + lifetime.ToString() + + " minutes') where UUID = '" + principalID.ToString() + "' and token = '" + token + "' and validity > datetime('now', 'localtime')"); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + { + cmd.Dispose(); + return true; + } + + cmd.Dispose(); + + return false; + } + + private void DoExpire() + { + SqliteCommand cmd = new SqliteCommand("delete from tokens where validity < datetime('now', 'localtime')"); + ExecuteNonQuery(cmd, m_Connection); + + cmd.Dispose(); + + m_LastExpire = System.Environment.TickCount; + } + } +} diff --git a/OpenSim/Data/SQLite/SQLiteEstateData.cs b/OpenSim/Data/SQLite/SQLiteEstateData.cs index 1be99ee..ad4e2a2 100644 --- a/OpenSim/Data/SQLite/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLite/SQLiteEstateData.cs @@ -30,7 +30,7 @@ using System.Collections.Generic; using System.Data; using System.Reflection; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -62,8 +62,8 @@ namespace OpenSim.Data.SQLite Migration m = new Migration(m_connection, assem, "EstateStore"); m.Update(); - m_connection.Close(); - m_connection.Open(); + //m_connection.Close(); + // m_connection.Open(); Type t = typeof(EstateSettings); m_Fields = t.GetFields(BindingFlags.NonPublic | @@ -90,7 +90,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = sql; - cmd.Parameters.Add(":RegionID", regionID.ToString()); + cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); IDataReader r = cmd.ExecuteReader(); @@ -140,13 +140,13 @@ namespace OpenSim.Data.SQLite if (m_FieldMap[name].GetValue(es) is bool) { if ((bool)m_FieldMap[name].GetValue(es)) - cmd.Parameters.Add(":"+name, "1"); + cmd.Parameters.AddWithValue(":"+name, "1"); else - cmd.Parameters.Add(":"+name, "0"); + cmd.Parameters.AddWithValue(":"+name, "0"); } else { - cmd.Parameters.Add(":"+name, m_FieldMap[name].GetValue(es).ToString()); + cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString()); } } @@ -164,8 +164,8 @@ namespace OpenSim.Data.SQLite r.Close(); cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; - cmd.Parameters.Add(":RegionID", regionID.ToString()); - cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); // This will throw on dupe key try @@ -222,13 +222,13 @@ namespace OpenSim.Data.SQLite if (m_FieldMap[name].GetValue(es) is bool) { if ((bool)m_FieldMap[name].GetValue(es)) - cmd.Parameters.Add(":"+name, "1"); + cmd.Parameters.AddWithValue(":"+name, "1"); else - cmd.Parameters.Add(":"+name, "0"); + cmd.Parameters.AddWithValue(":"+name, "0"); } else { - cmd.Parameters.Add(":"+name, m_FieldMap[name].GetValue(es).ToString()); + cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString()); } } @@ -247,7 +247,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = "select bannedUUID from estateban where EstateID = :EstateID"; - cmd.Parameters.Add(":EstateID", es.EstateID); + cmd.Parameters.AddWithValue(":EstateID", es.EstateID); IDataReader r = cmd.ExecuteReader(); @@ -271,7 +271,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = "delete from estateban where EstateID = :EstateID"; - cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); cmd.ExecuteNonQuery(); @@ -281,8 +281,8 @@ namespace OpenSim.Data.SQLite foreach (EstateBan b in es.EstateBans) { - cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); - cmd.Parameters.Add(":bannedUUID", b.BannedUserID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); + cmd.Parameters.AddWithValue(":bannedUUID", b.BannedUserID.ToString()); cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); @@ -294,7 +294,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = "delete from "+table+" where EstateID = :EstateID"; - cmd.Parameters.Add(":EstateID", EstateID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString()); cmd.ExecuteNonQuery(); @@ -304,8 +304,8 @@ namespace OpenSim.Data.SQLite foreach (UUID uuid in data) { - cmd.Parameters.Add(":EstateID", EstateID.ToString()); - cmd.Parameters.Add(":uuid", uuid.ToString()); + cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString()); + cmd.Parameters.AddWithValue(":uuid", uuid.ToString()); cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); @@ -319,7 +319,7 @@ namespace OpenSim.Data.SQLite SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); cmd.CommandText = "select uuid from "+table+" where EstateID = :EstateID"; - cmd.Parameters.Add(":EstateID", EstateID); + cmd.Parameters.AddWithValue(":EstateID", EstateID); IDataReader r = cmd.ExecuteReader(); @@ -336,5 +336,66 @@ namespace OpenSim.Data.SQLite return uuids.ToArray(); } +<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteEstateData.cs +======= + + public EstateSettings LoadEstateSettings(int estateID) + { + string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID :EstateID"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); + + return DoLoad(cmd, UUID.Zero, false); + } + + public List GetEstates(string search) + { + List result = new List(); + + string sql = "select EstateID from estate_settings where estate_settings.EstateName :EstateName"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + cmd.Parameters.AddWithValue(":EstateName", search); + + IDataReader r = cmd.ExecuteReader(); + + while (r.Read()) + { + result.Add(Convert.ToInt32(r["EstateID"])); + } + r.Close(); + + return result; + } + + public bool LinkRegion(UUID regionID, int estateID) + { + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; + cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); + cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); + + if (cmd.ExecuteNonQuery() == 0) + return false; + + return true; + } + + public List GetRegions(int estateID) + { + return new List(); + } + + public bool DeleteEstate(int estateID) + { + return false; + } +>>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteEstateData.cs } } diff --git a/OpenSim/Data/SQLite/SQLiteFramework.cs b/OpenSim/Data/SQLite/SQLiteFramework.cs index 12b2750..79eaab3 100644 --- a/OpenSim/Data/SQLite/SQLiteFramework.cs +++ b/OpenSim/Data/SQLite/SQLiteFramework.cs @@ -31,7 +31,7 @@ using System.Collections.Generic; using System.Data; using OpenMetaverse; using OpenSim.Framework; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; namespace OpenSim.Data.SQLite { @@ -57,7 +57,19 @@ namespace OpenSim.Data.SQLite { lock (m_Connection) { +<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteFramework.cs cmd.Connection = m_Connection; +======= +/* + SqliteConnection newConnection = + (SqliteConnection)((ICloneable)connection).Clone(); + newConnection.Open(); + + cmd.Connection = newConnection; +*/ + cmd.Connection = connection; + //Console.WriteLine("XXX " + cmd.CommandText); +>>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteFramework.cs return cmd.ExecuteNonQuery(); } @@ -65,12 +77,27 @@ namespace OpenSim.Data.SQLite protected IDataReader ExecuteReader(SqliteCommand cmd) { +<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteFramework.cs SqliteConnection newConnection = (SqliteConnection)((ICloneable)m_Connection).Clone(); newConnection.Open(); cmd.Connection = newConnection; return cmd.ExecuteReader(); +======= + lock (connection) + { + //SqliteConnection newConnection = + // (SqliteConnection)((ICloneable)connection).Clone(); + //newConnection.Open(); + + //cmd.Connection = newConnection; + cmd.Connection = connection; + //Console.WriteLine("XXX " + cmd.CommandText); + + return cmd.ExecuteReader(); + } +>>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteFramework.cs } protected void CloseReaderCommand(SqliteCommand cmd) diff --git a/OpenSim/Data/SQLite/SQLiteFriendsData.cs b/OpenSim/Data/SQLite/SQLiteFriendsData.cs new file mode 100644 index 0000000..b06853c --- /dev/null +++ b/OpenSim/Data/SQLite/SQLiteFriendsData.cs @@ -0,0 +1,70 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.Sqlite; + +namespace OpenSim.Data.SQLite +{ + public class SQLiteFriendsData : SQLiteGenericTableHandler, IFriendsData + { + public SQLiteFriendsData(string connectionString, string realm) + : base(connectionString, realm, "FriendsStore") + { + } + + public FriendsData[] GetFriends(UUID userID) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = :PrincipalID", m_Realm); + cmd.Parameters.AddWithValue(":PrincipalID", userID.ToString()); + + return DoQuery(cmd); + + } + + public bool Delete(UUID principalID, string friend) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm); + cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString()); + cmd.Parameters.AddWithValue(":Friend", friend); + + ExecuteNonQuery(cmd, cmd.Connection); + + return true; + } + + } +} diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs index 8e91693..918cb3d 100644 --- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs @@ -30,7 +30,7 @@ using System.Collections.Generic; using System.Data; using System.Reflection; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -54,7 +54,27 @@ namespace OpenSim.Data.SQLite m_Realm = realm; if (storeName != String.Empty) { +<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs Assembly assem = GetType().Assembly; +======= + m_Connection = new SqliteConnection(connectionString); + Console.WriteLine(string.Format("OPENING CONNECTION FOR {0} USING {1}", storeName, connectionString)); + m_Connection.Open(); + + if (storeName != String.Empty) + { + Assembly assem = GetType().Assembly; + //SqliteConnection newConnection = + // (SqliteConnection)((ICloneable)m_Connection).Clone(); + //newConnection.Open(); + + //Migration m = new Migration(newConnection, assem, storeName); + Migration m = new Migration(m_Connection, assem, storeName); + m.Update(); + //newConnection.Close(); + //newConnection.Dispose(); + } +>>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs Migration m = new Migration(m_Connection, assem, storeName); m.Update(); @@ -180,7 +200,11 @@ namespace OpenSim.Data.SQLite result.Add(row); } +<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs CloseReaderCommand(cmd); +======= + //CloseCommand(cmd); +>>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs return result.ToArray(); } diff --git a/OpenSim/Data/SQLite/SQLiteInventoryStore.cs b/OpenSim/Data/SQLite/SQLiteInventoryStore.cs index 64591fd..0149838 100644 --- a/OpenSim/Data/SQLite/SQLiteInventoryStore.cs +++ b/OpenSim/Data/SQLite/SQLiteInventoryStore.cs @@ -30,7 +30,7 @@ using System.Collections.Generic; using System.Data; using System.Reflection; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; @@ -89,6 +89,7 @@ namespace OpenSim.Data.SQLite ds = new DataSet(); +<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteInventoryStore.cs ds.Tables.Add(createInventoryFoldersTable()); invFoldersDa.Fill(ds.Tables["inventoryfolders"]); setupFoldersCommands(invFoldersDa, conn); @@ -98,6 +99,19 @@ namespace OpenSim.Data.SQLite invItemsDa.Fill(ds.Tables["inventoryitems"]); setupItemsCommands(invItemsDa, conn); m_log.Info("[INVENTORY DB]: Populated Inventory Items Definitions"); +======= + ds.Tables.Add(createInventoryFoldersTable()); + invFoldersDa.Fill(ds.Tables["inventoryfolders"]); + setupFoldersCommands(invFoldersDa, conn); + CreateDataSetMapping(invFoldersDa, "inventoryfolders"); + m_log.Info("[INVENTORY DB]: Populated Inventory Folders Definitions"); + + ds.Tables.Add(createInventoryItemsTable()); + invItemsDa.Fill(ds.Tables["inventoryitems"]); + setupItemsCommands(invItemsDa, conn); + CreateDataSetMapping(invItemsDa, "inventoryitems"); + m_log.Info("[INVENTORY DB]: Populated Inventory Items Definitions"); +>>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteInventoryStore.cs ds.AcceptChanges(); } @@ -721,6 +735,15 @@ namespace OpenSim.Data.SQLite * **********************************************************************/ + protected void CreateDataSetMapping(IDataAdapter da, string tableName) + { + ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName); + foreach (DataColumn col in ds.Tables[tableName].Columns) + { + dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName); + } + } + /// /// Create the "inventoryitems" table /// diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs index 5a4ee2a..85368ab 100644 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLite/SQLiteRegionData.cs @@ -32,7 +32,7 @@ using System.Drawing; using System.IO; using System.Reflection; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; @@ -87,119 +87,142 @@ namespace OpenSim.Data.SQLite /// the connection string public void Initialise(string connectionString) { - m_connectionString = connectionString; + try + { + m_connectionString = connectionString; - ds = new DataSet(); + ds = new DataSet("Region"); - m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); - m_conn = new SqliteConnection(m_connectionString); - m_conn.Open(); + m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); + m_conn = new SqliteConnection(m_connectionString); + m_conn.Open(); + SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); + primDa = new SqliteDataAdapter(primSelectCmd); + SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); + shapeDa = new SqliteDataAdapter(shapeSelectCmd); + // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); - SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); - primDa = new SqliteDataAdapter(primSelectCmd); - // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); + itemsDa = new SqliteDataAdapter(itemsSelectCmd); - SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); - shapeDa = new SqliteDataAdapter(shapeSelectCmd); - // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); + terrainDa = new SqliteDataAdapter(terrainSelectCmd); - SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); - itemsDa = new SqliteDataAdapter(itemsSelectCmd); + SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); + landDa = new SqliteDataAdapter(landSelectCmd); - SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); - terrainDa = new SqliteDataAdapter(terrainSelectCmd); + SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); + landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); - SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); - landDa = new SqliteDataAdapter(landSelectCmd); + SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); + regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); + // This actually does the roll forward assembly stuff + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_conn, assem, "RegionStore"); + m.Update(); - SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); - landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); + lock (ds) + { + ds.Tables.Add(createPrimTable()); + setupPrimCommands(primDa, m_conn); - SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); - regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); - // This actually does the roll forward assembly stuff - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_conn, assem, "RegionStore"); - m.Update(); + ds.Tables.Add(createShapeTable()); + setupShapeCommands(shapeDa, m_conn); - lock (ds) - { - ds.Tables.Add(createPrimTable()); - setupPrimCommands(primDa, m_conn); - primDa.Fill(ds.Tables["prims"]); + ds.Tables.Add(createItemsTable()); + setupItemsCommands(itemsDa, m_conn); - ds.Tables.Add(createShapeTable()); - setupShapeCommands(shapeDa, m_conn); + ds.Tables.Add(createTerrainTable()); + setupTerrainCommands(terrainDa, m_conn); - ds.Tables.Add(createItemsTable()); - setupItemsCommands(itemsDa, m_conn); - itemsDa.Fill(ds.Tables["primitems"]); + ds.Tables.Add(createLandTable()); + setupLandCommands(landDa, m_conn); - ds.Tables.Add(createTerrainTable()); - setupTerrainCommands(terrainDa, m_conn); + ds.Tables.Add(createLandAccessListTable()); + setupLandAccessCommands(landAccessListDa, m_conn); - ds.Tables.Add(createLandTable()); - setupLandCommands(landDa, m_conn); + ds.Tables.Add(createRegionSettingsTable()); + setupRegionSettingsCommands(regionSettingsDa, m_conn); - ds.Tables.Add(createLandAccessListTable()); - setupLandAccessCommands(landAccessListDa, m_conn); + // WORKAROUND: This is a work around for sqlite on + // windows, which gets really unhappy with blob columns + // that have no sample data in them. At some point we + // need to actually find a proper way to handle this. + try + { + primDa.Fill(ds.Tables["prims"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on prims table"); + } - ds.Tables.Add(createRegionSettingsTable()); - - setupRegionSettingsCommands(regionSettingsDa, m_conn); + try + { + shapeDa.Fill(ds.Tables["primshapes"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on primshapes table"); + } - // WORKAROUND: This is a work around for sqlite on - // windows, which gets really unhappy with blob columns - // that have no sample data in them. At some point we - // need to actually find a proper way to handle this. - try - { - shapeDa.Fill(ds.Tables["primshapes"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on primshapes table"); - } + try + { + terrainDa.Fill(ds.Tables["terrain"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on terrain table"); + } - try - { - terrainDa.Fill(ds.Tables["terrain"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on terrain table"); - } + try + { + landDa.Fill(ds.Tables["land"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on land table"); + } - try - { - landDa.Fill(ds.Tables["land"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on land table"); - } + try + { + landAccessListDa.Fill(ds.Tables["landaccesslist"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); + } - try - { - landAccessListDa.Fill(ds.Tables["landaccesslist"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); - } + try + { + regionSettingsDa.Fill(ds.Tables["regionsettings"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); + } - try - { - regionSettingsDa.Fill(ds.Tables["regionsettings"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); + // We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values! + // Not sure exactly why this is - this kind of thing was not necessary before - justincc 20100409 + // Possibly because we manually set up our own DataTables before connecting to the database + CreateDataSetMapping(primDa, "prims"); + CreateDataSetMapping(shapeDa, "primshapes"); + CreateDataSetMapping(itemsDa, "primitems"); + CreateDataSetMapping(terrainDa, "terrain"); + CreateDataSetMapping(landDa, "land"); + CreateDataSetMapping(landAccessListDa, "landaccesslist"); + CreateDataSetMapping(regionSettingsDa, "regionsettings"); } - return; } + catch (Exception e) + { + m_log.Error(e); + Environment.Exit(23); + } + + return; } public void Dispose() @@ -594,7 +617,7 @@ namespace OpenSim.Data.SQLite } } } - rev = (int) row["Revision"]; + rev = Convert.ToInt32(row["Revision"]); } else { @@ -746,6 +769,7 @@ namespace OpenSim.Data.SQLite /// public void Commit() { + m_log.Debug("[SQLITE]: Starting commit"); lock (ds) { primDa.Update(ds, "prims"); @@ -760,18 +784,11 @@ namespace OpenSim.Data.SQLite { regionSettingsDa.Update(ds, "regionsettings"); } - catch (SqliteExecutionException SqlEx) + catch (SqliteException SqlEx) { - if (SqlEx.Message.Contains("logic error")) - { - throw new Exception( - "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", - SqlEx); - } - else - { - throw SqlEx; - } + throw new Exception( + "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", + SqlEx); } ds.AcceptChanges(); } @@ -793,6 +810,15 @@ namespace OpenSim.Data.SQLite * **********************************************************************/ + protected void CreateDataSetMapping(IDataAdapter da, string tableName) + { + ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName); + foreach (DataColumn col in ds.Tables[tableName].Columns) + { + dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName); + } + } + /// /// /// @@ -1955,6 +1981,7 @@ namespace OpenSim.Data.SQLite sql += ") values (:"; sql += String.Join(", :", cols); sql += ")"; + m_log.DebugFormat("[SQLITE]: Created insert command {0}", sql); SqliteCommand cmd = new SqliteCommand(sql); // this provides the binding for all our parameters, so @@ -2250,6 +2277,36 @@ namespace OpenSim.Data.SQLite return DbType.String; } } + + static void PrintDataSet(DataSet ds) + { + // Print out any name and extended properties. + Console.WriteLine("DataSet is named: {0}", ds.DataSetName); + foreach (System.Collections.DictionaryEntry de in ds.ExtendedProperties) + { + Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value); + } + Console.WriteLine(); + foreach (DataTable dt in ds.Tables) + { + Console.WriteLine("=> {0} Table:", dt.TableName); + // Print out the column names. + for (int curCol = 0; curCol < dt.Columns.Count; curCol++) + { + Console.Write(dt.Columns[curCol].ColumnName + "\t"); + } + Console.WriteLine("\n----------------------------------"); + // Print the DataTable. + for (int curRow = 0; curRow < dt.Rows.Count; curRow++) + { + for (int curCol = 0; curCol < dt.Columns.Count; curCol++) + { + Console.Write(dt.Rows[curRow][curCol].ToString() + "\t"); + } + Console.WriteLine(); + } + } + } } } diff --git a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs new file mode 100644 index 0000000..893f105 --- /dev/null +++ b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs @@ -0,0 +1,81 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.Sqlite; + +namespace OpenSim.Data.SQLite +{ + public class SQLiteUserAccountData : SQLiteGenericTableHandler, IUserAccountData + { + public SQLiteUserAccountData(string connectionString, string realm) + : base(connectionString, realm, "UserAccount") + { + } + + public UserAccountData[] GetUsers(UUID scopeID, string query) + { + string[] words = query.Split(new char[] {' '}); + + for (int i = 0 ; i < words.Length ; i++) + { + if (words[i].Length < 3) + { + if (i != words.Length - 1) + Array.Copy(words, i + 1, words, i, words.Length - i - 1); + Array.Resize(ref words, words.Length - 1); + } + } + + if (words.Length == 0) + return new UserAccountData[0]; + + if (words.Length > 2) + return new UserAccountData[0]; + + SqliteCommand cmd = new SqliteCommand(); + + if (words.Length == 1) + { + cmd.CommandText = String.Format("select * from {0} where ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", + m_Realm, scopeID.ToString(), words[0]); + } + else + { + cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{3}%')", + m_Realm, scopeID.ToString(), words[0], words[1]); + } + + return DoQuery(cmd); + } + } +} diff --git a/OpenSim/Data/SQLite/SQLiteUtils.cs b/OpenSim/Data/SQLite/SQLiteUtils.cs index 4a835ce..07c6b69 100644 --- a/OpenSim/Data/SQLite/SQLiteUtils.cs +++ b/OpenSim/Data/SQLite/SQLiteUtils.cs @@ -27,7 +27,7 @@ using System; using System.Data; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; namespace OpenSim.Data.SQLite { diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs index 5c93f88..0650a86 100644 --- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs @@ -29,7 +29,7 @@ using System; using System.Data; using System.Reflection; using System.Collections.Generic; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using log4net; using OpenMetaverse; using OpenSim.Framework; @@ -147,7 +147,11 @@ namespace OpenSim.Data.SQLite } reader.Close(); +<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteXInventoryData.cs CloseReaderCommand(cmd); +======= + //CloseCommand(cmd); +>>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteXInventoryData.cs return perms; } diff --git a/OpenSim/Data/SQLiteLegacy/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLiteLegacy/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..609a024 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Properties/AssemblyInfo.cs @@ -0,0 +1,65 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Reflection; +using System.Runtime.InteropServices; + +// General information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. + +[assembly : AssemblyTitle("OpenSim.Data.SQLiteLegacy")] +[assembly : AssemblyDescription("")] +[assembly : AssemblyConfiguration("")] +[assembly : AssemblyCompany("http://opensimulator.org")] +[assembly : AssemblyProduct("OpenSim.Data.SQLiteLegacy")] +[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] +[assembly : AssemblyTrademark("")] +[assembly : AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. + +[assembly : ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM + +[assembly : Guid("6113d5ce-4547-49f4-9236-0dcc503457b1")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly : AssemblyVersion("0.6.5.*")] +[assembly : AssemblyFileVersion("0.6.5.0")] diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_AssetStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_AssetStore.sql new file mode 100644 index 0000000..2e026ca --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/001_AssetStore.sql @@ -0,0 +1,12 @@ +BEGIN TRANSACTION; +CREATE TABLE assets( + UUID varchar(255) primary key, + Name varchar(255), + Description varchar(255), + Type integer, + InvType integer, + Local integer, + Temporary integer, + Data blob); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_AuthStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_AuthStore.sql new file mode 100644 index 0000000..468567d --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/001_AuthStore.sql @@ -0,0 +1,18 @@ +BEGIN TRANSACTION; + +CREATE TABLE auth ( + UUID char(36) NOT NULL, + passwordHash char(32) NOT NULL default '', + passwordSalt char(32) NOT NULL default '', + webLoginKey varchar(255) NOT NULL default '', + accountType VARCHAR(32) NOT NULL DEFAULT 'UserAccount', + PRIMARY KEY (`UUID`) +); + +CREATE TABLE tokens ( + UUID char(36) NOT NULL, + token varchar(255) NOT NULL, + validity datetime NOT NULL +); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql new file mode 100644 index 0000000..7ec906b --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql @@ -0,0 +1,9 @@ +BEGIN TRANSACTION; + +CREATE TABLE Avatars ( + PrincipalID CHAR(36) NOT NULL, + Name VARCHAR(32) NOT NULL, + Value VARCHAR(255) NOT NULL DEFAULT '', + PRIMARY KEY(PrincipalID, Name)); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_FriendsStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_FriendsStore.sql new file mode 100644 index 0000000..f1b9ab9 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/001_FriendsStore.sql @@ -0,0 +1,10 @@ +BEGIN TRANSACTION; + +CREATE TABLE `Friends` ( + `PrincipalID` CHAR(36) NOT NULL, + `Friend` VARCHAR(255) NOT NULL, + `Flags` VARCHAR(16) NOT NULL DEFAULT 0, + `Offered` VARCHAR(32) NOT NULL DEFAULT 0, + PRIMARY KEY(`PrincipalID`, `Friend`)); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_InventoryStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_InventoryStore.sql new file mode 100644 index 0000000..554d5c2 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/001_InventoryStore.sql @@ -0,0 +1,32 @@ +BEGIN TRANSACTION; + +CREATE TABLE inventoryfolders( + UUID varchar(255) primary key, + name varchar(255), + agentID varchar(255), + parentID varchar(255), + type integer, + version integer); + +CREATE TABLE inventoryitems( + UUID varchar(255) primary key, + assetID varchar(255), + assetType integer, + invType integer, + parentFolderID varchar(255), + avatarID varchar(255), + creatorsID varchar(255), + inventoryName varchar(255), + inventoryDescription varchar(255), + inventoryNextPermissions integer, + inventoryCurrentPermissions integer, + inventoryBasePermissions integer, + inventoryEveryOnePermissions integer, + salePrice integer default 99, + saleType integer default 0, + creationDate integer default 2000, + groupID varchar(255) default '00000000-0000-0000-0000-000000000000', + groupOwned integer default 0, + flags integer default 0); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_RegionStore.sql new file mode 100644 index 0000000..39e8180 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/001_RegionStore.sql @@ -0,0 +1,144 @@ +BEGIN TRANSACTION; + +CREATE TABLE prims( + UUID varchar(255) primary key, + RegionUUID varchar(255), + ParentID integer, + CreationDate integer, + Name varchar(255), + SceneGroupID varchar(255), + Text varchar(255), + Description varchar(255), + SitName varchar(255), + TouchName varchar(255), + CreatorID varchar(255), + OwnerID varchar(255), + GroupID varchar(255), + LastOwnerID varchar(255), + OwnerMask integer, + NextOwnerMask integer, + GroupMask integer, + EveryoneMask integer, + BaseMask integer, + PositionX float, + PositionY float, + PositionZ float, + GroupPositionX float, + GroupPositionY float, + GroupPositionZ float, + VelocityX float, + VelocityY float, + VelocityZ float, + AngularVelocityX float, + AngularVelocityY float, + AngularVelocityZ float, + AccelerationX float, + AccelerationY float, + AccelerationZ float, + RotationX float, + RotationY float, + RotationZ float, + RotationW float, + ObjectFlags integer, + SitTargetOffsetX float NOT NULL default 0, + SitTargetOffsetY float NOT NULL default 0, + SitTargetOffsetZ float NOT NULL default 0, + SitTargetOrientW float NOT NULL default 0, + SitTargetOrientX float NOT NULL default 0, + SitTargetOrientY float NOT NULL default 0, + SitTargetOrientZ float NOT NULL default 0); + +CREATE TABLE primshapes( + UUID varchar(255) primary key, + Shape integer, + ScaleX float, + ScaleY float, + ScaleZ float, + PCode integer, + PathBegin integer, + PathEnd integer, + PathScaleX integer, + PathScaleY integer, + PathShearX integer, + PathShearY integer, + PathSkew integer, + PathCurve integer, + PathRadiusOffset integer, + PathRevolutions integer, + PathTaperX integer, + PathTaperY integer, + PathTwist integer, + PathTwistBegin integer, + ProfileBegin integer, + ProfileEnd integer, + ProfileCurve integer, + ProfileHollow integer, + Texture blob, + ExtraParams blob, + State Integer NOT NULL default 0); + +CREATE TABLE primitems( + itemID varchar(255) primary key, + primID varchar(255), + assetID varchar(255), + parentFolderID varchar(255), + invType integer, + assetType integer, + name varchar(255), + description varchar(255), + creationDate integer, + creatorID varchar(255), + ownerID varchar(255), + lastOwnerID varchar(255), + groupID varchar(255), + nextPermissions string, + currentPermissions string, + basePermissions string, + everyonePermissions string, + groupPermissions string); + +CREATE TABLE terrain( + RegionUUID varchar(255), + Revision integer, + Heightfield blob); + +CREATE TABLE land( + UUID varchar(255) primary key, + RegionUUID varchar(255), + LocalLandID string, + Bitmap blob, + Name varchar(255), + Desc varchar(255), + OwnerUUID varchar(255), + IsGroupOwned string, + Area integer, + AuctionID integer, + Category integer, + ClaimDate integer, + ClaimPrice integer, + GroupUUID varchar(255), + SalePrice integer, + LandStatus integer, + LandFlags string, + LandingType string, + MediaAutoScale string, + MediaTextureUUID varchar(255), + MediaURL varchar(255), + MusicURL varchar(255), + PassHours float, + PassPrice string, + SnapshotUUID varchar(255), + UserLocationX float, + UserLocationY float, + UserLocationZ float, + UserLookAtX float, + UserLookAtY float, + UserLookAtZ float, + AuthbuyerID varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'); + +CREATE TABLE landaccesslist( + LandUUID varchar(255), + AccessUUID varchar(255), + Flags string); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_UserAccount.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_UserAccount.sql new file mode 100644 index 0000000..c38d9a7 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/001_UserAccount.sql @@ -0,0 +1,17 @@ +BEGIN TRANSACTION; + +-- useraccounts table +CREATE TABLE UserAccounts ( + PrincipalID CHAR(36) primary key, + ScopeID CHAR(36) NOT NULL, + FirstName VARCHAR(64) NOT NULL, + LastName VARCHAR(64) NOT NULL, + Email VARCHAR(64), + ServiceURLs TEXT, + Created INT(11), + UserLevel integer NOT NULL DEFAULT 0, + UserFlags integer NOT NULL DEFAULT 0, + UserTitle varchar(64) NOT NULL DEFAULT '' +); + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_UserStore.sql new file mode 100644 index 0000000..b584594 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/001_UserStore.sql @@ -0,0 +1,39 @@ +BEGIN TRANSACTION; + +-- users table +CREATE TABLE users( + UUID varchar(255) primary key, + username varchar(255), + surname varchar(255), + passwordHash varchar(255), + passwordSalt varchar(255), + homeRegionX integer, + homeRegionY integer, + homeLocationX float, + homeLocationY float, + homeLocationZ float, + homeLookAtX float, + homeLookAtY float, + homeLookAtZ float, + created integer, + lastLogin integer, + rootInventoryFolderID varchar(255), + userInventoryURI varchar(255), + userAssetURI varchar(255), + profileCanDoMask integer, + profileWantDoMask integer, + profileAboutText varchar(255), + profileFirstText varchar(255), + profileImage varchar(255), + profileFirstImage varchar(255), + webLoginKey text default '00000000-0000-0000-0000-000000000000'); +-- friends table +CREATE TABLE userfriends( + ownerID varchar(255), + friendID varchar(255), + friendPerms integer, + ownerPerms integer, + datetimestamp integer); + +COMMIT; + diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_AssetStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_AssetStore.sql new file mode 100644 index 0000000..5339b84 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/002_AssetStore.sql @@ -0,0 +1,10 @@ +BEGIN TRANSACTION; + +CREATE TEMPORARY TABLE assets_backup(UUID,Name,Description,Type,Local,Temporary,Data); +INSERT INTO assets_backup SELECT UUID,Name,Description,Type,Local,Temporary,Data FROM assets; +DROP TABLE assets; +CREATE TABLE assets(UUID,Name,Description,Type,Local,Temporary,Data); +INSERT INTO assets SELECT UUID,Name,Description,Type,Local,Temporary,Data FROM assets_backup; +DROP TABLE assets_backup; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_AuthStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_AuthStore.sql new file mode 100644 index 0000000..3237b68 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/002_AuthStore.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION; + +INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey) SELECT `UUID` AS UUID, `passwordHash` AS passwordHash, `passwordSalt` AS passwordSalt, `webLoginKey` AS webLoginKey FROM users; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_FriendsStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_FriendsStore.sql new file mode 100644 index 0000000..6733502 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/002_FriendsStore.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION; + +INSERT INTO `Friends` SELECT `ownerID`, `friendID`, `friendPerms`, 0 FROM `userfriends`; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_InventoryStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_InventoryStore.sql new file mode 100644 index 0000000..01951d6 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/002_InventoryStore.sql @@ -0,0 +1,8 @@ +BEGIN TRANSACTION; + +create index inventoryfolders_agentid on inventoryfolders(agentid); +create index inventoryfolders_parentid on inventoryfolders(parentid); +create index inventoryitems_parentfolderid on inventoryitems(parentfolderid); +create index inventoryitems_avatarid on inventoryitems(avatarid); + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_RegionStore.sql new file mode 100644 index 0000000..c5c7c99 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/002_RegionStore.sql @@ -0,0 +1,10 @@ +BEGIN TRANSACTION; + +CREATE TABLE regionban( + regionUUID varchar (255), + bannedUUID varchar (255), + bannedIp varchar (255), + bannedIpHostMask varchar (255) + ); + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_UserAccount.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_UserAccount.sql new file mode 100644 index 0000000..c7a6293 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/002_UserAccount.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION; + +INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT `UUID` AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, username AS FirstName, surname AS LastName, '' as Email, '' AS ServiceURLs, created as Created FROM users; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_UserStore.sql new file mode 100644 index 0000000..48fc680 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/002_UserStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE users add homeRegionID varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/003_AssetStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/003_AssetStore.sql new file mode 100644 index 0000000..f54f8d9 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/003_AssetStore.sql @@ -0,0 +1 @@ +DELETE FROM assets WHERE UUID = 'dc4b9f0bd00845c696a401dd947ac621' diff --git a/OpenSim/Data/SQLiteLegacy/Resources/003_InventoryStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/003_InventoryStore.sql new file mode 100644 index 0000000..4c6da91 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/003_InventoryStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +alter table inventoryitems add column inventoryGroupPermissions integer unsigned not null default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/003_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/003_RegionStore.sql new file mode 100644 index 0000000..4db2f75 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/003_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE primitems add flags integer not null default 0; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/Resources/003_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/003_UserStore.sql new file mode 100644 index 0000000..6f890ee --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/003_UserStore.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE users add userFlags integer NOT NULL default 0; +ALTER TABLE users add godLevel integer NOT NULL default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/004_AssetStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/004_AssetStore.sql new file mode 100644 index 0000000..39421c4 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/004_AssetStore.sql @@ -0,0 +1,7 @@ +BEGIN; + +update assets + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/004_InventoryStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/004_InventoryStore.sql new file mode 100644 index 0000000..e8f4d46 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/004_InventoryStore.sql @@ -0,0 +1,36 @@ +BEGIN; + +update inventoryitems + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update inventoryitems + set assetID = substr(assetID, 1, 8) || "-" || substr(assetID, 9, 4) || "-" || substr(assetID, 13, 4) || "-" || substr(assetID, 17, 4) || "-" || substr(assetID, 21, 12) + where assetID not like '%-%'; + +update inventoryitems + set parentFolderID = substr(parentFolderID, 1, 8) || "-" || substr(parentFolderID, 9, 4) || "-" || substr(parentFolderID, 13, 4) || "-" || substr(parentFolderID, 17, 4) || "-" || substr(parentFolderID, 21, 12) + where parentFolderID not like '%-%'; + +update inventoryitems + set avatarID = substr(avatarID, 1, 8) || "-" || substr(avatarID, 9, 4) || "-" || substr(avatarID, 13, 4) || "-" || substr(avatarID, 17, 4) || "-" || substr(avatarID, 21, 12) + where avatarID not like '%-%'; + +update inventoryitems + set creatorsID = substr(creatorsID, 1, 8) || "-" || substr(creatorsID, 9, 4) || "-" || substr(creatorsID, 13, 4) || "-" || substr(creatorsID, 17, 4) || "-" || substr(creatorsID, 21, 12) + where creatorsID not like '%-%'; + + +update inventoryfolders + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update inventoryfolders + set agentID = substr(agentID, 1, 8) || "-" || substr(agentID, 9, 4) || "-" || substr(agentID, 13, 4) || "-" || substr(agentID, 17, 4) || "-" || substr(agentID, 21, 12) + where agentID not like '%-%'; + +update inventoryfolders + set parentID = substr(parentID, 1, 8) || "-" || substr(parentID, 9, 4) || "-" || substr(parentID, 13, 4) || "-" || substr(parentID, 17, 4) || "-" || substr(parentID, 21, 12) + where parentID not like '%-%'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/004_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/004_RegionStore.sql new file mode 100644 index 0000000..de328cb --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/004_RegionStore.sql @@ -0,0 +1,38 @@ +BEGIN; + +create table regionsettings ( + regionUUID char(36) not null, + block_terraform integer not null, + block_fly integer not null, + allow_damage integer not null, + restrict_pushing integer not null, + allow_land_resell integer not null, + allow_land_join_divide integer not null, + block_show_in_search integer not null, + agent_limit integer not null, + object_bonus float not null, + maturity integer not null, + disable_scripts integer not null, + disable_collisions integer not null, + disable_physics integer not null, + terrain_texture_1 char(36) not null, + terrain_texture_2 char(36) not null, + terrain_texture_3 char(36) not null, + terrain_texture_4 char(36) not null, + elevation_1_nw float not null, + elevation_2_nw float not null, + elevation_1_ne float not null, + elevation_2_ne float not null, + elevation_1_se float not null, + elevation_2_se float not null, + elevation_1_sw float not null, + elevation_2_sw float not null, + water_height float not null, + terrain_raise_limit float not null, + terrain_lower_limit float not null, + use_estate_sun integer not null, + fixed_sun integer not null, + sun_position float not null, + covenant char(36)); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/004_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/004_UserStore.sql new file mode 100644 index 0000000..03142af --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/004_UserStore.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE users add customType varchar(32) not null default ''; +ALTER TABLE users add partner char(36) not null default '00000000-0000-0000-0000-000000000000'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/005_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/005_RegionStore.sql new file mode 100644 index 0000000..1f6d1bd --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/005_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +delete from regionsettings; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/005_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/005_UserStore.sql new file mode 100644 index 0000000..e45c09a --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/005_UserStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +CREATE TABLE `avatarattachments` (`UUID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', `attachpoint` int(11) NOT NULL DEFAULT 0, `item` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', `asset` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/006_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/006_RegionStore.sql new file mode 100644 index 0000000..94ed818 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/006_RegionStore.sql @@ -0,0 +1,102 @@ +BEGIN TRANSACTION; + +CREATE TABLE estate_groups ( + EstateID int(10) NOT NULL, + uuid char(36) NOT NULL +); + +CREATE TABLE estate_managers ( + EstateID int(10) NOT NULL, + uuid char(36) NOT NULL +); + +CREATE TABLE estate_map ( + RegionID char(36) NOT NULL default '00000000-0000-0000-0000-000000000000', + EstateID int(11) NOT NULL +); + +CREATE TABLE estate_settings ( + EstateID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + EstateName varchar(64) default NULL, + AbuseEmailToEstateOwner tinyint(4) NOT NULL, + DenyAnonymous tinyint(4) NOT NULL, + ResetHomeOnTeleport tinyint(4) NOT NULL, + FixedSun tinyint(4) NOT NULL, + DenyTransacted tinyint(4) NOT NULL, + BlockDwell tinyint(4) NOT NULL, + DenyIdentified tinyint(4) NOT NULL, + AllowVoice tinyint(4) NOT NULL, + UseGlobalTime tinyint(4) NOT NULL, + PricePerMeter int(11) NOT NULL, + TaxFree tinyint(4) NOT NULL, + AllowDirectTeleport tinyint(4) NOT NULL, + RedirectGridX int(11) NOT NULL, + RedirectGridY int(11) NOT NULL, + ParentEstateID int(10) NOT NULL, + SunPosition double NOT NULL, + EstateSkipScripts tinyint(4) NOT NULL, + BillableFactor float NOT NULL, + PublicAccess tinyint(4) NOT NULL +); +insert into estate_settings (EstateID,EstateName,AbuseEmailToEstateOwner,DenyAnonymous,ResetHomeOnTeleport,FixedSun,DenyTransacted,BlockDwell,DenyIdentified,AllowVoice,UseGlobalTime,PricePerMeter,TaxFree,AllowDirectTeleport,RedirectGridX,RedirectGridY,ParentEstateID,SunPosition,PublicAccess,EstateSkipScripts,BillableFactor) values ( 99, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''); +delete from estate_settings; +CREATE TABLE estate_users ( + EstateID int(10) NOT NULL, + uuid char(36) NOT NULL +); + +CREATE TABLE estateban ( + EstateID int(10) NOT NULL, + bannedUUID varchar(36) NOT NULL, + bannedIp varchar(16) NOT NULL, + bannedIpHostMask varchar(16) NOT NULL, + bannedNameMask varchar(64) default NULL +); + +drop table regionsettings; +CREATE TABLE regionsettings ( + regionUUID char(36) NOT NULL, + block_terraform int(11) NOT NULL, + block_fly int(11) NOT NULL, + allow_damage int(11) NOT NULL, + restrict_pushing int(11) NOT NULL, + allow_land_resell int(11) NOT NULL, + allow_land_join_divide int(11) NOT NULL, + block_show_in_search int(11) NOT NULL, + agent_limit int(11) NOT NULL, + object_bonus float NOT NULL, + maturity int(11) NOT NULL, + disable_scripts int(11) NOT NULL, + disable_collisions int(11) NOT NULL, + disable_physics int(11) NOT NULL, + terrain_texture_1 char(36) NOT NULL, + terrain_texture_2 char(36) NOT NULL, + terrain_texture_3 char(36) NOT NULL, + terrain_texture_4 char(36) NOT NULL, + elevation_1_nw float NOT NULL, + elevation_2_nw float NOT NULL, + elevation_1_ne float NOT NULL, + elevation_2_ne float NOT NULL, + elevation_1_se float NOT NULL, + elevation_2_se float NOT NULL, + elevation_1_sw float NOT NULL, + elevation_2_sw float NOT NULL, + water_height float NOT NULL, + terrain_raise_limit float NOT NULL, + terrain_lower_limit float NOT NULL, + use_estate_sun int(11) NOT NULL, + fixed_sun int(11) NOT NULL, + sun_position float NOT NULL, + covenant char(36) default NULL, + Sandbox tinyint(4) NOT NULL, + PRIMARY KEY (regionUUID) +); + +CREATE INDEX estate_ban_estate_id on estateban(EstateID); +CREATE INDEX estate_groups_estate_id on estate_groups(EstateID); +CREATE INDEX estate_managers_estate_id on estate_managers(EstateID); +CREATE INDEX estate_map_estate_id on estate_map(EstateID); +CREATE UNIQUE INDEX estate_map_region_id on estate_map(RegionID); +CREATE INDEX estate_users_estate_id on estate_users(EstateID); + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/Resources/006_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/006_UserStore.sql new file mode 100644 index 0000000..f9454c5 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/006_UserStore.sql @@ -0,0 +1,20 @@ +BEGIN TRANSACTION; + +-- usersagents table +CREATE TABLE IF NOT EXISTS useragents( + UUID varchar(255) primary key, + agentIP varchar(255), + agentPort integer, + agentOnline boolean, + sessionID varchar(255), + secureSessionID varchar(255), + regionID varchar(255), + loginTime integer, + logoutTime integer, + currentRegion varchar(255), + currentHandle varchar(255), + currentPosX float, + currentPosY float, + currentPosZ float); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/007_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/007_RegionStore.sql new file mode 100644 index 0000000..1c813a0 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/007_RegionStore.sql @@ -0,0 +1,8 @@ +begin; + +alter table estate_settings add column AbuseEmail varchar(255) not null default ''; + +alter table estate_settings add column EstateOwner varchar(36) not null default ''; + +commit; + diff --git a/OpenSim/Data/SQLiteLegacy/Resources/007_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/007_UserStore.sql new file mode 100644 index 0000000..8b0cd28 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/007_UserStore.sql @@ -0,0 +1,7 @@ +BEGIN TRANSACTION; + +ALTER TABLE useragents add currentLookAtX float not null default 128; +ALTER TABLE useragents add currentLookAtY float not null default 128; +ALTER TABLE useragents add currentLookAtZ float not null default 70; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/008_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/008_RegionStore.sql new file mode 100644 index 0000000..28bfbf5 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/008_RegionStore.sql @@ -0,0 +1,6 @@ +begin; + +alter table estate_settings add column DenyMinors tinyint not null default 0; + +commit; + diff --git a/OpenSim/Data/SQLiteLegacy/Resources/008_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/008_UserStore.sql new file mode 100644 index 0000000..97da818 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/008_UserStore.sql @@ -0,0 +1,5 @@ +BEGIN TRANSACTION; + +ALTER TABLE users add email varchar(250); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/009_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/009_RegionStore.sql new file mode 100644 index 0000000..1f40548 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/009_RegionStore.sql @@ -0,0 +1,8 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN ColorR integer not null default 0; +ALTER TABLE prims ADD COLUMN ColorG integer not null default 0; +ALTER TABLE prims ADD COLUMN ColorB integer not null default 0; +ALTER TABLE prims ADD COLUMN ColorA integer not null default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/009_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/009_UserStore.sql new file mode 100644 index 0000000..8ab03ef --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/009_UserStore.sql @@ -0,0 +1,11 @@ +BEGIN; + +update users + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update useragents + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/010_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/010_RegionStore.sql new file mode 100644 index 0000000..b91ccf0 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/010_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN ClickAction INTEGER NOT NULL default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/010_UserStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/010_UserStore.sql new file mode 100644 index 0000000..5f956da --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/010_UserStore.sql @@ -0,0 +1,37 @@ +BEGIN TRANSACTION; + +CREATE TABLE IF NOT EXISTS avatarappearance( + Owner varchar(36) NOT NULL primary key, + BodyItem varchar(36) DEFAULT NULL, + BodyAsset varchar(36) DEFAULT NULL, + SkinItem varchar(36) DEFAULT NULL, + SkinAsset varchar(36) DEFAULT NULL, + HairItem varchar(36) DEFAULT NULL, + HairAsset varchar(36) DEFAULT NULL, + EyesItem varchar(36) DEFAULT NULL, + EyesAsset varchar(36) DEFAULT NULL, + ShirtItem varchar(36) DEFAULT NULL, + ShirtAsset varchar(36) DEFAULT NULL, + PantsItem varchar(36) DEFAULT NULL, + PantsAsset varchar(36) DEFAULT NULL, + ShoesItem varchar(36) DEFAULT NULL, + ShoesAsset varchar(36) DEFAULT NULL, + SocksItem varchar(36) DEFAULT NULL, + SocksAsset varchar(36) DEFAULT NULL, + JacketItem varchar(36) DEFAULT NULL, + JacketAsset varchar(36) DEFAULT NULL, + GlovesItem varchar(36) DEFAULT NULL, + GlovesAsset varchar(36) DEFAULT NULL, + UnderShirtItem varchar(36) DEFAULT NULL, + UnderShirtAsset varchar(36) DEFAULT NULL, + UnderPantsItem varchar(36) DEFAULT NULL, + UnderPantsAsset varchar(36) DEFAULT NULL, + SkirtItem varchar(36) DEFAULT NULL, + SkirtAsset varchar(36) DEFAULT NULL, + Texture blob, + VisualParams blob, + Serial int DEFAULT NULL, + AvatarHeight float DEFAULT NULL +); + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/011_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/011_RegionStore.sql new file mode 100644 index 0000000..42bef89 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/011_RegionStore.sql @@ -0,0 +1,28 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN PayPrice INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN PayButton1 INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN PayButton2 INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN PayButton3 INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN PayButton4 INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN LoopedSound varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'; +ALTER TABLE prims ADD COLUMN LoopedSoundGain float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN TextureAnimation string; +ALTER TABLE prims ADD COLUMN ParticleSystem string; +ALTER TABLE prims ADD COLUMN OmegaX float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN OmegaY float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN OmegaZ float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraEyeOffsetX float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraEyeOffsetY float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraEyeOffsetZ float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraAtOffsetX float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraAtOffsetY float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN CameraAtOffsetZ float NOT NULL default 0; +ALTER TABLE prims ADD COLUMN ForceMouselook string NOT NULL default 0; +ALTER TABLE prims ADD COLUMN ScriptAccessPin INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN AllowedDrop INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN DieAtEdge string NOT NULL default 0; +ALTER TABLE prims ADD COLUMN SalePrice INTEGER NOT NULL default 0; +ALTER TABLE prims ADD COLUMN SaleType string NOT NULL default 0; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/Resources/012_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/012_RegionStore.sql new file mode 100644 index 0000000..d952b78 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/012_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN Material INTEGER NOT NULL default 3; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/013_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/013_RegionStore.sql new file mode 100644 index 0000000..11529cd --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/013_RegionStore.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE land ADD COLUMN OtherCleanTime INTEGER NOT NULL default 0; +ALTER TABLE land ADD COLUMN Dwell INTEGER NOT NULL default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/014_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/014_RegionStore.sql new file mode 100644 index 0000000..c59b27e --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/014_RegionStore.sql @@ -0,0 +1,8 @@ +begin; + +ALTER TABLE regionsettings ADD COLUMN sunvectorx double NOT NULL default 0; +ALTER TABLE regionsettings ADD COLUMN sunvectory double NOT NULL default 0; +ALTER TABLE regionsettings ADD COLUMN sunvectorz double NOT NULL default 0; + +commit; + diff --git a/OpenSim/Data/SQLiteLegacy/Resources/015_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/015_RegionStore.sql new file mode 100644 index 0000000..c43f356 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/015_RegionStore.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN CollisionSound varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'; +ALTER TABLE prims ADD COLUMN CollisionSoundVolume float NOT NULL default 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/016_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/016_RegionStore.sql new file mode 100644 index 0000000..52f160c --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/016_RegionStore.sql @@ -0,0 +1,5 @@ +BEGIN; + +ALTER TABLE prims ADD COLUMN VolumeDetect INTEGER NOT NULL DEFAULT 0; + +COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/017_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/017_RegionStore.sql new file mode 100644 index 0000000..6c6b7b5 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/017_RegionStore.sql @@ -0,0 +1,8 @@ +BEGIN; +CREATE TEMPORARY TABLE prims_backup(UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect); +INSERT INTO prims_backup SELECT UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect FROM prims; +DROP TABLE prims; +CREATE TABLE prims(UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect); +INSERT INTO prims SELECT UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect FROM prims_backup; +DROP TABLE prims_backup; +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/Resources/018_RegionStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/018_RegionStore.sql new file mode 100644 index 0000000..6a390c2 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/018_RegionStore.sql @@ -0,0 +1,79 @@ +BEGIN; + +update terrain + set RegionUUID = substr(RegionUUID, 1, 8) || "-" || substr(RegionUUID, 9, 4) || "-" || substr(RegionUUID, 13, 4) || "-" || substr(RegionUUID, 17, 4) || "-" || substr(RegionUUID, 21, 12) + where RegionUUID not like '%-%'; + + +update landaccesslist + set LandUUID = substr(LandUUID, 1, 8) || "-" || substr(LandUUID, 9, 4) || "-" || substr(LandUUID, 13, 4) || "-" || substr(LandUUID, 17, 4) || "-" || substr(LandUUID, 21, 12) + where LandUUID not like '%-%'; + +update landaccesslist + set AccessUUID = substr(AccessUUID, 1, 8) || "-" || substr(AccessUUID, 9, 4) || "-" || substr(AccessUUID, 13, 4) || "-" || substr(AccessUUID, 17, 4) || "-" || substr(AccessUUID, 21, 12) + where AccessUUID not like '%-%'; + + +update prims + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update prims + set RegionUUID = substr(RegionUUID, 1, 8) || "-" || substr(RegionUUID, 9, 4) || "-" || substr(RegionUUID, 13, 4) || "-" || substr(RegionUUID, 17, 4) || "-" || substr(RegionUUID, 21, 12) + where RegionUUID not like '%-%'; + +update prims + set SceneGroupID = substr(SceneGroupID, 1, 8) || "-" || substr(SceneGroupID, 9, 4) || "-" || substr(SceneGroupID, 13, 4) || "-" || substr(SceneGroupID, 17, 4) || "-" || substr(SceneGroupID, 21, 12) + where SceneGroupID not like '%-%'; + +update prims + set CreatorID = substr(CreatorID, 1, 8) || "-" || substr(CreatorID, 9, 4) || "-" || substr(CreatorID, 13, 4) || "-" || substr(CreatorID, 17, 4) || "-" || substr(CreatorID, 21, 12) + where CreatorID not like '%-%'; + +update prims + set OwnerID = substr(OwnerID, 1, 8) || "-" || substr(OwnerID, 9, 4) || "-" || substr(OwnerID, 13, 4) || "-" || substr(OwnerID, 17, 4) || "-" || substr(OwnerID, 21, 12) + where OwnerID not like '%-%'; + +update prims + set GroupID = substr(GroupID, 1, 8) || "-" || substr(GroupID, 9, 4) || "-" || substr(GroupID, 13, 4) || "-" || substr(GroupID, 17, 4) || "-" || substr(GroupID, 21, 12) + where GroupID not like '%-%'; + +update prims + set LastOwnerID = substr(LastOwnerID, 1, 8) || "-" || substr(LastOwnerID, 9, 4) || "-" || substr(LastOwnerID, 13, 4) || "-" || substr(LastOwnerID, 17, 4) || "-" || substr(LastOwnerID, 21, 12) + where LastOwnerID not like '%-%'; + + +update primshapes + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + + +update land + set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) + where UUID not like '%-%'; + +update land + set RegionUUID = substr(RegionUUID, 1, 8) || "-" || substr(RegionUUID, 9, 4) || "-" || substr(RegionUUID, 13, 4) || "-" || substr(RegionUUID, 17, 4) || "-" || substr(RegionUUID, 21, 12) + where RegionUUID not like '%-%'; + +update land + set OwnerUUID = substr(OwnerUUID, 1, 8) || "-" || substr(OwnerUUID, 9, 4) || "-" || substr(OwnerUUID, 13, 4) || "-" || substr(OwnerUUID, 17, 4) || "-" || substr(OwnerUUID, 21, 12) + where OwnerUUID not like '%-%'; + +update land + set GroupUUID = substr(GroupUUID, 1, 8) || "-" || substr(GroupUUID, 9, 4) || "-" || substr(GroupUUID, 13, 4) || "-" || substr(GroupUUID, 17, 4) || "-" || substr(GroupUUID, 21, 12) + where GroupUUID not like '%-%'; + +update land + set MediaTextureUUID = substr(MediaTextureUUID, 1, 8) || "-" || substr(MediaTextureUUID, 9, 4) || "-" || substr(MediaTextureUUID, 13, 4) || "-" || substr(MediaTextureUUID, 17, 4) || "-" || substr(MediaTextureUUID, 21, 12) + where MediaTextureUUID not like '%-%'; + +update land + set SnapshotUUID = substr(SnapshotUUID, 1, 8) || "-" || substr(SnapshotUUID, 9, 4) || "-" || substr(SnapshotUUID, 13, 4) || "-" || substr(SnapshotUUID, 17, 4) || "-" || substr(SnapshotUUID, 21, 12) + where SnapshotUUID not like '%-%'; + +update land + set AuthbuyerID = substr(AuthbuyerID, 1, 8) || "-" || substr(AuthbuyerID, 9, 4) || "-" || substr(AuthbuyerID, 13, 4) || "-" || substr(AuthbuyerID, 17, 4) || "-" || substr(AuthbuyerID, 21, 12) + where AuthbuyerID not like '%-%'; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/Resources/OpenSim.Data.SQLite.addin.xml b/OpenSim/Data/SQLiteLegacy/Resources/OpenSim.Data.SQLite.addin.xml new file mode 100644 index 0000000..e6764fa --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/Resources/OpenSim.Data.SQLite.addin.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs new file mode 100644 index 0000000..0d63dea --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs @@ -0,0 +1,343 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Data; +using System.Reflection; +using System.Collections.Generic; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.SQLiteLegacy +{ + /// + /// An asset storage interface for the SQLite database system + /// + public class SQLiteAssetData : AssetDataBase + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const string SelectAssetSQL = "select * from assets where UUID=:UUID"; + private const string SelectAssetMetadataSQL = "select Name, Description, Type, Temporary, UUID from assets limit :start, :count"; + private const string DeleteAssetSQL = "delete from assets where UUID=:UUID"; + private const string InsertAssetSQL = "insert into assets(UUID, Name, Description, Type, Local, Temporary, Data) values(:UUID, :Name, :Description, :Type, :Local, :Temporary, :Data)"; + private const string UpdateAssetSQL = "update assets set Name=:Name, Description=:Description, Type=:Type, Local=:Local, Temporary=:Temporary, Data=:Data where UUID=:UUID"; + private const string assetSelect = "select * from assets"; + + private SqliteConnection m_conn; + + override public void Dispose() + { + if (m_conn != null) + { + m_conn.Close(); + m_conn = null; + } + } + + /// + /// + /// Initialises AssetData interface + /// Loads and initialises a new SQLite connection and maintains it. + /// use default URI if connect string is empty. + /// + /// + /// connect string + override public void Initialise(string dbconnect) + { + if (dbconnect == string.Empty) + { + dbconnect = "URI=file:Asset.db,version=3"; + } + m_conn = new SqliteConnection(dbconnect); + m_conn.Open(); + + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_conn, assem, "AssetStore"); + m.Update(); + + return; + } + + /// + /// Fetch Asset + /// + /// UUID of ... ? + /// Asset base + override public AssetBase GetAsset(UUID uuid) + { + lock (this) + { + using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); + using (IDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + AssetBase asset = buildAsset(reader); + reader.Close(); + return asset; + } + else + { + reader.Close(); + return null; + } + } + } + } + } + + /// + /// Create an asset + /// + /// Asset Base + override public void StoreAsset(AssetBase asset) + { + //m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString()); + if (ExistsAsset(asset.FullID)) + { + //LogAssetLoad(asset); + + lock (this) + { + using (SqliteCommand cmd = new SqliteCommand(UpdateAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", asset.FullID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Name", asset.Name)); + cmd.Parameters.Add(new SqliteParameter(":Description", asset.Description)); + cmd.Parameters.Add(new SqliteParameter(":Type", asset.Type)); + cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); + cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); + cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); + + cmd.ExecuteNonQuery(); + } + } + } + else + { + lock (this) + { + using (SqliteCommand cmd = new SqliteCommand(InsertAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", asset.FullID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Name", asset.Name)); + cmd.Parameters.Add(new SqliteParameter(":Description", asset.Description)); + cmd.Parameters.Add(new SqliteParameter(":Type", asset.Type)); + cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); + cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); + cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); + + cmd.ExecuteNonQuery(); + } + } + } + } + +// /// +// /// Some... logging functionnality +// /// +// /// +// private static void LogAssetLoad(AssetBase asset) +// { +// string temporary = asset.Temporary ? "Temporary" : "Stored"; +// string local = asset.Local ? "Local" : "Remote"; +// +// int assetLength = (asset.Data != null) ? asset.Data.Length : 0; +// +// m_log.Debug("[ASSET DB]: " + +// string.Format("Loaded {5} {4} Asset: [{0}][{3}] \"{1}\":{2} ({6} bytes)", +// asset.FullID, asset.Name, asset.Description, asset.Type, +// temporary, local, assetLength)); +// } + + /// + /// Check if an asset exist in database + /// + /// The asset UUID + /// True if exist, or false. + override public bool ExistsAsset(UUID uuid) + { + lock (this) { + using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); + using (IDataReader reader = cmd.ExecuteReader()) + { + if (reader.Read()) + { + reader.Close(); + return true; + } + else + { + reader.Close(); + return false; + } + } + } + } + } + + /// + /// Delete an asset from database + /// + /// + public void DeleteAsset(UUID uuid) + { + using (SqliteCommand cmd = new SqliteCommand(DeleteAssetSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); + + cmd.ExecuteNonQuery(); + } + } + + /// + /// + /// + /// + /// + private static AssetBase buildAsset(IDataReader row) + { + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + AssetBase asset = new AssetBase( + new UUID((String)row["UUID"]), + (String)row["Name"], + Convert.ToSByte(row["Type"]), + UUID.Zero.ToString() + ); + + asset.Description = (String) row["Description"]; + asset.Local = Convert.ToBoolean(row["Local"]); + asset.Temporary = Convert.ToBoolean(row["Temporary"]); + asset.Data = (byte[]) row["Data"]; + return asset; + } + + private static AssetMetadata buildAssetMetadata(IDataReader row) + { + AssetMetadata metadata = new AssetMetadata(); + + metadata.FullID = new UUID((string) row["UUID"]); + metadata.Name = (string) row["Name"]; + metadata.Description = (string) row["Description"]; + metadata.Type = Convert.ToSByte(row["Type"]); + metadata.Temporary = Convert.ToBoolean(row["Temporary"]); // Not sure if this is correct. + + // Current SHA1s are not stored/computed. + metadata.SHA1 = new byte[] {}; + + return metadata; + } + + /// + /// Returns a list of AssetMetadata objects. The list is a subset of + /// the entire data set offset by containing + /// elements. + /// + /// The number of results to discard from the total data set. + /// The number of rows the returned list should contain. + /// A list of AssetMetadata objects. + public override List FetchAssetMetadataSet(int start, int count) + { + List retList = new List(count); + + lock (this) + { + using (SqliteCommand cmd = new SqliteCommand(SelectAssetMetadataSQL, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":start", start)); + cmd.Parameters.Add(new SqliteParameter(":count", count)); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while (reader.Read()) + { + AssetMetadata metadata = buildAssetMetadata(reader); + retList.Add(metadata); + } + } + } + } + + return retList; + } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + #region IPlugin interface + + /// + /// + /// + override public string Version + { + get + { + Module module = GetType().Module; + // string dllName = module.Assembly.ManifestModule.Name; + Version dllVersion = module.Assembly.GetName().Version; + + return + string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, + dllVersion.Revision); + } + } + + /// + /// Initialise the AssetData interface using default URI + /// + override public void Initialise() + { + Initialise("URI=file:Asset.db,version=3"); + } + + /// + /// Name of this DB provider + /// + override public string Name + { + get { return "SQLite Asset storage engine"; } + } + + #endregion + } +} \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteAuthenticationData.cs new file mode 100644 index 0000000..c64830a --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteAuthenticationData.cs @@ -0,0 +1,262 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLiteLegacy +{ + public class SQLiteAuthenticationData : SQLiteFramework, IAuthenticationData + { + private string m_Realm; + private List m_ColumnNames; + private int m_LastExpire; + private string m_connectionString; + + protected static SqliteConnection m_Connection; + private static bool m_initialized = false; + + public SQLiteAuthenticationData(string connectionString, string realm) + : base(connectionString) + { + m_Realm = realm; + m_connectionString = connectionString; + + if (!m_initialized) + { + m_Connection = new SqliteConnection(connectionString); + m_Connection.Open(); + + using (SqliteConnection dbcon = (SqliteConnection)((ICloneable)m_Connection).Clone()) + { + dbcon.Open(); + Migration m = new Migration(dbcon, GetType().Assembly, "AuthStore"); + m.Update(); + dbcon.Close(); + } + + m_initialized = true; + } + } + + public AuthenticationData Get(UUID principalID) + { + AuthenticationData ret = new AuthenticationData(); + ret.Data = new Dictionary(); + + SqliteCommand cmd = new SqliteCommand("select * from `" + m_Realm + "` where UUID = :PrincipalID"); + cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); + + IDataReader result = ExecuteReader(cmd, m_Connection); + + try + { + if (result.Read()) + { + ret.PrincipalID = principalID; + + if (m_ColumnNames == null) + { + m_ColumnNames = new List(); + + DataTable schemaTable = result.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + m_ColumnNames.Add(row["ColumnName"].ToString()); + } + + foreach (string s in m_ColumnNames) + { + if (s == "UUID") + continue; + + ret.Data[s] = result[s].ToString(); + } + + return ret; + } + else + { + return null; + } + } + catch + { + } + finally + { + CloseCommand(cmd); + } + + return null; + } + + public bool Store(AuthenticationData data) + { + if (data.Data.ContainsKey("UUID")) + data.Data.Remove("UUID"); + + string[] fields = new List(data.Data.Keys).ToArray(); + string[] values = new string[data.Data.Count]; + int i = 0; + foreach (object o in data.Data.Values) + values[i++] = o.ToString(); + + SqliteCommand cmd = new SqliteCommand(); + + if (Get(data.PrincipalID) != null) + { + + + string update = "update `" + m_Realm + "` set "; + bool first = true; + foreach (string field in fields) + { + if (!first) + update += ", "; + update += "`" + field + "` = :" + field; + cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); + + first = false; + } + + update += " where UUID = :UUID"; + cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); + + cmd.CommandText = update; + try + { + if (ExecuteNonQuery(cmd, m_Connection) < 1) + { + CloseCommand(cmd); + return false; + } + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + CloseCommand(cmd); + return false; + } + } + + else + { + string insert = "insert into `" + m_Realm + "` (`UUID`, `" + + String.Join("`, `", fields) + + "`) values (:UUID, :" + String.Join(", :", fields) + ")"; + + cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); + foreach (string field in fields) + cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); + + cmd.CommandText = insert; + + try + { + if (ExecuteNonQuery(cmd, m_Connection) < 1) + { + CloseCommand(cmd); + return false; + } + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + CloseCommand(cmd); + return false; + } + } + + CloseCommand(cmd); + + return true; + } + + public bool SetDataItem(UUID principalID, string item, string value) + { + SqliteCommand cmd = new SqliteCommand("update `" + m_Realm + + "` set `" + item + "` = " + value + " where UUID = '" + principalID.ToString() + "'"); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; + + return false; + } + + public bool SetToken(UUID principalID, string token, int lifetime) + { + if (System.Environment.TickCount - m_LastExpire > 30000) + DoExpire(); + + SqliteCommand cmd = new SqliteCommand("insert into tokens (UUID, token, validity) values ('" + principalID.ToString() + + "', '" + token + "', datetime('now', 'localtime', '+" + lifetime.ToString() + " minutes'))"); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + { + cmd.Dispose(); + return true; + } + + cmd.Dispose(); + return false; + } + + public bool CheckToken(UUID principalID, string token, int lifetime) + { + if (System.Environment.TickCount - m_LastExpire > 30000) + DoExpire(); + + SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now', 'localtime', '+" + lifetime.ToString() + + " minutes') where UUID = '" + principalID.ToString() + "' and token = '" + token + "' and validity > datetime('now', 'localtime')"); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + { + cmd.Dispose(); + return true; + } + + cmd.Dispose(); + + return false; + } + + private void DoExpire() + { + SqliteCommand cmd = new SqliteCommand("delete from tokens where validity < datetime('now', 'localtime')"); + ExecuteNonQuery(cmd, m_Connection); + + cmd.Dispose(); + + m_LastExpire = System.Environment.TickCount; + } + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs new file mode 100644 index 0000000..660632c --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs @@ -0,0 +1,74 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using System.Threading; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLiteLegacy +{ + /// + /// A SQLite Interface for Avatar Data + /// + public class SQLiteAvatarData : SQLiteGenericTableHandler, + IAvatarData + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public SQLiteAvatarData(string connectionString, string realm) : + base(connectionString, realm, "Avatar") + { + } + + public bool Delete(UUID principalID, string name) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("delete from {0} where `PrincipalID` = :PrincipalID and `Name` = :Name", m_Realm); + cmd.Parameters.Add(":PrincipalID", principalID.ToString()); + cmd.Parameters.Add(":Name", name); + + try + { + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; + + return false; + } + finally + { + CloseCommand(cmd); + } + } + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs new file mode 100644 index 0000000..e135eaa --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs @@ -0,0 +1,387 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Data.SQLiteLegacy +{ + public class SQLiteEstateStore : IEstateDataStore + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private SqliteConnection m_connection; + private string m_connectionString; + + private FieldInfo[] m_Fields; + private Dictionary m_FieldMap = + new Dictionary(); + + public void Initialise(string connectionString) + { + m_connectionString = connectionString; + + m_log.Info("[ESTATE DB]: Sqlite - connecting: "+m_connectionString); + + m_connection = new SqliteConnection(m_connectionString); + m_connection.Open(); + + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_connection, assem, "EstateStore"); + m.Update(); + + m_connection.Close(); + m_connection.Open(); + + Type t = typeof(EstateSettings); + m_Fields = t.GetFields(BindingFlags.NonPublic | + BindingFlags.Instance | + BindingFlags.DeclaredOnly); + + foreach (FieldInfo f in m_Fields) + if (f.Name.Substring(0, 2) == "m_") + m_FieldMap[f.Name.Substring(2)] = f; + } + + private string[] FieldList + { + get { return new List(m_FieldMap.Keys).ToArray(); } + } + + public EstateSettings LoadEstateSettings(UUID regionID, bool create) + { + string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = :RegionID"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + cmd.Parameters.Add(":RegionID", regionID.ToString()); + + return DoLoad(cmd, regionID, create); + } + + private EstateSettings DoLoad(SqliteCommand cmd, UUID regionID, bool create) + { + EstateSettings es = new EstateSettings(); + es.OnSave += StoreEstateSettings; + + IDataReader r = cmd.ExecuteReader(); + + if (r.Read()) + { + foreach (string name in FieldList) + { + if (m_FieldMap[name].GetValue(es) is bool) + { + int v = Convert.ToInt32(r[name]); + if (v != 0) + m_FieldMap[name].SetValue(es, true); + else + m_FieldMap[name].SetValue(es, false); + } + else if (m_FieldMap[name].GetValue(es) is UUID) + { + UUID uuid = UUID.Zero; + + UUID.TryParse(r[name].ToString(), out uuid); + m_FieldMap[name].SetValue(es, uuid); + } + else + { + m_FieldMap[name].SetValue(es, Convert.ChangeType(r[name], m_FieldMap[name].FieldType)); + } + } + r.Close(); + } + else if (create) + { + r.Close(); + + List names = new List(FieldList); + + names.Remove("EstateID"); + + string sql = "insert into estate_settings ("+String.Join(",", names.ToArray())+") values ( :"+String.Join(", :", names.ToArray())+")"; + + cmd.CommandText = sql; + cmd.Parameters.Clear(); + + foreach (string name in FieldList) + { + if (m_FieldMap[name].GetValue(es) is bool) + { + if ((bool)m_FieldMap[name].GetValue(es)) + cmd.Parameters.Add(":"+name, "1"); + else + cmd.Parameters.Add(":"+name, "0"); + } + else + { + cmd.Parameters.Add(":"+name, m_FieldMap[name].GetValue(es).ToString()); + } + } + + cmd.ExecuteNonQuery(); + + cmd.CommandText = "select LAST_INSERT_ROWID() as id"; + cmd.Parameters.Clear(); + + r = cmd.ExecuteReader(); + + r.Read(); + + es.EstateID = Convert.ToUInt32(r["id"]); + + r.Close(); + + cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; + cmd.Parameters.Add(":RegionID", regionID.ToString()); + cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + + // This will throw on dupe key + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception) + { + } + + es.Save(); + } + + LoadBanList(es); + + es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers"); + es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users"); + es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups"); + return es; + } + + public void StoreEstateSettings(EstateSettings es) + { + List fields = new List(FieldList); + fields.Remove("EstateID"); + + List terms = new List(); + + foreach (string f in fields) + terms.Add(f+" = :"+f); + + string sql = "update estate_settings set "+String.Join(", ", terms.ToArray())+" where EstateID = :EstateID"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + + foreach (string name in FieldList) + { + if (m_FieldMap[name].GetValue(es) is bool) + { + if ((bool)m_FieldMap[name].GetValue(es)) + cmd.Parameters.Add(":"+name, "1"); + else + cmd.Parameters.Add(":"+name, "0"); + } + else + { + cmd.Parameters.Add(":"+name, m_FieldMap[name].GetValue(es).ToString()); + } + } + + cmd.ExecuteNonQuery(); + + SaveBanList(es); + SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers); + SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess); + SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups); + } + + private void LoadBanList(EstateSettings es) + { + es.ClearBans(); + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "select bannedUUID from estateban where EstateID = :EstateID"; + cmd.Parameters.Add(":EstateID", es.EstateID); + + IDataReader r = cmd.ExecuteReader(); + + while (r.Read()) + { + EstateBan eb = new EstateBan(); + + UUID uuid = new UUID(); + UUID.TryParse(r["bannedUUID"].ToString(), out uuid); + + eb.BannedUserID = uuid; + eb.BannedHostAddress = "0.0.0.0"; + eb.BannedHostIPMask = "0.0.0.0"; + es.AddBan(eb); + } + r.Close(); + } + + private void SaveBanList(EstateSettings es) + { + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "delete from estateban where EstateID = :EstateID"; + cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + + cmd.ExecuteNonQuery(); + + cmd.Parameters.Clear(); + + cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( :EstateID, :bannedUUID, '', '', '' )"; + + foreach (EstateBan b in es.EstateBans) + { + cmd.Parameters.Add(":EstateID", es.EstateID.ToString()); + cmd.Parameters.Add(":bannedUUID", b.BannedUserID.ToString()); + + cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + } + } + + void SaveUUIDList(uint EstateID, string table, UUID[] data) + { + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "delete from "+table+" where EstateID = :EstateID"; + cmd.Parameters.Add(":EstateID", EstateID.ToString()); + + cmd.ExecuteNonQuery(); + + cmd.Parameters.Clear(); + + cmd.CommandText = "insert into "+table+" (EstateID, uuid) values ( :EstateID, :uuid )"; + + foreach (UUID uuid in data) + { + cmd.Parameters.Add(":EstateID", EstateID.ToString()); + cmd.Parameters.Add(":uuid", uuid.ToString()); + + cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + } + } + + UUID[] LoadUUIDList(uint EstateID, string table) + { + List uuids = new List(); + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "select uuid from "+table+" where EstateID = :EstateID"; + cmd.Parameters.Add(":EstateID", EstateID); + + IDataReader r = cmd.ExecuteReader(); + + while (r.Read()) + { + // EstateBan eb = new EstateBan(); + + UUID uuid = new UUID(); + UUID.TryParse(r["uuid"].ToString(), out uuid); + + uuids.Add(uuid); + } + r.Close(); + + return uuids.ToArray(); + } + + public EstateSettings LoadEstateSettings(int estateID) + { + string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID :EstateID"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + cmd.Parameters.Add(":EstateID", estateID.ToString()); + + return DoLoad(cmd, UUID.Zero, false); + } + + public List GetEstates(string search) + { + List result = new List(); + + string sql = "select EstateID from estate_settings where estate_settings.EstateName :EstateName"; + + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = sql; + cmd.Parameters.Add(":EstateName", search); + + IDataReader r = cmd.ExecuteReader(); + + while (r.Read()) + { + result.Add(Convert.ToInt32(r["EstateID"])); + } + r.Close(); + + return result; + } + + public bool LinkRegion(UUID regionID, int estateID) + { + SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); + + cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; + cmd.Parameters.Add(":RegionID", regionID.ToString()); + cmd.Parameters.Add(":EstateID", estateID.ToString()); + + if (cmd.ExecuteNonQuery() == 0) + return false; + + return true; + } + + public List GetRegions(int estateID) + { + return new List(); + } + + public bool DeleteEstate(int estateID) + { + return false; + } + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteFramework.cs b/OpenSim/Data/SQLiteLegacy/SQLiteFramework.cs new file mode 100644 index 0000000..606478e --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteFramework.cs @@ -0,0 +1,91 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLiteLegacy +{ + /// + /// A database interface class to a user profile storage system + /// + public class SQLiteFramework + { + protected Object m_lockObject = new Object(); + + protected SQLiteFramework(string connectionString) + { + } + + ////////////////////////////////////////////////////////////// + // + // All non queries are funneled through one connection + // to increase performance a little + // + protected int ExecuteNonQuery(SqliteCommand cmd, SqliteConnection connection) + { + lock (connection) + { + SqliteConnection newConnection = + (SqliteConnection)((ICloneable)connection).Clone(); + newConnection.Open(); + + cmd.Connection = newConnection; + //Console.WriteLine("XXX " + cmd.CommandText); + + return cmd.ExecuteNonQuery(); + } + } + + protected IDataReader ExecuteReader(SqliteCommand cmd, SqliteConnection connection) + { + lock (connection) + { + SqliteConnection newConnection = + (SqliteConnection)((ICloneable)connection).Clone(); + newConnection.Open(); + + cmd.Connection = newConnection; + //Console.WriteLine("XXX " + cmd.CommandText); + + return cmd.ExecuteReader(); + } + } + + protected void CloseCommand(SqliteCommand cmd) + { + cmd.Connection.Close(); + cmd.Connection.Dispose(); + cmd.Dispose(); + } + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs new file mode 100644 index 0000000..d529d4d --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs @@ -0,0 +1,70 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLiteLegacy +{ + public class SQLiteFriendsData : SQLiteGenericTableHandler, IFriendsData + { + public SQLiteFriendsData(string connectionString, string realm) + : base(connectionString, realm, "FriendsStore") + { + } + + public FriendsData[] GetFriends(UUID userID) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = :PrincipalID", m_Realm); + cmd.Parameters.Add(":PrincipalID", userID.ToString()); + + return DoQuery(cmd); + + } + + public bool Delete(UUID principalID, string friend) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm); + cmd.Parameters.Add(":PrincipalID", principalID.ToString()); + cmd.Parameters.Add(":Friend", friend); + + ExecuteNonQuery(cmd, cmd.Connection); + + return true; + } + + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLiteLegacy/SQLiteGenericTableHandler.cs new file mode 100644 index 0000000..1c1fe8c --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteGenericTableHandler.cs @@ -0,0 +1,268 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; + +namespace OpenSim.Data.SQLiteLegacy +{ + public class SQLiteGenericTableHandler : SQLiteFramework where T: class, new() + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Dictionary m_Fields = + new Dictionary(); + + protected List m_ColumnNames = null; + protected string m_Realm; + protected FieldInfo m_DataField = null; + + protected static SqliteConnection m_Connection; + private static bool m_initialized; + + public SQLiteGenericTableHandler(string connectionString, + string realm, string storeName) : base(connectionString) + { + m_Realm = realm; + + if (!m_initialized) + { + m_Connection = new SqliteConnection(connectionString); + m_Connection.Open(); + + if (storeName != String.Empty) + { + Assembly assem = GetType().Assembly; + SqliteConnection newConnection = + (SqliteConnection)((ICloneable)m_Connection).Clone(); + newConnection.Open(); + + Migration m = new Migration(newConnection, assem, storeName); + m.Update(); + newConnection.Close(); + newConnection.Dispose(); + } + + m_initialized = true; + } + + Type t = typeof(T); + FieldInfo[] fields = t.GetFields(BindingFlags.Public | + BindingFlags.Instance | + BindingFlags.DeclaredOnly); + + if (fields.Length == 0) + return; + + foreach (FieldInfo f in fields) + { + if (f.Name != "Data") + m_Fields[f.Name] = f; + else + m_DataField = f; + } + } + + private void CheckColumnNames(IDataReader reader) + { + if (m_ColumnNames != null) + return; + + m_ColumnNames = new List(); + + DataTable schemaTable = reader.GetSchemaTable(); + foreach (DataRow row in schemaTable.Rows) + { + if (row["ColumnName"] != null && + (!m_Fields.ContainsKey(row["ColumnName"].ToString()))) + m_ColumnNames.Add(row["ColumnName"].ToString()); + } + } + + public T[] Get(string field, string key) + { + return Get(new string[] { field }, new string[] { key }); + } + + public T[] Get(string[] fields, string[] keys) + { + if (fields.Length != keys.Length) + return new T[0]; + + List terms = new List(); + + SqliteCommand cmd = new SqliteCommand(); + + for (int i = 0 ; i < fields.Length ; i++) + { + cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i])); + terms.Add("`" + fields[i] + "` = :" + fields[i]); + } + + string where = String.Join(" and ", terms.ToArray()); + + string query = String.Format("select * from {0} where {1}", + m_Realm, where); + + cmd.CommandText = query; + + return DoQuery(cmd); + } + + protected T[] DoQuery(SqliteCommand cmd) + { + IDataReader reader = ExecuteReader(cmd, m_Connection); + if (reader == null) + return new T[0]; + + CheckColumnNames(reader); + + List result = new List(); + + while (reader.Read()) + { + T row = new T(); + + foreach (string name in m_Fields.Keys) + { + if (m_Fields[name].GetValue(row) is bool) + { + int v = Convert.ToInt32(reader[name]); + m_Fields[name].SetValue(row, v != 0 ? true : false); + } + else if (m_Fields[name].GetValue(row) is UUID) + { + UUID uuid = UUID.Zero; + + UUID.TryParse(reader[name].ToString(), out uuid); + m_Fields[name].SetValue(row, uuid); + } + else if (m_Fields[name].GetValue(row) is int) + { + int v = Convert.ToInt32(reader[name]); + m_Fields[name].SetValue(row, v); + } + else + { + m_Fields[name].SetValue(row, reader[name]); + } + } + + if (m_DataField != null) + { + Dictionary data = + new Dictionary(); + + foreach (string col in m_ColumnNames) + { + data[col] = reader[col].ToString(); + if (data[col] == null) + data[col] = String.Empty; + } + + m_DataField.SetValue(row, data); + } + + result.Add(row); + } + + CloseCommand(cmd); + + return result.ToArray(); + } + + public T[] Get(string where) + { + SqliteCommand cmd = new SqliteCommand(); + + string query = String.Format("select * from {0} where {1}", + m_Realm, where); + + cmd.CommandText = query; + + return DoQuery(cmd); + } + + public bool Store(T row) + { + SqliteCommand cmd = new SqliteCommand(); + + string query = ""; + List names = new List(); + List values = new List(); + + foreach (FieldInfo fi in m_Fields.Values) + { + names.Add(fi.Name); + values.Add(":" + fi.Name); + cmd.Parameters.Add(new SqliteParameter(":" + fi.Name, fi.GetValue(row).ToString())); + } + + if (m_DataField != null) + { + Dictionary data = + (Dictionary)m_DataField.GetValue(row); + + foreach (KeyValuePair kvp in data) + { + names.Add(kvp.Key); + values.Add(":" + kvp.Key); + cmd.Parameters.Add(new SqliteParameter(":" + kvp.Key, kvp.Value)); + } + } + + query = String.Format("replace into {0} (`", m_Realm) + String.Join("`,`", names.ToArray()) + "`) values (" + String.Join(",", values.ToArray()) + ")"; + + cmd.CommandText = query; + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; + + return false; + } + + public bool Delete(string field, string val) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("delete from {0} where `{1}` = :{1}", m_Realm, field); + cmd.Parameters.Add(new SqliteParameter(field, val)); + + if (ExecuteNonQuery(cmd, m_Connection) > 0) + return true; + + return false; + } + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteInventoryStore.cs b/OpenSim/Data/SQLiteLegacy/SQLiteInventoryStore.cs new file mode 100644 index 0000000..726703b --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteInventoryStore.cs @@ -0,0 +1,898 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Reflection; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.SQLiteLegacy +{ + /// + /// An Inventory Interface to the SQLite database + /// + public class SQLiteInventoryStore : SQLiteUtil, IInventoryDataPlugin + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const string invItemsSelect = "select * from inventoryitems"; + private const string invFoldersSelect = "select * from inventoryfolders"; + + private static SqliteConnection conn; + private static DataSet ds; + private static SqliteDataAdapter invItemsDa; + private static SqliteDataAdapter invFoldersDa; + + private static bool m_Initialized = false; + + public void Initialise() + { + m_log.Info("[SQLiteInventoryData]: " + Name + " cannot be default-initialized!"); + throw new PluginNotInitialisedException(Name); + } + + /// + /// + /// Initialises Inventory interface + /// Loads and initialises a new SQLite connection and maintains it. + /// use default URI if connect string string is empty. + /// + /// + /// connect string + public void Initialise(string dbconnect) + { + if (!m_Initialized) + { + m_Initialized = true; + + if (dbconnect == string.Empty) + { + dbconnect = "URI=file:inventoryStore.db,version=3"; + } + m_log.Info("[INVENTORY DB]: Sqlite - connecting: " + dbconnect); + conn = new SqliteConnection(dbconnect); + + conn.Open(); + + Assembly assem = GetType().Assembly; + Migration m = new Migration(conn, assem, "InventoryStore"); + m.Update(); + + SqliteCommand itemsSelectCmd = new SqliteCommand(invItemsSelect, conn); + invItemsDa = new SqliteDataAdapter(itemsSelectCmd); + // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + + SqliteCommand foldersSelectCmd = new SqliteCommand(invFoldersSelect, conn); + invFoldersDa = new SqliteDataAdapter(foldersSelectCmd); + + ds = new DataSet(); + + ds.Tables.Add(createInventoryFoldersTable()); + invFoldersDa.Fill(ds.Tables["inventoryfolders"]); + setupFoldersCommands(invFoldersDa, conn); + m_log.Info("[INVENTORY DB]: Populated Inventory Folders Definitions"); + + ds.Tables.Add(createInventoryItemsTable()); + invItemsDa.Fill(ds.Tables["inventoryitems"]); + setupItemsCommands(invItemsDa, conn); + m_log.Info("[INVENTORY DB]: Populated Inventory Items Definitions"); + + ds.AcceptChanges(); + } + } + + /// + /// Closes the inventory interface + /// + public void Dispose() + { + if (conn != null) + { + conn.Close(); + conn = null; + } + if (invItemsDa != null) + { + invItemsDa.Dispose(); + invItemsDa = null; + } + if (invFoldersDa != null) + { + invFoldersDa.Dispose(); + invFoldersDa = null; + } + if (ds != null) + { + ds.Dispose(); + ds = null; + } + } + + /// + /// + /// + /// + /// + public InventoryItemBase buildItem(DataRow row) + { + InventoryItemBase item = new InventoryItemBase(); + item.ID = new UUID((string) row["UUID"]); + item.AssetID = new UUID((string) row["assetID"]); + item.AssetType = Convert.ToInt32(row["assetType"]); + item.InvType = Convert.ToInt32(row["invType"]); + item.Folder = new UUID((string) row["parentFolderID"]); + item.Owner = new UUID((string) row["avatarID"]); + item.CreatorId = (string)row["creatorsID"]; + item.Name = (string) row["inventoryName"]; + item.Description = (string) row["inventoryDescription"]; + + item.NextPermissions = Convert.ToUInt32(row["inventoryNextPermissions"]); + item.CurrentPermissions = Convert.ToUInt32(row["inventoryCurrentPermissions"]); + item.BasePermissions = Convert.ToUInt32(row["inventoryBasePermissions"]); + item.EveryOnePermissions = Convert.ToUInt32(row["inventoryEveryOnePermissions"]); + item.GroupPermissions = Convert.ToUInt32(row["inventoryGroupPermissions"]); + + // new fields + if (!Convert.IsDBNull(row["salePrice"])) + item.SalePrice = Convert.ToInt32(row["salePrice"]); + + if (!Convert.IsDBNull(row["saleType"])) + item.SaleType = Convert.ToByte(row["saleType"]); + + if (!Convert.IsDBNull(row["creationDate"])) + item.CreationDate = Convert.ToInt32(row["creationDate"]); + + if (!Convert.IsDBNull(row["groupID"])) + item.GroupID = new UUID((string)row["groupID"]); + + if (!Convert.IsDBNull(row["groupOwned"])) + item.GroupOwned = Convert.ToBoolean(row["groupOwned"]); + + if (!Convert.IsDBNull(row["Flags"])) + item.Flags = Convert.ToUInt32(row["Flags"]); + + return item; + } + + /// + /// Fill a database row with item data + /// + /// + /// + private static void fillItemRow(DataRow row, InventoryItemBase item) + { + row["UUID"] = item.ID.ToString(); + row["assetID"] = item.AssetID.ToString(); + row["assetType"] = item.AssetType; + row["invType"] = item.InvType; + row["parentFolderID"] = item.Folder.ToString(); + row["avatarID"] = item.Owner.ToString(); + row["creatorsID"] = item.CreatorId.ToString(); + row["inventoryName"] = item.Name; + row["inventoryDescription"] = item.Description; + + row["inventoryNextPermissions"] = item.NextPermissions; + row["inventoryCurrentPermissions"] = item.CurrentPermissions; + row["inventoryBasePermissions"] = item.BasePermissions; + row["inventoryEveryOnePermissions"] = item.EveryOnePermissions; + row["inventoryGroupPermissions"] = item.GroupPermissions; + + // new fields + row["salePrice"] = item.SalePrice; + row["saleType"] = item.SaleType; + row["creationDate"] = item.CreationDate; + row["groupID"] = item.GroupID.ToString(); + row["groupOwned"] = item.GroupOwned; + row["flags"] = item.Flags; + } + + /// + /// Add inventory folder + /// + /// Folder base + /// true=create folder. false=update existing folder + /// nasty + private void addFolder(InventoryFolderBase folder, bool add) + { + lock (ds) + { + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + + DataRow inventoryRow = inventoryFolderTable.Rows.Find(folder.ID.ToString()); + if (inventoryRow == null) + { + if (! add) + m_log.ErrorFormat("Interface Misuse: Attempting to Update non-existant inventory folder: {0}", folder.ID); + + inventoryRow = inventoryFolderTable.NewRow(); + fillFolderRow(inventoryRow, folder); + inventoryFolderTable.Rows.Add(inventoryRow); + } + else + { + if (add) + m_log.ErrorFormat("Interface Misuse: Attempting to Add inventory folder that already exists: {0}", folder.ID); + + fillFolderRow(inventoryRow, folder); + } + + invFoldersDa.Update(ds, "inventoryfolders"); + } + } + + /// + /// Move an inventory folder + /// + /// folder base + private void moveFolder(InventoryFolderBase folder) + { + lock (ds) + { + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + + DataRow inventoryRow = inventoryFolderTable.Rows.Find(folder.ID.ToString()); + if (inventoryRow == null) + { + inventoryRow = inventoryFolderTable.NewRow(); + fillFolderRow(inventoryRow, folder); + inventoryFolderTable.Rows.Add(inventoryRow); + } + else + { + moveFolderRow(inventoryRow, folder); + } + + invFoldersDa.Update(ds, "inventoryfolders"); + } + } + + /// + /// add an item in inventory + /// + /// the item + /// true=add item ; false=update existing item + private void addItem(InventoryItemBase item, bool add) + { + lock (ds) + { + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + + DataRow inventoryRow = inventoryItemTable.Rows.Find(item.ID.ToString()); + if (inventoryRow == null) + { + if (!add) + m_log.ErrorFormat("[INVENTORY DB]: Interface Misuse: Attempting to Update non-existant inventory item: {0}", item.ID); + + inventoryRow = inventoryItemTable.NewRow(); + fillItemRow(inventoryRow, item); + inventoryItemTable.Rows.Add(inventoryRow); + } + else + { + if (add) + m_log.ErrorFormat("[INVENTORY DB]: Interface Misuse: Attempting to Add inventory item that already exists: {0}", item.ID); + + fillItemRow(inventoryRow, item); + } + + invItemsDa.Update(ds, "inventoryitems"); + + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + + inventoryRow = inventoryFolderTable.Rows.Find(item.Folder.ToString()); + if (inventoryRow != null) //MySQL doesn't throw an exception here, so sqlite shouldn't either. + inventoryRow["version"] = (int)inventoryRow["version"] + 1; + + invFoldersDa.Update(ds, "inventoryfolders"); + } + } + + /// + /// TODO : DataSet commit + /// + public void Shutdown() + { + // TODO: DataSet commit + } + + /// + /// The name of this DB provider + /// + /// Name of DB provider + public string Name + { + get { return "SQLite Inventory Data Interface"; } + } + + /// + /// Returns the version of this DB provider + /// + /// A string containing the DB provider version + public string Version + { + get + { + Module module = GetType().Module; + // string dllName = module.Assembly.ManifestModule.Name; + Version dllVersion = module.Assembly.GetName().Version; + + + return + string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, + dllVersion.Revision); + } + } + + /// + /// Returns a list of inventory items contained within the specified folder + /// + /// The UUID of the target folder + /// A List of InventoryItemBase items + public List getInventoryInFolder(UUID folderID) + { + lock (ds) + { + List retval = new List(); + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + string selectExp = "parentFolderID = '" + folderID + "'"; + DataRow[] rows = inventoryItemTable.Select(selectExp); + foreach (DataRow row in rows) + { + retval.Add(buildItem(row)); + } + + return retval; + } + } + + /// + /// Returns a list of the root folders within a users inventory + /// + /// The user whos inventory is to be searched + /// A list of folder objects + public List getUserRootFolders(UUID user) + { + return new List(); + } + + // see InventoryItemBase.getUserRootFolder + public InventoryFolderBase getUserRootFolder(UUID user) + { + lock (ds) + { + List folders = new List(); + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + string selectExp = "agentID = '" + user + "' AND parentID = '" + UUID.Zero + "'"; + DataRow[] rows = inventoryFolderTable.Select(selectExp); + foreach (DataRow row in rows) + { + folders.Add(buildFolder(row)); + } + + // There should only ever be one root folder for a user. However, if there's more + // than one we'll simply use the first one rather than failing. It would be even + // nicer to print some message to this effect, but this feels like it's too low a + // to put such a message out, and it's too minor right now to spare the time to + // suitably refactor. + if (folders.Count > 0) + { + return folders[0]; + } + + return null; + } + } + + /// + /// Append a list of all the child folders of a parent folder + /// + /// list where folders will be appended + /// ID of parent + protected void getInventoryFolders(ref List folders, UUID parentID) + { + lock (ds) + { + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + string selectExp = "parentID = '" + parentID + "'"; + DataRow[] rows = inventoryFolderTable.Select(selectExp); + foreach (DataRow row in rows) + { + folders.Add(buildFolder(row)); + } + + } + } + + /// + /// Returns a list of inventory folders contained in the folder 'parentID' + /// + /// The folder to get subfolders for + /// A list of inventory folders + public List getInventoryFolders(UUID parentID) + { + List folders = new List(); + getInventoryFolders(ref folders, parentID); + return folders; + } + + /// + /// See IInventoryDataPlugin + /// + /// + /// + public List getFolderHierarchy(UUID parentID) + { + /* Note: There are subtle changes between this implementation of getFolderHierarchy and the previous one + * - We will only need to hit the database twice instead of n times. + * - We assume the database is well-formed - no stranded/dangling folders, all folders in heirarchy owned + * by the same person, each user only has 1 inventory heirarchy + * - The returned list is not ordered, instead of breadth-first ordered + There are basically 2 usage cases for getFolderHeirarchy: + 1) Getting the user's entire inventory heirarchy when they log in + 2) Finding a subfolder heirarchy to delete when emptying the trash. + This implementation will pull all inventory folders from the database, and then prune away any folder that + is not part of the requested sub-heirarchy. The theory is that it is cheaper to make 1 request from the + database than to make n requests. This pays off only if requested heirarchy is large. + By making this choice, we are making the worst case better at the cost of making the best case worse + - Francis + */ + + List folders = new List(); + DataRow[] folderRows = null, parentRow; + InventoryFolderBase parentFolder = null; + lock (ds) + { + /* Fetch the parent folder from the database to determine the agent ID. + * Then fetch all inventory folders for that agent from the agent ID. + */ + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + string selectExp = "UUID = '" + parentID + "'"; + parentRow = inventoryFolderTable.Select(selectExp); // Assume at most 1 result + if (parentRow.GetLength(0) >= 1) // No result means parent folder does not exist + { + parentFolder = buildFolder(parentRow[0]); + UUID agentID = parentFolder.Owner; + selectExp = "agentID = '" + agentID + "'"; + folderRows = inventoryFolderTable.Select(selectExp); + } + + if (folderRows != null && folderRows.GetLength(0) >= 1) // No result means parent folder does not exist + { // or has no children + /* if we're querying the root folder, just return an unordered list of all folders in the user's + * inventory + */ + if (parentFolder.ParentID == UUID.Zero) + { + foreach (DataRow row in folderRows) + { + InventoryFolderBase curFolder = buildFolder(row); + if (curFolder.ID != parentID) // Return all folders except the parent folder of heirarchy + folders.Add(buildFolder(row)); + } + } // If requesting root folder + /* else we are querying a non-root folder. We currently have a list of all of the user's folders, + * we must construct a list of all folders in the heirarchy below parentID. + * Our first step will be to construct a hash table of all folders, indexed by parent ID. + * Once we have constructed the hash table, we will do a breadth-first traversal on the tree using the + * hash table to find child folders. + */ + else + { // Querying a non-root folder + + // Build a hash table of all user's inventory folders, indexed by each folder's parent ID + Dictionary> hashtable = + new Dictionary>(folderRows.GetLength(0)); + + foreach (DataRow row in folderRows) + { + InventoryFolderBase curFolder = buildFolder(row); + if (curFolder.ParentID != UUID.Zero) // Discard root of tree - not needed + { + if (hashtable.ContainsKey(curFolder.ParentID)) + { + // Current folder already has a sibling - append to sibling list + hashtable[curFolder.ParentID].Add(curFolder); + } + else + { + List siblingList = new List(); + siblingList.Add(curFolder); + // Current folder has no known (yet) siblings + hashtable.Add(curFolder.ParentID, siblingList); + } + } + } // For all inventory folders + + // Note: Could release the ds lock here - we don't access folderRows or the database anymore. + // This is somewhat of a moot point as the callers of this function usually lock db anyways. + + if (hashtable.ContainsKey(parentID)) // if requested folder does have children + folders.AddRange(hashtable[parentID]); + + // BreadthFirstSearch build inventory tree **Note: folders.Count is *not* static + for (int i = 0; i < folders.Count; i++) + if (hashtable.ContainsKey(folders[i].ID)) + folders.AddRange(hashtable[folders[i].ID]); + + } // if requesting a subfolder heirarchy + } // if folder parentID exists and has children + } // lock ds + return folders; + } + + /// + /// Returns an inventory item by its UUID + /// + /// The UUID of the item to be returned + /// A class containing item information + public InventoryItemBase getInventoryItem(UUID item) + { + lock (ds) + { + DataRow row = ds.Tables["inventoryitems"].Rows.Find(item.ToString()); + if (row != null) + { + return buildItem(row); + } + else + { + return null; + } + } + } + + /// + /// Returns a specified inventory folder by its UUID + /// + /// The UUID of the folder to be returned + /// A class containing folder information + public InventoryFolderBase getInventoryFolder(UUID folder) + { + // TODO: Deep voodoo here. If you enable this code then + // multi region breaks. No idea why, but I figured it was + // better to leave multi region at this point. It does mean + // that you don't get to see system textures why creating + // clothes and the like. :( + lock (ds) + { + DataRow row = ds.Tables["inventoryfolders"].Rows.Find(folder.ToString()); + if (row != null) + { + return buildFolder(row); + } + else + { + return null; + } + } + } + + /// + /// Creates a new inventory item based on item + /// + /// The item to be created + public void addInventoryItem(InventoryItemBase item) + { + addItem(item, true); + } + + /// + /// Updates an inventory item with item (updates based on ID) + /// + /// The updated item + public void updateInventoryItem(InventoryItemBase item) + { + addItem(item, false); + } + + /// + /// Delete an inventory item + /// + /// The item UUID + public void deleteInventoryItem(UUID itemID) + { + lock (ds) + { + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + + DataRow inventoryRow = inventoryItemTable.Rows.Find(itemID.ToString()); + if (inventoryRow != null) + { + inventoryRow.Delete(); + } + + invItemsDa.Update(ds, "inventoryitems"); + } + } + + public InventoryItemBase queryInventoryItem(UUID itemID) + { + return getInventoryItem(itemID); + } + + public InventoryFolderBase queryInventoryFolder(UUID folderID) + { + return getInventoryFolder(folderID); + } + + /// + /// Delete all items in the specified folder + /// + /// id of the folder, whose item content should be deleted + /// this is horribly inefficient, but I don't want to ruin the overall structure of this implementation + private void deleteItemsInFolder(UUID folderId) + { + List items = getInventoryInFolder(folderId); + + foreach (InventoryItemBase i in items) + deleteInventoryItem(i.ID); + } + + /// + /// Adds a new folder specified by folder + /// + /// The inventory folder + public void addInventoryFolder(InventoryFolderBase folder) + { + addFolder(folder, true); + } + + /// + /// Updates a folder based on its ID with folder + /// + /// The inventory folder + public void updateInventoryFolder(InventoryFolderBase folder) + { + addFolder(folder, false); + } + + /// + /// Moves a folder based on its ID with folder + /// + /// The inventory folder + public void moveInventoryFolder(InventoryFolderBase folder) + { + moveFolder(folder); + } + + /// + /// Delete a folder + /// + /// + /// This will clean-up any child folders and child items as well + /// + /// the folder UUID + public void deleteInventoryFolder(UUID folderID) + { + lock (ds) + { + List subFolders = getFolderHierarchy(folderID); + + DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; + DataRow inventoryRow; + + //Delete all sub-folders + foreach (InventoryFolderBase f in subFolders) + { + inventoryRow = inventoryFolderTable.Rows.Find(f.ID.ToString()); + if (inventoryRow != null) + { + deleteItemsInFolder(f.ID); + inventoryRow.Delete(); + } + } + + //Delete the actual row + inventoryRow = inventoryFolderTable.Rows.Find(folderID.ToString()); + if (inventoryRow != null) + { + deleteItemsInFolder(folderID); + inventoryRow.Delete(); + } + + invFoldersDa.Update(ds, "inventoryfolders"); + } + } + + /*********************************************************************** + * + * Data Table definitions + * + **********************************************************************/ + + /// + /// Create the "inventoryitems" table + /// + private static DataTable createInventoryItemsTable() + { + DataTable inv = new DataTable("inventoryitems"); + + createCol(inv, "UUID", typeof (String)); //inventoryID + createCol(inv, "assetID", typeof (String)); + createCol(inv, "assetType", typeof (Int32)); + createCol(inv, "invType", typeof (Int32)); + createCol(inv, "parentFolderID", typeof (String)); + createCol(inv, "avatarID", typeof (String)); + createCol(inv, "creatorsID", typeof (String)); + + createCol(inv, "inventoryName", typeof (String)); + createCol(inv, "inventoryDescription", typeof (String)); + // permissions + createCol(inv, "inventoryNextPermissions", typeof (Int32)); + createCol(inv, "inventoryCurrentPermissions", typeof (Int32)); + createCol(inv, "inventoryBasePermissions", typeof (Int32)); + createCol(inv, "inventoryEveryOnePermissions", typeof (Int32)); + createCol(inv, "inventoryGroupPermissions", typeof (Int32)); + + // sale info + createCol(inv, "salePrice", typeof(Int32)); + createCol(inv, "saleType", typeof(Byte)); + + // creation date + createCol(inv, "creationDate", typeof(Int32)); + + // group info + createCol(inv, "groupID", typeof(String)); + createCol(inv, "groupOwned", typeof(Boolean)); + + // Flags + createCol(inv, "flags", typeof(UInt32)); + + inv.PrimaryKey = new DataColumn[] { inv.Columns["UUID"] }; + return inv; + } + + /// + /// Creates the "inventoryfolders" table + /// + /// + private static DataTable createInventoryFoldersTable() + { + DataTable fol = new DataTable("inventoryfolders"); + + createCol(fol, "UUID", typeof (String)); //folderID + createCol(fol, "name", typeof (String)); + createCol(fol, "agentID", typeof (String)); + createCol(fol, "parentID", typeof (String)); + createCol(fol, "type", typeof (Int32)); + createCol(fol, "version", typeof (Int32)); + + fol.PrimaryKey = new DataColumn[] {fol.Columns["UUID"]}; + return fol; + } + + /// + /// + /// + /// + /// + private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + lock (ds) + { + da.InsertCommand = createInsertCommand("inventoryitems", ds.Tables["inventoryitems"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("inventoryitems", "UUID=:UUID", ds.Tables["inventoryitems"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from inventoryitems where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + } + + /// + /// + /// + /// + /// + private void setupFoldersCommands(SqliteDataAdapter da, SqliteConnection conn) + { + lock (ds) + { + da.InsertCommand = createInsertCommand("inventoryfolders", ds.Tables["inventoryfolders"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("inventoryfolders", "UUID=:UUID", ds.Tables["inventoryfolders"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from inventoryfolders where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + } + + /// + /// + /// + /// + /// + private static InventoryFolderBase buildFolder(DataRow row) + { + InventoryFolderBase folder = new InventoryFolderBase(); + folder.ID = new UUID((string) row["UUID"]); + folder.Name = (string) row["name"]; + folder.Owner = new UUID((string) row["agentID"]); + folder.ParentID = new UUID((string) row["parentID"]); + folder.Type = Convert.ToInt16(row["type"]); + folder.Version = Convert.ToUInt16(row["version"]); + return folder; + } + + /// + /// + /// + /// + /// + private static void fillFolderRow(DataRow row, InventoryFolderBase folder) + { + row["UUID"] = folder.ID.ToString(); + row["name"] = folder.Name; + row["agentID"] = folder.Owner.ToString(); + row["parentID"] = folder.ParentID.ToString(); + row["type"] = folder.Type; + row["version"] = folder.Version; + } + + /// + /// + /// + /// + /// + private static void moveFolderRow(DataRow row, InventoryFolderBase folder) + { + row["UUID"] = folder.ID.ToString(); + row["parentID"] = folder.ParentID.ToString(); + } + + public List fetchActiveGestures (UUID avatarID) + { + lock (ds) + { + List items = new List(); + + DataTable inventoryItemTable = ds.Tables["inventoryitems"]; + string selectExp + = "avatarID = '" + avatarID + "' AND assetType = " + (int)AssetType.Gesture + " AND flags = 1"; + //m_log.DebugFormat("[SQL]: sql = " + selectExp); + DataRow[] rows = inventoryItemTable.Select(selectExp); + foreach (DataRow row in rows) + { + items.Add(buildItem(row)); + } + return items; + } + } + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs new file mode 100644 index 0000000..eb78037 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs @@ -0,0 +1,2264 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Data; +using System.Drawing; +using System.IO; +using System.Reflection; +using log4net; +using Mono.Data.SqliteClient; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Data.SQLiteLegacy +{ + /// + /// A RegionData Interface to the SQLite database + /// + public class SQLiteRegionData : IRegionDataStore + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private const string primSelect = "select * from prims"; + private const string shapeSelect = "select * from primshapes"; + private const string itemsSelect = "select * from primitems"; + private const string terrainSelect = "select * from terrain limit 1"; + private const string landSelect = "select * from land"; + private const string landAccessListSelect = "select distinct * from landaccesslist"; + private const string regionbanListSelect = "select * from regionban"; + private const string regionSettingsSelect = "select * from regionsettings"; + + private DataSet ds; + private SqliteDataAdapter primDa; + private SqliteDataAdapter shapeDa; + private SqliteDataAdapter itemsDa; + private SqliteDataAdapter terrainDa; + private SqliteDataAdapter landDa; + private SqliteDataAdapter landAccessListDa; + private SqliteDataAdapter regionSettingsDa; + + private SqliteConnection m_conn; + + private String m_connectionString; + + // Temporary attribute while this is experimental + + /*********************************************************************** + * + * Public Interface Functions + * + **********************************************************************/ + + /// + /// See IRegionDataStore + /// + /// Initialises RegionData Interface + /// Loads and initialises a new SQLite connection and maintains it. + /// + /// + /// the connection string + public void Initialise(string connectionString) + { + m_connectionString = connectionString; + + ds = new DataSet(); + + m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); + m_conn = new SqliteConnection(m_connectionString); + m_conn.Open(); + + + + SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); + primDa = new SqliteDataAdapter(primSelectCmd); + // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); + + SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); + shapeDa = new SqliteDataAdapter(shapeSelectCmd); + // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); + + SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); + itemsDa = new SqliteDataAdapter(itemsSelectCmd); + + SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); + terrainDa = new SqliteDataAdapter(terrainSelectCmd); + + SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); + landDa = new SqliteDataAdapter(landSelectCmd); + + SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); + landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); + + SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); + regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); + // This actually does the roll forward assembly stuff + Assembly assem = GetType().Assembly; + Migration m = new Migration(m_conn, assem, "RegionStore"); + m.Update(); + + lock (ds) + { + ds.Tables.Add(createPrimTable()); + setupPrimCommands(primDa, m_conn); + primDa.Fill(ds.Tables["prims"]); + + ds.Tables.Add(createShapeTable()); + setupShapeCommands(shapeDa, m_conn); + + ds.Tables.Add(createItemsTable()); + setupItemsCommands(itemsDa, m_conn); + itemsDa.Fill(ds.Tables["primitems"]); + + ds.Tables.Add(createTerrainTable()); + setupTerrainCommands(terrainDa, m_conn); + + ds.Tables.Add(createLandTable()); + setupLandCommands(landDa, m_conn); + + ds.Tables.Add(createLandAccessListTable()); + setupLandAccessCommands(landAccessListDa, m_conn); + + ds.Tables.Add(createRegionSettingsTable()); + + setupRegionSettingsCommands(regionSettingsDa, m_conn); + + // WORKAROUND: This is a work around for sqlite on + // windows, which gets really unhappy with blob columns + // that have no sample data in them. At some point we + // need to actually find a proper way to handle this. + try + { + shapeDa.Fill(ds.Tables["primshapes"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on primshapes table"); + } + + try + { + terrainDa.Fill(ds.Tables["terrain"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on terrain table"); + } + + try + { + landDa.Fill(ds.Tables["land"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on land table"); + } + + try + { + landAccessListDa.Fill(ds.Tables["landaccesslist"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); + } + + try + { + regionSettingsDa.Fill(ds.Tables["regionsettings"]); + } + catch (Exception) + { + m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); + } + return; + } + } + + public void Dispose() + { + if (m_conn != null) + { + m_conn.Close(); + m_conn = null; + } + if (ds != null) + { + ds.Dispose(); + ds = null; + } + if (primDa != null) + { + primDa.Dispose(); + primDa = null; + } + if (shapeDa != null) + { + shapeDa.Dispose(); + shapeDa = null; + } + if (itemsDa != null) + { + itemsDa.Dispose(); + itemsDa = null; + } + if (terrainDa != null) + { + terrainDa.Dispose(); + terrainDa = null; + } + if (landDa != null) + { + landDa.Dispose(); + landDa = null; + } + if (landAccessListDa != null) + { + landAccessListDa.Dispose(); + landAccessListDa = null; + } + if (regionSettingsDa != null) + { + regionSettingsDa.Dispose(); + regionSettingsDa = null; + } + } + + public void StoreRegionSettings(RegionSettings rs) + { + lock (ds) + { + DataTable regionsettings = ds.Tables["regionsettings"]; + + DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString()); + if (settingsRow == null) + { + settingsRow = regionsettings.NewRow(); + fillRegionSettingsRow(settingsRow, rs); + regionsettings.Rows.Add(settingsRow); + } + else + { + fillRegionSettingsRow(settingsRow, rs); + } + + Commit(); + } + } + public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) + { + //This connector doesn't support the windlight module yet + //Return default LL windlight settings + return new RegionLightShareData(); + } + public void StoreRegionWindlightSettings(RegionLightShareData wl) + { + //This connector doesn't support the windlight module yet + } + public RegionSettings LoadRegionSettings(UUID regionUUID) + { + lock (ds) + { + DataTable regionsettings = ds.Tables["regionsettings"]; + + string searchExp = "regionUUID = '" + regionUUID.ToString() + "'"; + DataRow[] rawsettings = regionsettings.Select(searchExp); + if (rawsettings.Length == 0) + { + RegionSettings rs = new RegionSettings(); + rs.RegionUUID = regionUUID; + rs.OnSave += StoreRegionSettings; + + StoreRegionSettings(rs); + + return rs; + } + DataRow row = rawsettings[0]; + + RegionSettings newSettings = buildRegionSettings(row); + newSettings.OnSave += StoreRegionSettings; + + return newSettings; + } + } + + /// + /// Adds an object into region storage + /// + /// the object + /// the region UUID + public void StoreObject(SceneObjectGroup obj, UUID regionUUID) + { + uint flags = obj.RootPart.GetEffectiveObjectFlags(); + + // Eligibility check + // + if ((flags & (uint)PrimFlags.Temporary) != 0) + return; + if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) + return; + + lock (ds) + { + foreach (SceneObjectPart prim in obj.Children.Values) + { +// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); + addPrim(prim, obj.UUID, regionUUID); + } + } + + Commit(); + // m_log.Info("[Dump of prims]: " + ds.GetXml()); + } + + /// + /// Removes an object from region storage + /// + /// the object + /// the region UUID + public void RemoveObject(UUID obj, UUID regionUUID) + { + // m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.Guid, regionUUID); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string selectExp = "SceneGroupID = '" + obj + "' and RegionUUID = '" + regionUUID + "'"; + lock (ds) + { + DataRow[] primRows = prims.Select(selectExp); + foreach (DataRow row in primRows) + { + // Remove shape rows + UUID uuid = new UUID((string) row["UUID"]); + DataRow shapeRow = shapes.Rows.Find(uuid.ToString()); + if (shapeRow != null) + { + shapeRow.Delete(); + } + + RemoveItems(uuid); + + // Remove prim row + row.Delete(); + } + } + + Commit(); + } + + /// + /// Remove all persisted items of the given prim. + /// The caller must acquire the necessrary synchronization locks and commit or rollback changes. + /// + /// The item UUID + private void RemoveItems(UUID uuid) + { + DataTable items = ds.Tables["primitems"]; + + String sql = String.Format("primID = '{0}'", uuid); + DataRow[] itemRows = items.Select(sql); + + foreach (DataRow itemRow in itemRows) + { + itemRow.Delete(); + } + } + + /// + /// Load persisted objects from region storage. + /// + /// The region UUID + /// List of loaded groups + public List LoadObjects(UUID regionUUID) + { + Dictionary createdObjects = new Dictionary(); + + List retvals = new List(); + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + string byRegion = "RegionUUID = '" + regionUUID + "'"; + + lock (ds) + { + DataRow[] primsForRegion = prims.Select(byRegion); + m_log.Info("[REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); + + // First, create all groups + foreach (DataRow primRow in primsForRegion) + { + try + { + SceneObjectPart prim = null; + + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + + if (uuid == objID) //is new SceneObjectGroup ? + { + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Info( + "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + + SceneObjectGroup group = new SceneObjectGroup(prim); + createdObjects.Add(group.UUID, group); + retvals.Add(group); + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[REGION DB]: Failed create prim object in new group, exception and data follows"); + m_log.Info("[REGION DB]: " + e.ToString()); + foreach (DataColumn col in prims.Columns) + { + m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + + // Now fill the groups with part data + foreach (DataRow primRow in primsForRegion) + { + try + { + SceneObjectPart prim = null; + + string uuid = (string) primRow["UUID"]; + string objID = (string) primRow["SceneGroupID"]; + if (uuid != objID) //is new SceneObjectGroup ? + { + prim = buildPrim(primRow); + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow != null) + { + prim.Shape = buildShape(shapeRow); + } + else + { + m_log.Warn( + "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + prim.Shape = PrimitiveBaseShape.Default; + } + + createdObjects[new UUID(objID)].AddPart(prim); + LoadItems(prim); + } + } + catch (Exception e) + { + m_log.Error("[REGION DB]: Failed create prim object in group, exception and data follows"); + m_log.Info("[REGION DB]: " + e.ToString()); + foreach (DataColumn col in prims.Columns) + { + m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + } + } + } + } + return retvals; + } + + /// + /// Load in a prim's persisted inventory. + /// + /// the prim + private void LoadItems(SceneObjectPart prim) + { + //m_log.DebugFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); + + DataTable dbItems = ds.Tables["primitems"]; + String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); + DataRow[] dbItemRows = dbItems.Select(sql); + IList inventory = new List(); + + foreach (DataRow row in dbItemRows) + { + TaskInventoryItem item = buildItem(row); + inventory.Add(item); + + //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); + } + + prim.Inventory.RestoreInventoryItems(inventory); + } + + /// + /// Store a terrain revision in region storage + /// + /// terrain heightfield + /// region UUID + public void StoreTerrain(double[,] ter, UUID regionID) + { + lock (ds) + { + int revision = Util.UnixTimeSinceEpoch(); + + // This is added to get rid of the infinitely growing + // terrain databases which negatively impact on SQLite + // over time. Before reenabling this feature there + // needs to be a limitter put on the number of + // revisions in the database, as this old + // implementation is a DOS attack waiting to happen. + + using ( + SqliteCommand cmd = + new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision", + m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.ExecuteNonQuery(); + } + + // the following is an work around for .NET. The perf + // issues associated with it aren't as bad as you think. + m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString()); + String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + + " values(:RegionUUID, :Revision, :Heightfield)"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); + cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter))); + cmd.ExecuteNonQuery(); + } + } + } + + /// + /// Load the latest terrain revision from region storage + /// + /// the region UUID + /// Heightfield data + public double[,] LoadTerrain(UUID regionID) + { + lock (ds) + { + double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; + terret.Initialize(); + + String sql = "select RegionUUID, Revision, Heightfield from terrain" + + " where RegionUUID=:RegionUUID order by Revision desc"; + + using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) + { + cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); + + using (IDataReader row = cmd.ExecuteReader()) + { + int rev = 0; + if (row.Read()) + { + // TODO: put this into a function + using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"])) + { + using (BinaryReader br = new BinaryReader(str)) + { + for (int x = 0; x < (int)Constants.RegionSize; x++) + { + for (int y = 0; y < (int)Constants.RegionSize; y++) + { + terret[x, y] = br.ReadDouble(); + } + } + } + } + rev = (int) row["Revision"]; + } + else + { + m_log.Info("[REGION DB]: No terrain found for region"); + return null; + } + + m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString()); + } + } + return terret; + } + } + + /// + /// + /// + /// + public void RemoveLandObject(UUID globalID) + { + lock (ds) + { + // Can't use blanket SQL statements when using SqlAdapters unless you re-read the data into the adapter + // after you're done. + // replaced below code with the SqliteAdapter version. + //using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); + // cmd.ExecuteNonQuery(); + //} + + //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); + // cmd.ExecuteNonQuery(); + //} + + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + DataRow landRow = land.Rows.Find(globalID.ToString()); + if (landRow != null) + { + land.Rows.Remove(landRow); + } + List rowsToDelete = new List(); + foreach (DataRow rowToCheck in landaccesslist.Rows) + { + if (rowToCheck["LandUUID"].ToString() == globalID.ToString()) + rowsToDelete.Add(rowToCheck); + } + for (int iter = 0; iter < rowsToDelete.Count; iter++) + { + landaccesslist.Rows.Remove(rowsToDelete[iter]); + } + + + } + Commit(); + } + + /// + /// + /// + /// + public void StoreLandObject(ILandObject parcel) + { + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + + DataRow landRow = land.Rows.Find(parcel.LandData.GlobalID.ToString()); + if (landRow == null) + { + landRow = land.NewRow(); + fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); + land.Rows.Add(landRow); + } + else + { + fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); + } + + // I know this caused someone issues before, but OpenSim is unusable if we leave this stuff around + //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn)) + //{ + // cmd.Parameters.Add(new SqliteParameter(":LandUUID", parcel.LandData.GlobalID.ToString())); + // cmd.ExecuteNonQuery(); + +// } + + // This is the slower.. but more appropriate thing to do + + // We can't modify the table with direct queries before calling Commit() and re-filling them. + List rowsToDelete = new List(); + foreach (DataRow rowToCheck in landaccesslist.Rows) + { + if (rowToCheck["LandUUID"].ToString() == parcel.LandData.GlobalID.ToString()) + rowsToDelete.Add(rowToCheck); + } + for (int iter = 0; iter < rowsToDelete.Count; iter++) + { + landaccesslist.Rows.Remove(rowsToDelete[iter]); + } + rowsToDelete.Clear(); + foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList) + { + DataRow newAccessRow = landaccesslist.NewRow(); + fillLandAccessRow(newAccessRow, entry, parcel.LandData.GlobalID); + landaccesslist.Rows.Add(newAccessRow); + } + } + + Commit(); + } + + /// + /// + /// + /// + /// + public List LoadLandObjects(UUID regionUUID) + { + List landDataForRegion = new List(); + lock (ds) + { + DataTable land = ds.Tables["land"]; + DataTable landaccesslist = ds.Tables["landaccesslist"]; + string searchExp = "RegionUUID = '" + regionUUID + "'"; + DataRow[] rawDataForRegion = land.Select(searchExp); + foreach (DataRow rawDataLand in rawDataForRegion) + { + LandData newLand = buildLandData(rawDataLand); + string accessListSearchExp = "LandUUID = '" + newLand.GlobalID + "'"; + DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); + foreach (DataRow rawDataLandAccess in rawDataForLandAccessList) + { + newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); + } + + landDataForRegion.Add(newLand); + } + } + return landDataForRegion; + } + + /// + /// + /// + public void Commit() + { + lock (ds) + { + primDa.Update(ds, "prims"); + shapeDa.Update(ds, "primshapes"); + + itemsDa.Update(ds, "primitems"); + + terrainDa.Update(ds, "terrain"); + landDa.Update(ds, "land"); + landAccessListDa.Update(ds, "landaccesslist"); + try + { + regionSettingsDa.Update(ds, "regionsettings"); + } + catch (SqliteExecutionException SqlEx) + { + if (SqlEx.Message.Contains("logic error")) + { + throw new Exception( + "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", + SqlEx); + } + else + { + throw SqlEx; + } + } + ds.AcceptChanges(); + } + } + + /// + /// See + /// + public void Shutdown() + { + Commit(); + } + + /*********************************************************************** + * + * Database Definition Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + /// + /// + /// + /// + /// + /// + private static void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + /// + /// Creates the "terrain" table + /// + /// terrain table DataTable + private static DataTable createTerrainTable() + { + DataTable terrain = new DataTable("terrain"); + + createCol(terrain, "RegionUUID", typeof (String)); + createCol(terrain, "Revision", typeof (Int32)); + createCol(terrain, "Heightfield", typeof (Byte[])); + + return terrain; + } + + /// + /// Creates the "prims" table + /// + /// prim table DataTable + private static DataTable createPrimTable() + { + DataTable prims = new DataTable("prims"); + + createCol(prims, "UUID", typeof (String)); + createCol(prims, "RegionUUID", typeof (String)); + createCol(prims, "CreationDate", typeof (Int32)); + createCol(prims, "Name", typeof (String)); + createCol(prims, "SceneGroupID", typeof (String)); + // various text fields + createCol(prims, "Text", typeof (String)); + createCol(prims, "ColorR", typeof (Int32)); + createCol(prims, "ColorG", typeof (Int32)); + createCol(prims, "ColorB", typeof (Int32)); + createCol(prims, "ColorA", typeof (Int32)); + createCol(prims, "Description", typeof (String)); + createCol(prims, "SitName", typeof (String)); + createCol(prims, "TouchName", typeof (String)); + // permissions + createCol(prims, "ObjectFlags", typeof (Int32)); + createCol(prims, "CreatorID", typeof (String)); + createCol(prims, "OwnerID", typeof (String)); + createCol(prims, "GroupID", typeof (String)); + createCol(prims, "LastOwnerID", typeof (String)); + createCol(prims, "OwnerMask", typeof (Int32)); + createCol(prims, "NextOwnerMask", typeof (Int32)); + createCol(prims, "GroupMask", typeof (Int32)); + createCol(prims, "EveryoneMask", typeof (Int32)); + createCol(prims, "BaseMask", typeof (Int32)); + // vectors + createCol(prims, "PositionX", typeof (Double)); + createCol(prims, "PositionY", typeof (Double)); + createCol(prims, "PositionZ", typeof (Double)); + createCol(prims, "GroupPositionX", typeof (Double)); + createCol(prims, "GroupPositionY", typeof (Double)); + createCol(prims, "GroupPositionZ", typeof (Double)); + createCol(prims, "VelocityX", typeof (Double)); + createCol(prims, "VelocityY", typeof (Double)); + createCol(prims, "VelocityZ", typeof (Double)); + createCol(prims, "AngularVelocityX", typeof (Double)); + createCol(prims, "AngularVelocityY", typeof (Double)); + createCol(prims, "AngularVelocityZ", typeof (Double)); + createCol(prims, "AccelerationX", typeof (Double)); + createCol(prims, "AccelerationY", typeof (Double)); + createCol(prims, "AccelerationZ", typeof (Double)); + // quaternions + createCol(prims, "RotationX", typeof (Double)); + createCol(prims, "RotationY", typeof (Double)); + createCol(prims, "RotationZ", typeof (Double)); + createCol(prims, "RotationW", typeof (Double)); + + // sit target + createCol(prims, "SitTargetOffsetX", typeof (Double)); + createCol(prims, "SitTargetOffsetY", typeof (Double)); + createCol(prims, "SitTargetOffsetZ", typeof (Double)); + + createCol(prims, "SitTargetOrientW", typeof (Double)); + createCol(prims, "SitTargetOrientX", typeof (Double)); + createCol(prims, "SitTargetOrientY", typeof (Double)); + createCol(prims, "SitTargetOrientZ", typeof (Double)); + + createCol(prims, "PayPrice", typeof(Int32)); + createCol(prims, "PayButton1", typeof(Int32)); + createCol(prims, "PayButton2", typeof(Int32)); + createCol(prims, "PayButton3", typeof(Int32)); + createCol(prims, "PayButton4", typeof(Int32)); + + createCol(prims, "LoopedSound", typeof(String)); + createCol(prims, "LoopedSoundGain", typeof(Double)); + createCol(prims, "TextureAnimation", typeof(String)); + createCol(prims, "ParticleSystem", typeof(String)); + + createCol(prims, "OmegaX", typeof(Double)); + createCol(prims, "OmegaY", typeof(Double)); + createCol(prims, "OmegaZ", typeof(Double)); + + createCol(prims, "CameraEyeOffsetX", typeof(Double)); + createCol(prims, "CameraEyeOffsetY", typeof(Double)); + createCol(prims, "CameraEyeOffsetZ", typeof(Double)); + + createCol(prims, "CameraAtOffsetX", typeof(Double)); + createCol(prims, "CameraAtOffsetY", typeof(Double)); + createCol(prims, "CameraAtOffsetZ", typeof(Double)); + + createCol(prims, "ForceMouselook", typeof(Int16)); + + createCol(prims, "ScriptAccessPin", typeof(Int32)); + + createCol(prims, "AllowedDrop", typeof(Int16)); + createCol(prims, "DieAtEdge", typeof(Int16)); + + createCol(prims, "SalePrice", typeof(Int32)); + createCol(prims, "SaleType", typeof(Int16)); + + // click action + createCol(prims, "ClickAction", typeof (Byte)); + + createCol(prims, "Material", typeof(Byte)); + + createCol(prims, "CollisionSound", typeof(String)); + createCol(prims, "CollisionSoundVolume", typeof(Double)); + + createCol(prims, "VolumeDetect", typeof(Int16)); + + // Add in contraints + prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; + + return prims; + } + + /// + /// Creates "primshapes" table + /// + /// shape table DataTable + private static DataTable createShapeTable() + { + DataTable shapes = new DataTable("primshapes"); + createCol(shapes, "UUID", typeof (String)); + // shape is an enum + createCol(shapes, "Shape", typeof (Int32)); + // vectors + createCol(shapes, "ScaleX", typeof (Double)); + createCol(shapes, "ScaleY", typeof (Double)); + createCol(shapes, "ScaleZ", typeof (Double)); + // paths + createCol(shapes, "PCode", typeof (Int32)); + createCol(shapes, "PathBegin", typeof (Int32)); + createCol(shapes, "PathEnd", typeof (Int32)); + createCol(shapes, "PathScaleX", typeof (Int32)); + createCol(shapes, "PathScaleY", typeof (Int32)); + createCol(shapes, "PathShearX", typeof (Int32)); + createCol(shapes, "PathShearY", typeof (Int32)); + createCol(shapes, "PathSkew", typeof (Int32)); + createCol(shapes, "PathCurve", typeof (Int32)); + createCol(shapes, "PathRadiusOffset", typeof (Int32)); + createCol(shapes, "PathRevolutions", typeof (Int32)); + createCol(shapes, "PathTaperX", typeof (Int32)); + createCol(shapes, "PathTaperY", typeof (Int32)); + createCol(shapes, "PathTwist", typeof (Int32)); + createCol(shapes, "PathTwistBegin", typeof (Int32)); + // profile + createCol(shapes, "ProfileBegin", typeof (Int32)); + createCol(shapes, "ProfileEnd", typeof (Int32)); + createCol(shapes, "ProfileCurve", typeof (Int32)); + createCol(shapes, "ProfileHollow", typeof (Int32)); + createCol(shapes, "State", typeof(Int32)); + // text TODO: this isn't right, but I'm not sure the right + // way to specify this as a blob atm + createCol(shapes, "Texture", typeof (Byte[])); + createCol(shapes, "ExtraParams", typeof (Byte[])); + + shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; + + return shapes; + } + + /// + /// creates "primitems" table + /// + /// item table DataTable + private static DataTable createItemsTable() + { + DataTable items = new DataTable("primitems"); + + createCol(items, "itemID", typeof (String)); + createCol(items, "primID", typeof (String)); + createCol(items, "assetID", typeof (String)); + createCol(items, "parentFolderID", typeof (String)); + + createCol(items, "invType", typeof (Int32)); + createCol(items, "assetType", typeof (Int32)); + + createCol(items, "name", typeof (String)); + createCol(items, "description", typeof (String)); + + createCol(items, "creationDate", typeof (Int64)); + createCol(items, "creatorID", typeof (String)); + createCol(items, "ownerID", typeof (String)); + createCol(items, "lastOwnerID", typeof (String)); + createCol(items, "groupID", typeof (String)); + + createCol(items, "nextPermissions", typeof (UInt32)); + createCol(items, "currentPermissions", typeof (UInt32)); + createCol(items, "basePermissions", typeof (UInt32)); + createCol(items, "everyonePermissions", typeof (UInt32)); + createCol(items, "groupPermissions", typeof (UInt32)); + createCol(items, "flags", typeof (UInt32)); + + items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] }; + + return items; + } + + /// + /// Creates "land" table + /// + /// land table DataTable + private static DataTable createLandTable() + { + DataTable land = new DataTable("land"); + createCol(land, "UUID", typeof (String)); + createCol(land, "RegionUUID", typeof (String)); + createCol(land, "LocalLandID", typeof (UInt32)); + + // Bitmap is a byte[512] + createCol(land, "Bitmap", typeof (Byte[])); + + createCol(land, "Name", typeof (String)); + createCol(land, "Desc", typeof (String)); + createCol(land, "OwnerUUID", typeof (String)); + createCol(land, "IsGroupOwned", typeof (Boolean)); + createCol(land, "Area", typeof (Int32)); + createCol(land, "AuctionID", typeof (Int32)); //Unemplemented + createCol(land, "Category", typeof (Int32)); //Enum OpenMetaverse.Parcel.ParcelCategory + createCol(land, "ClaimDate", typeof (Int32)); + createCol(land, "ClaimPrice", typeof (Int32)); + createCol(land, "GroupUUID", typeof (string)); + createCol(land, "SalePrice", typeof (Int32)); + createCol(land, "LandStatus", typeof (Int32)); //Enum. OpenMetaverse.Parcel.ParcelStatus + createCol(land, "LandFlags", typeof (UInt32)); + createCol(land, "LandingType", typeof (Byte)); + createCol(land, "MediaAutoScale", typeof (Byte)); + createCol(land, "MediaTextureUUID", typeof (String)); + createCol(land, "MediaURL", typeof (String)); + createCol(land, "MusicURL", typeof (String)); + createCol(land, "PassHours", typeof (Double)); + createCol(land, "PassPrice", typeof (UInt32)); + createCol(land, "SnapshotUUID", typeof (String)); + createCol(land, "UserLocationX", typeof (Double)); + createCol(land, "UserLocationY", typeof (Double)); + createCol(land, "UserLocationZ", typeof (Double)); + createCol(land, "UserLookAtX", typeof (Double)); + createCol(land, "UserLookAtY", typeof (Double)); + createCol(land, "UserLookAtZ", typeof (Double)); + createCol(land, "AuthbuyerID", typeof(String)); + createCol(land, "OtherCleanTime", typeof(Int32)); + createCol(land, "Dwell", typeof(Int32)); + + land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; + + return land; + } + + /// + /// create "landaccesslist" table + /// + /// Landacceslist DataTable + private static DataTable createLandAccessListTable() + { + DataTable landaccess = new DataTable("landaccesslist"); + createCol(landaccess, "LandUUID", typeof (String)); + createCol(landaccess, "AccessUUID", typeof (String)); + createCol(landaccess, "Flags", typeof (UInt32)); + + return landaccess; + } + + private static DataTable createRegionSettingsTable() + { + DataTable regionsettings = new DataTable("regionsettings"); + createCol(regionsettings, "regionUUID", typeof(String)); + createCol(regionsettings, "block_terraform", typeof (Int32)); + createCol(regionsettings, "block_fly", typeof (Int32)); + createCol(regionsettings, "allow_damage", typeof (Int32)); + createCol(regionsettings, "restrict_pushing", typeof (Int32)); + createCol(regionsettings, "allow_land_resell", typeof (Int32)); + createCol(regionsettings, "allow_land_join_divide", typeof (Int32)); + createCol(regionsettings, "block_show_in_search", typeof (Int32)); + createCol(regionsettings, "agent_limit", typeof (Int32)); + createCol(regionsettings, "object_bonus", typeof (Double)); + createCol(regionsettings, "maturity", typeof (Int32)); + createCol(regionsettings, "disable_scripts", typeof (Int32)); + createCol(regionsettings, "disable_collisions", typeof (Int32)); + createCol(regionsettings, "disable_physics", typeof (Int32)); + createCol(regionsettings, "terrain_texture_1", typeof(String)); + createCol(regionsettings, "terrain_texture_2", typeof(String)); + createCol(regionsettings, "terrain_texture_3", typeof(String)); + createCol(regionsettings, "terrain_texture_4", typeof(String)); + createCol(regionsettings, "elevation_1_nw", typeof (Double)); + createCol(regionsettings, "elevation_2_nw", typeof (Double)); + createCol(regionsettings, "elevation_1_ne", typeof (Double)); + createCol(regionsettings, "elevation_2_ne", typeof (Double)); + createCol(regionsettings, "elevation_1_se", typeof (Double)); + createCol(regionsettings, "elevation_2_se", typeof (Double)); + createCol(regionsettings, "elevation_1_sw", typeof (Double)); + createCol(regionsettings, "elevation_2_sw", typeof (Double)); + createCol(regionsettings, "water_height", typeof (Double)); + createCol(regionsettings, "terrain_raise_limit", typeof (Double)); + createCol(regionsettings, "terrain_lower_limit", typeof (Double)); + createCol(regionsettings, "use_estate_sun", typeof (Int32)); + createCol(regionsettings, "sandbox", typeof (Int32)); + createCol(regionsettings, "sunvectorx",typeof (Double)); + createCol(regionsettings, "sunvectory",typeof (Double)); + createCol(regionsettings, "sunvectorz",typeof (Double)); + createCol(regionsettings, "fixed_sun", typeof (Int32)); + createCol(regionsettings, "sun_position", typeof (Double)); + createCol(regionsettings, "covenant", typeof(String)); + regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] }; + return regionsettings; + } + + /*********************************************************************** + * + * Convert between ADO.NET <=> OpenSim Objects + * + * These should be database independant + * + **********************************************************************/ + + /// + /// + /// + /// + /// + private SceneObjectPart buildPrim(DataRow row) + { + // Code commented. Uncomment to test the unit test inline. + + // The unit test mentions this commented code for the purposes + // of debugging a unit test failure + + // SceneObjectGroup sog = new SceneObjectGroup(); + // SceneObjectPart sop = new SceneObjectPart(); + // sop.LocalId = 1; + // sop.Name = "object1"; + // sop.Description = "object1"; + // sop.Text = ""; + // sop.SitName = ""; + // sop.TouchName = ""; + // sop.UUID = UUID.Random(); + // sop.Shape = PrimitiveBaseShape.Default; + // sog.SetRootPart(sop); + // Add breakpoint in above line. Check sop fields. + + // TODO: this doesn't work yet because something more + // interesting has to be done to actually get these values + // back out. Not enough time to figure it out yet. + + SceneObjectPart prim = new SceneObjectPart(); + prim.UUID = new UUID((String) row["UUID"]); + // explicit conversion of integers is required, which sort + // of sucks. No idea if there is a shortcut here or not. + prim.CreationDate = Convert.ToInt32(row["CreationDate"]); + prim.Name = row["Name"] == DBNull.Value ? string.Empty : (string)row["Name"]; + // various text fields + prim.Text = (String) row["Text"]; + prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), + Convert.ToInt32(row["ColorR"]), + Convert.ToInt32(row["ColorG"]), + Convert.ToInt32(row["ColorB"])); + prim.Description = (String) row["Description"]; + prim.SitName = (String) row["SitName"]; + prim.TouchName = (String) row["TouchName"]; + // permissions + prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); + prim.CreatorID = new UUID((String) row["CreatorID"]); + prim.OwnerID = new UUID((String) row["OwnerID"]); + prim.GroupID = new UUID((String) row["GroupID"]); + prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); + prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); + prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); + prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); + prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); + prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); + // vectors + prim.OffsetPosition = new Vector3( + Convert.ToSingle(row["PositionX"]), + Convert.ToSingle(row["PositionY"]), + Convert.ToSingle(row["PositionZ"]) + ); + prim.GroupPosition = new Vector3( + Convert.ToSingle(row["GroupPositionX"]), + Convert.ToSingle(row["GroupPositionY"]), + Convert.ToSingle(row["GroupPositionZ"]) + ); + prim.Velocity = new Vector3( + Convert.ToSingle(row["VelocityX"]), + Convert.ToSingle(row["VelocityY"]), + Convert.ToSingle(row["VelocityZ"]) + ); + prim.AngularVelocity = new Vector3( + Convert.ToSingle(row["AngularVelocityX"]), + Convert.ToSingle(row["AngularVelocityY"]), + Convert.ToSingle(row["AngularVelocityZ"]) + ); + prim.Acceleration = new Vector3( + Convert.ToSingle(row["AccelerationX"]), + Convert.ToSingle(row["AccelerationY"]), + Convert.ToSingle(row["AccelerationZ"]) + ); + // quaternions + prim.RotationOffset = new Quaternion( + Convert.ToSingle(row["RotationX"]), + Convert.ToSingle(row["RotationY"]), + Convert.ToSingle(row["RotationZ"]), + Convert.ToSingle(row["RotationW"]) + ); + + prim.SitTargetPositionLL = new Vector3( + Convert.ToSingle(row["SitTargetOffsetX"]), + Convert.ToSingle(row["SitTargetOffsetY"]), + Convert.ToSingle(row["SitTargetOffsetZ"])); + prim.SitTargetOrientationLL = new Quaternion( + Convert.ToSingle( + row["SitTargetOrientX"]), + Convert.ToSingle( + row["SitTargetOrientY"]), + Convert.ToSingle( + row["SitTargetOrientZ"]), + Convert.ToSingle( + row["SitTargetOrientW"])); + + prim.ClickAction = Convert.ToByte(row["ClickAction"]); + prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); + prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); + prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); + prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); + prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); + + prim.Sound = new UUID(row["LoopedSound"].ToString()); + prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); + prim.SoundFlags = 1; // If it's persisted at all, it's looped + + if (!row.IsNull("TextureAnimation")) + prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString()); + if (!row.IsNull("ParticleSystem")) + prim.ParticleSystem = Convert.FromBase64String(row["ParticleSystem"].ToString()); + + prim.AngularVelocity = new Vector3( + Convert.ToSingle(row["OmegaX"]), + Convert.ToSingle(row["OmegaY"]), + Convert.ToSingle(row["OmegaZ"]) + ); + + prim.SetCameraEyeOffset(new Vector3( + Convert.ToSingle(row["CameraEyeOffsetX"]), + Convert.ToSingle(row["CameraEyeOffsetY"]), + Convert.ToSingle(row["CameraEyeOffsetZ"]) + )); + + prim.SetCameraAtOffset(new Vector3( + Convert.ToSingle(row["CameraAtOffsetX"]), + Convert.ToSingle(row["CameraAtOffsetY"]), + Convert.ToSingle(row["CameraAtOffsetZ"]) + )); + + if (Convert.ToInt16(row["ForceMouselook"]) != 0) + prim.SetForceMouselook(true); + + prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); + + if (Convert.ToInt16(row["AllowedDrop"]) != 0) + prim.AllowedDrop = true; + + if (Convert.ToInt16(row["DieAtEdge"]) != 0) + prim.DIE_AT_EDGE = true; + + prim.SalePrice = Convert.ToInt32(row["SalePrice"]); + prim.ObjectSaleType = Convert.ToByte(row["SaleType"]); + + prim.Material = Convert.ToByte(row["Material"]); + + prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); + prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); + + if (Convert.ToInt16(row["VolumeDetect"]) != 0) + prim.VolumeDetectActive = true; + + return prim; + } + + /// + /// Build a prim inventory item from the persisted data. + /// + /// + /// + private static TaskInventoryItem buildItem(DataRow row) + { + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = new UUID((String)row["itemID"]); + taskItem.ParentPartID = new UUID((String)row["primID"]); + taskItem.AssetID = new UUID((String)row["assetID"]); + taskItem.ParentID = new UUID((String)row["parentFolderID"]); + + taskItem.InvType = Convert.ToInt32(row["invType"]); + taskItem.Type = Convert.ToInt32(row["assetType"]); + + taskItem.Name = (String)row["name"]; + taskItem.Description = (String)row["description"]; + taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); + taskItem.CreatorID = new UUID((String)row["creatorID"]); + taskItem.OwnerID = new UUID((String)row["ownerID"]); + taskItem.LastOwnerID = new UUID((String)row["lastOwnerID"]); + taskItem.GroupID = new UUID((String)row["groupID"]); + + taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); + taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); + taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); + taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); + taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); + taskItem.Flags = Convert.ToUInt32(row["flags"]); + + return taskItem; + } + + /// + /// Build a Land Data from the persisted data. + /// + /// + /// + private LandData buildLandData(DataRow row) + { + LandData newData = new LandData(); + + newData.GlobalID = new UUID((String) row["UUID"]); + newData.LocalID = Convert.ToInt32(row["LocalLandID"]); + + // Bitmap is a byte[512] + newData.Bitmap = (Byte[]) row["Bitmap"]; + + newData.Name = (String) row["Name"]; + newData.Description = (String) row["Desc"]; + newData.OwnerID = (UUID)(String) row["OwnerUUID"]; + newData.IsGroupOwned = (Boolean) row["IsGroupOwned"]; + newData.Area = Convert.ToInt32(row["Area"]); + newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented + newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]); + //Enum OpenMetaverse.Parcel.ParcelCategory + newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); + newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); + newData.GroupID = new UUID((String) row["GroupUUID"]); + newData.SalePrice = Convert.ToInt32(row["SalePrice"]); + newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]); + //Enum. OpenMetaverse.Parcel.ParcelStatus + newData.Flags = Convert.ToUInt32(row["LandFlags"]); + newData.LandingType = (Byte) row["LandingType"]; + newData.MediaAutoScale = (Byte) row["MediaAutoScale"]; + newData.MediaID = new UUID((String) row["MediaTextureUUID"]); + newData.MediaURL = (String) row["MediaURL"]; + newData.MusicURL = (String) row["MusicURL"]; + newData.PassHours = Convert.ToSingle(row["PassHours"]); + newData.PassPrice = Convert.ToInt32(row["PassPrice"]); + newData.SnapshotID = (UUID)(String) row["SnapshotUUID"]; + try + { + + newData.UserLocation = + new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), + Convert.ToSingle(row["UserLocationZ"])); + newData.UserLookAt = + new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), + Convert.ToSingle(row["UserLookAtZ"])); + + } + catch (InvalidCastException) + { + m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); + newData.UserLocation = Vector3.Zero; + newData.UserLookAt = Vector3.Zero; + } + newData.ParcelAccessList = new List(); + UUID authBuyerID = UUID.Zero; + + UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID); + + newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); + newData.Dwell = Convert.ToInt32(row["Dwell"]); + + return newData; + } + + private RegionSettings buildRegionSettings(DataRow row) + { + RegionSettings newSettings = new RegionSettings(); + + newSettings.RegionUUID = new UUID((string) row["regionUUID"]); + newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); + newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); + newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); + newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); + newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); + newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); + newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); + newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); + newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); + newSettings.Maturity = Convert.ToInt32(row["maturity"]); + newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); + newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); + newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); + newSettings.TerrainTexture1 = new UUID((String) row["terrain_texture_1"]); + newSettings.TerrainTexture2 = new UUID((String) row["terrain_texture_2"]); + newSettings.TerrainTexture3 = new UUID((String) row["terrain_texture_3"]); + newSettings.TerrainTexture4 = new UUID((String) row["terrain_texture_4"]); + newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); + newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); + newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); + newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); + newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); + newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); + newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); + newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); + newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); + newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); + newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); + newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); + newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); + newSettings.SunVector = new Vector3 ( + Convert.ToSingle(row["sunvectorx"]), + Convert.ToSingle(row["sunvectory"]), + Convert.ToSingle(row["sunvectorz"]) + ); + newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); + newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); + newSettings.Covenant = new UUID((String) row["covenant"]); + + return newSettings; + } + + /// + /// Build a land access entry from the persisted data. + /// + /// + /// + private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = new UUID((string) row["AccessUUID"]); + entry.Flags = (AccessList) row["Flags"]; + entry.Time = new DateTime(); + return entry; + } + + /// + /// + /// + /// + /// + private static Array serializeTerrain(double[,] val) + { + MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); + BinaryWriter bw = new BinaryWriter(str); + + // TODO: COMPATIBILITY - Add byte-order conversions + for (int x = 0; x < (int)Constants.RegionSize; x++) + for (int y = 0; y < (int)Constants.RegionSize; y++) + bw.Write(val[x, y]); + + return str.ToArray(); + } + +// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val) +// { +// row["RegionUUID"] = regionUUID; +// row["Revision"] = rev; + + // MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double)); +// BinaryWriter bw = new BinaryWriter(str); + +// // TODO: COMPATIBILITY - Add byte-order conversions + // for (int x = 0; x < (int)Constants.RegionSize; x++) + // for (int y = 0; y < (int)Constants.RegionSize; y++) +// bw.Write(val[x, y]); + +// row["Heightfield"] = str.ToArray(); +// } + + /// + /// + /// + /// + /// + /// + /// + private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + row["UUID"] = prim.UUID.ToString(); + row["RegionUUID"] = regionUUID.ToString(); + row["CreationDate"] = prim.CreationDate; + row["Name"] = prim.Name; + row["SceneGroupID"] = sceneGroupID.ToString(); + // the UUID of the root part for this SceneObjectGroup + // various text fields + row["Text"] = prim.Text; + row["Description"] = prim.Description; + row["SitName"] = prim.SitName; + row["TouchName"] = prim.TouchName; + // permissions + row["ObjectFlags"] = prim.ObjectFlags; + row["CreatorID"] = prim.CreatorID.ToString(); + row["OwnerID"] = prim.OwnerID.ToString(); + row["GroupID"] = prim.GroupID.ToString(); + row["LastOwnerID"] = prim.LastOwnerID.ToString(); + row["OwnerMask"] = prim.OwnerMask; + row["NextOwnerMask"] = prim.NextOwnerMask; + row["GroupMask"] = prim.GroupMask; + row["EveryoneMask"] = prim.EveryoneMask; + row["BaseMask"] = prim.BaseMask; + // vectors + row["PositionX"] = prim.OffsetPosition.X; + row["PositionY"] = prim.OffsetPosition.Y; + row["PositionZ"] = prim.OffsetPosition.Z; + row["GroupPositionX"] = prim.GroupPosition.X; + row["GroupPositionY"] = prim.GroupPosition.Y; + row["GroupPositionZ"] = prim.GroupPosition.Z; + row["VelocityX"] = prim.Velocity.X; + row["VelocityY"] = prim.Velocity.Y; + row["VelocityZ"] = prim.Velocity.Z; + row["AngularVelocityX"] = prim.AngularVelocity.X; + row["AngularVelocityY"] = prim.AngularVelocity.Y; + row["AngularVelocityZ"] = prim.AngularVelocity.Z; + row["AccelerationX"] = prim.Acceleration.X; + row["AccelerationY"] = prim.Acceleration.Y; + row["AccelerationZ"] = prim.Acceleration.Z; + // quaternions + row["RotationX"] = prim.RotationOffset.X; + row["RotationY"] = prim.RotationOffset.Y; + row["RotationZ"] = prim.RotationOffset.Z; + row["RotationW"] = prim.RotationOffset.W; + + // Sit target + Vector3 sitTargetPos = prim.SitTargetPositionLL; + row["SitTargetOffsetX"] = sitTargetPos.X; + row["SitTargetOffsetY"] = sitTargetPos.Y; + row["SitTargetOffsetZ"] = sitTargetPos.Z; + + Quaternion sitTargetOrient = prim.SitTargetOrientationLL; + row["SitTargetOrientW"] = sitTargetOrient.W; + row["SitTargetOrientX"] = sitTargetOrient.X; + row["SitTargetOrientY"] = sitTargetOrient.Y; + row["SitTargetOrientZ"] = sitTargetOrient.Z; + row["ColorR"] = Convert.ToInt32(prim.Color.R); + row["ColorG"] = Convert.ToInt32(prim.Color.G); + row["ColorB"] = Convert.ToInt32(prim.Color.B); + row["ColorA"] = Convert.ToInt32(prim.Color.A); + row["PayPrice"] = prim.PayPrice[0]; + row["PayButton1"] = prim.PayPrice[1]; + row["PayButton2"] = prim.PayPrice[2]; + row["PayButton3"] = prim.PayPrice[3]; + row["PayButton4"] = prim.PayPrice[4]; + + + row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation); + row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem); + + row["OmegaX"] = prim.AngularVelocity.X; + row["OmegaY"] = prim.AngularVelocity.Y; + row["OmegaZ"] = prim.AngularVelocity.Z; + + row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X; + row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y; + row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z; + + row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X; + row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y; + row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z; + + + if ((prim.SoundFlags & 1) != 0) // Looped + { + row["LoopedSound"] = prim.Sound.ToString(); + row["LoopedSoundGain"] = prim.SoundGain; + } + else + { + row["LoopedSound"] = UUID.Zero.ToString(); + row["LoopedSoundGain"] = 0.0f; + } + + if (prim.GetForceMouselook()) + row["ForceMouselook"] = 1; + else + row["ForceMouselook"] = 0; + + row["ScriptAccessPin"] = prim.ScriptAccessPin; + + if (prim.AllowedDrop) + row["AllowedDrop"] = 1; + else + row["AllowedDrop"] = 0; + + if (prim.DIE_AT_EDGE) + row["DieAtEdge"] = 1; + else + row["DieAtEdge"] = 0; + + row["SalePrice"] = prim.SalePrice; + row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType); + + // click action + row["ClickAction"] = prim.ClickAction; + + row["SalePrice"] = prim.SalePrice; + row["Material"] = prim.Material; + + row["CollisionSound"] = prim.CollisionSound.ToString(); + row["CollisionSoundVolume"] = prim.CollisionSoundVolume; + if (prim.VolumeDetectActive) + row["VolumeDetect"] = 1; + else + row["VolumeDetect"] = 0; + + } + + /// + /// + /// + /// + /// + private static void fillItemRow(DataRow row, TaskInventoryItem taskItem) + { + row["itemID"] = taskItem.ItemID.ToString(); + row["primID"] = taskItem.ParentPartID.ToString(); + row["assetID"] = taskItem.AssetID.ToString(); + row["parentFolderID"] = taskItem.ParentID.ToString(); + + row["invType"] = taskItem.InvType; + row["assetType"] = taskItem.Type; + + row["name"] = taskItem.Name; + row["description"] = taskItem.Description; + row["creationDate"] = taskItem.CreationDate; + row["creatorID"] = taskItem.CreatorID.ToString(); + row["ownerID"] = taskItem.OwnerID.ToString(); + row["lastOwnerID"] = taskItem.LastOwnerID.ToString(); + row["groupID"] = taskItem.GroupID.ToString(); + row["nextPermissions"] = taskItem.NextPermissions; + row["currentPermissions"] = taskItem.CurrentPermissions; + row["basePermissions"] = taskItem.BasePermissions; + row["everyonePermissions"] = taskItem.EveryonePermissions; + row["groupPermissions"] = taskItem.GroupPermissions; + row["flags"] = taskItem.Flags; + } + + /// + /// + /// + /// + /// + /// + private static void fillLandRow(DataRow row, LandData land, UUID regionUUID) + { + row["UUID"] = land.GlobalID.ToString(); + row["RegionUUID"] = regionUUID.ToString(); + row["LocalLandID"] = land.LocalID; + + // Bitmap is a byte[512] + row["Bitmap"] = land.Bitmap; + + row["Name"] = land.Name; + row["Desc"] = land.Description; + row["OwnerUUID"] = land.OwnerID.ToString(); + row["IsGroupOwned"] = land.IsGroupOwned; + row["Area"] = land.Area; + row["AuctionID"] = land.AuctionID; //Unemplemented + row["Category"] = land.Category; //Enum OpenMetaverse.Parcel.ParcelCategory + row["ClaimDate"] = land.ClaimDate; + row["ClaimPrice"] = land.ClaimPrice; + row["GroupUUID"] = land.GroupID.ToString(); + row["SalePrice"] = land.SalePrice; + row["LandStatus"] = land.Status; //Enum. OpenMetaverse.Parcel.ParcelStatus + row["LandFlags"] = land.Flags; + row["LandingType"] = land.LandingType; + row["MediaAutoScale"] = land.MediaAutoScale; + row["MediaTextureUUID"] = land.MediaID.ToString(); + row["MediaURL"] = land.MediaURL; + row["MusicURL"] = land.MusicURL; + row["PassHours"] = land.PassHours; + row["PassPrice"] = land.PassPrice; + row["SnapshotUUID"] = land.SnapshotID.ToString(); + row["UserLocationX"] = land.UserLocation.X; + row["UserLocationY"] = land.UserLocation.Y; + row["UserLocationZ"] = land.UserLocation.Z; + row["UserLookAtX"] = land.UserLookAt.X; + row["UserLookAtY"] = land.UserLookAt.Y; + row["UserLookAtZ"] = land.UserLookAt.Z; + row["AuthbuyerID"] = land.AuthBuyerID.ToString(); + row["OtherCleanTime"] = land.OtherCleanTime; + row["Dwell"] = land.Dwell; + } + + /// + /// + /// + /// + /// + /// + private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID) + { + row["LandUUID"] = parcelID.ToString(); + row["AccessUUID"] = entry.AgentID.ToString(); + row["Flags"] = entry.Flags; + } + + private static void fillRegionSettingsRow(DataRow row, RegionSettings settings) + { + row["regionUUID"] = settings.RegionUUID.ToString(); + row["block_terraform"] = settings.BlockTerraform; + row["block_fly"] = settings.BlockFly; + row["allow_damage"] = settings.AllowDamage; + row["restrict_pushing"] = settings.RestrictPushing; + row["allow_land_resell"] = settings.AllowLandResell; + row["allow_land_join_divide"] = settings.AllowLandJoinDivide; + row["block_show_in_search"] = settings.BlockShowInSearch; + row["agent_limit"] = settings.AgentLimit; + row["object_bonus"] = settings.ObjectBonus; + row["maturity"] = settings.Maturity; + row["disable_scripts"] = settings.DisableScripts; + row["disable_collisions"] = settings.DisableCollisions; + row["disable_physics"] = settings.DisablePhysics; + row["terrain_texture_1"] = settings.TerrainTexture1.ToString(); + row["terrain_texture_2"] = settings.TerrainTexture2.ToString(); + row["terrain_texture_3"] = settings.TerrainTexture3.ToString(); + row["terrain_texture_4"] = settings.TerrainTexture4.ToString(); + row["elevation_1_nw"] = settings.Elevation1NW; + row["elevation_2_nw"] = settings.Elevation2NW; + row["elevation_1_ne"] = settings.Elevation1NE; + row["elevation_2_ne"] = settings.Elevation2NE; + row["elevation_1_se"] = settings.Elevation1SE; + row["elevation_2_se"] = settings.Elevation2SE; + row["elevation_1_sw"] = settings.Elevation1SW; + row["elevation_2_sw"] = settings.Elevation2SW; + row["water_height"] = settings.WaterHeight; + row["terrain_raise_limit"] = settings.TerrainRaiseLimit; + row["terrain_lower_limit"] = settings.TerrainLowerLimit; + row["use_estate_sun"] = settings.UseEstateSun; + row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox + row["sunvectorx"] = settings.SunVector.X; + row["sunvectory"] = settings.SunVector.Y; + row["sunvectorz"] = settings.SunVector.Z; + row["fixed_sun"] = settings.FixedSun; + row["sun_position"] = settings.SunPosition; + row["covenant"] = settings.Covenant.ToString(); + } + + /// + /// + /// + /// + /// + private PrimitiveBaseShape buildShape(DataRow row) + { + PrimitiveBaseShape s = new PrimitiveBaseShape(); + s.Scale = new Vector3( + Convert.ToSingle(row["ScaleX"]), + Convert.ToSingle(row["ScaleY"]), + Convert.ToSingle(row["ScaleZ"]) + ); + // paths + s.PCode = Convert.ToByte(row["PCode"]); + s.PathBegin = Convert.ToUInt16(row["PathBegin"]); + s.PathEnd = Convert.ToUInt16(row["PathEnd"]); + s.PathScaleX = Convert.ToByte(row["PathScaleX"]); + s.PathScaleY = Convert.ToByte(row["PathScaleY"]); + s.PathShearX = Convert.ToByte(row["PathShearX"]); + s.PathShearY = Convert.ToByte(row["PathShearY"]); + s.PathSkew = Convert.ToSByte(row["PathSkew"]); + s.PathCurve = Convert.ToByte(row["PathCurve"]); + s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); + s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); + s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); + s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); + s.PathTwist = Convert.ToSByte(row["PathTwist"]); + s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); + // profile + s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); + s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); + s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); + s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); + s.State = Convert.ToByte(row["State"]); + + byte[] textureEntry = (byte[])row["Texture"]; + s.TextureEntry = textureEntry; + + s.ExtraParams = (byte[]) row["ExtraParams"]; + return s; + } + + /// + /// + /// + /// + /// + private static void fillShapeRow(DataRow row, SceneObjectPart prim) + { + PrimitiveBaseShape s = prim.Shape; + row["UUID"] = prim.UUID.ToString(); + // shape is an enum + row["Shape"] = 0; + // vectors + row["ScaleX"] = s.Scale.X; + row["ScaleY"] = s.Scale.Y; + row["ScaleZ"] = s.Scale.Z; + // paths + row["PCode"] = s.PCode; + row["PathBegin"] = s.PathBegin; + row["PathEnd"] = s.PathEnd; + row["PathScaleX"] = s.PathScaleX; + row["PathScaleY"] = s.PathScaleY; + row["PathShearX"] = s.PathShearX; + row["PathShearY"] = s.PathShearY; + row["PathSkew"] = s.PathSkew; + row["PathCurve"] = s.PathCurve; + row["PathRadiusOffset"] = s.PathRadiusOffset; + row["PathRevolutions"] = s.PathRevolutions; + row["PathTaperX"] = s.PathTaperX; + row["PathTaperY"] = s.PathTaperY; + row["PathTwist"] = s.PathTwist; + row["PathTwistBegin"] = s.PathTwistBegin; + // profile + row["ProfileBegin"] = s.ProfileBegin; + row["ProfileEnd"] = s.ProfileEnd; + row["ProfileCurve"] = s.ProfileCurve; + row["ProfileHollow"] = s.ProfileHollow; + row["State"] = s.State; + + row["Texture"] = s.TextureEntry; + row["ExtraParams"] = s.ExtraParams; + } + + /// + /// + /// + /// + /// + /// + private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) + { + + DataTable prims = ds.Tables["prims"]; + DataTable shapes = ds.Tables["primshapes"]; + + DataRow primRow = prims.Rows.Find(prim.UUID.ToString()); + if (primRow == null) + { + primRow = prims.NewRow(); + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + prims.Rows.Add(primRow); + } + else + { + fillPrimRow(primRow, prim, sceneGroupID, regionUUID); + } + + DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); + if (shapeRow == null) + { + shapeRow = shapes.NewRow(); + fillShapeRow(shapeRow, prim); + shapes.Rows.Add(shapeRow); + } + else + { + fillShapeRow(shapeRow, prim); + } + } + + /// + /// see IRegionDatastore + /// + /// + /// + public void StorePrimInventory(UUID primID, ICollection items) + { + m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); + + DataTable dbItems = ds.Tables["primitems"]; + + // For now, we're just going to crudely remove all the previous inventory items + // no matter whether they have changed or not, and replace them with the current set. + lock (ds) + { + RemoveItems(primID); + + // repalce with current inventory details + foreach (TaskInventoryItem newItem in items) + { +// m_log.InfoFormat( +// "[DATASTORE]: ", +// "Adding item {0}, {1} to prim ID {2}", +// newItem.Name, newItem.ItemID, newItem.ParentPartID); + + DataRow newItemRow = dbItems.NewRow(); + fillItemRow(newItemRow, newItem); + dbItems.Rows.Add(newItemRow); + } + } + + Commit(); + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + /// + /// Create an insert command + /// + /// table name + /// data table + /// the created command + /// + /// This is subtle enough to deserve some commentary. + /// Instead of doing *lots* and *lots of hardcoded strings + /// for database definitions we'll use the fact that + /// realistically all insert statements look like "insert + /// into A(b, c) values(:b, :c) on the parameterized query + /// front. If we just have a list of b, c, etc... we can + /// generate these strings instead of typing them out. + /// + private static SqliteCommand createInsertCommand(string table, DataTable dt) + { + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (:"; + sql += String.Join(", :", cols); + sql += ")"; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + private static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + private static SqliteCommand createUpdateCommand(string table, string pk1, string pk2, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk1 + " and " + pk2; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// + /// + /// Data Table + /// + // private static string defineTable(DataTable dt) + // { + // string sql = "create table " + dt.TableName + "("; + // string subsql = String.Empty; + // foreach (DataColumn col in dt.Columns) + // { + // if (subsql.Length > 0) + // { + // // a map function would rock so much here + // subsql += ",\n"; + // } + // subsql += col.ColumnName + " " + sqliteType(col.DataType); + // if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) + // { + // subsql += " primary key"; + // } + // } + // sql += subsql; + // sql += ")"; + // return sql; + // } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining SqliteParameters to 2 parameters: + /// column name and database type. + /// + /// It assumes certain conventions like :param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + ///a built sqlite parameter + private static SqliteParameter createSqliteParameter(string name, Type type) + { + SqliteParameter param = new SqliteParameter(); + param.ParameterName = ":" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + /// + /// + /// + /// + /// + private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /// + /// + /// + /// + /// + private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID"); + delete.Parameters.Add(createSqliteParameter("itemID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /// + /// + /// + /// + /// + private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); + da.InsertCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("land", ds.Tables["land"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from land where UUID=:UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); + da.DeleteCommand = delete; + da.DeleteCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("landaccesslist", "LandUUID=:landUUID", "AccessUUID=:AccessUUID", ds.Tables["landaccesslist"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from landaccesslist where LandUUID= :LandUUID and AccessUUID= :AccessUUID"); + delete.Parameters.Add(createSqliteParameter("LandUUID", typeof(String))); + delete.Parameters.Add(createSqliteParameter("AccessUUID", typeof(String))); + da.DeleteCommand = delete; + da.DeleteCommand.Connection = conn; + + } + + private void setupRegionSettingsCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("regionsettings", ds.Tables["regionsettings"]); + da.InsertCommand.Connection = conn; + da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID=:regionUUID", ds.Tables["regionsettings"]); + da.UpdateCommand.Connection = conn; + } + + /// + /// + /// + /// + /// + private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) + { + da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); + da.InsertCommand.Connection = conn; + + da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); + da.UpdateCommand.Connection = conn; + + SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); + delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); + delete.Connection = conn; + da.DeleteCommand = delete; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + /// + /// Type conversion function + /// + /// + /// + private static DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte)) + { + return DbType.Byte; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs new file mode 100644 index 0000000..27553c6 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs @@ -0,0 +1,81 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using OpenMetaverse; +using OpenSim.Framework; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLiteLegacy +{ + public class SQLiteUserAccountData : SQLiteGenericTableHandler, IUserAccountData + { + public SQLiteUserAccountData(string connectionString, string realm) + : base(connectionString, realm, "UserAccount") + { + } + + public UserAccountData[] GetUsers(UUID scopeID, string query) + { + string[] words = query.Split(new char[] {' '}); + + for (int i = 0 ; i < words.Length ; i++) + { + if (words[i].Length < 3) + { + if (i != words.Length - 1) + Array.Copy(words, i + 1, words, i, words.Length - i - 1); + Array.Resize(ref words, words.Length - 1); + } + } + + if (words.Length == 0) + return new UserAccountData[0]; + + if (words.Length > 2) + return new UserAccountData[0]; + + SqliteCommand cmd = new SqliteCommand(); + + if (words.Length == 1) + { + cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", + m_Realm, scopeID.ToString(), words[0]); + } + else + { + cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{3}%')", + m_Realm, scopeID.ToString(), words[0], words[1]); + } + + return DoQuery(cmd); + } + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteUtils.cs b/OpenSim/Data/SQLiteLegacy/SQLiteUtils.cs new file mode 100644 index 0000000..095a262 --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteUtils.cs @@ -0,0 +1,307 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Data; +using Mono.Data.SqliteClient; + +namespace OpenSim.Data.SQLiteLegacy +{ + /// + /// A base class for methods needed by all SQLite database classes + /// + public class SQLiteUtil + { + /*********************************************************************** + * + * Database Definition Helper Functions + * + * This should be db agnostic as we define them in ADO.NET terms + * + **********************************************************************/ + + /// + /// + /// + /// + /// + /// + public static void createCol(DataTable dt, string name, Type type) + { + DataColumn col = new DataColumn(name, type); + dt.Columns.Add(col); + } + + /*********************************************************************** + * + * SQL Statement Creation Functions + * + * These functions create SQL statements for update, insert, and create. + * They can probably be factored later to have a db independant + * portion and a db specific portion + * + **********************************************************************/ + + /// + /// Create an insert command + /// + /// table name + /// data table + /// the created command + /// + /// This is subtle enough to deserve some commentary. + /// Instead of doing *lots* and *lots of hardcoded strings + /// for database definitions we'll use the fact that + /// realistically all insert statements look like "insert + /// into A(b, c) values(:b, :c) on the parameterized query + /// front. If we just have a list of b, c, etc... we can + /// generate these strings instead of typing them out. + /// + public static SqliteCommand createInsertCommand(string table, DataTable dt) + { + + string[] cols = new string[dt.Columns.Count]; + for (int i = 0; i < dt.Columns.Count; i++) + { + DataColumn col = dt.Columns[i]; + cols[i] = col.ColumnName; + } + + string sql = "insert into " + table + "("; + sql += String.Join(", ", cols); + // important, the first ':' needs to be here, the rest get added in the join + sql += ") values (:"; + sql += String.Join(", :", cols); + sql += ")"; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// create an update command + /// + /// table name + /// + /// + /// the created command + public static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) + { + string sql = "update " + table + " set "; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ", "; + } + subsql += col.ColumnName + "= :" + col.ColumnName; + } + sql += subsql; + sql += " where " + pk; + SqliteCommand cmd = new SqliteCommand(sql); + + // this provides the binding for all our parameters, so + // much less code than it used to be + + foreach (DataColumn col in dt.Columns) + { + cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); + } + return cmd; + } + + /// + /// + /// + /// Data Table + /// + public static string defineTable(DataTable dt) + { + string sql = "create table " + dt.TableName + "("; + string subsql = String.Empty; + foreach (DataColumn col in dt.Columns) + { + if (subsql.Length > 0) + { + // a map function would rock so much here + subsql += ",\n"; + } + subsql += col.ColumnName + " " + sqliteType(col.DataType); + if (dt.PrimaryKey.Length > 0) + { + if (col == dt.PrimaryKey[0]) + { + subsql += " primary key"; + } + } + } + sql += subsql; + sql += ")"; + return sql; + } + + /*********************************************************************** + * + * Database Binding functions + * + * These will be db specific due to typing, and minor differences + * in databases. + * + **********************************************************************/ + + /// + /// + /// This is a convenience function that collapses 5 repetitive + /// lines for defining SqliteParameters to 2 parameters: + /// column name and database type. + /// + /// + /// + /// It assumes certain conventions like :param as the param + /// name to replace in parametrized queries, and that source + /// version is always current version, both of which are fine + /// for us. + /// + /// + /// + /// + ///a built sqlite parameter + public static SqliteParameter createSqliteParameter(string name, Type type) + { + SqliteParameter param = new SqliteParameter(); + param.ParameterName = ":" + name; + param.DbType = dbtypeFromType(type); + param.SourceColumn = name; + param.SourceVersion = DataRowVersion.Current; + return param; + } + + /*********************************************************************** + * + * Type conversion functions + * + **********************************************************************/ + + /// + /// Type conversion function + /// + /// a type + /// a DbType + public static DbType dbtypeFromType(Type type) + { + if (type == typeof (String)) + { + return DbType.String; + } + else if (type == typeof (Int32)) + { + return DbType.Int32; + } + else if (type == typeof (UInt32)) + { + return DbType.UInt32; + } + else if (type == typeof (Int64)) + { + return DbType.Int64; + } + else if (type == typeof (UInt64)) + { + return DbType.UInt64; + } + else if (type == typeof (Double)) + { + return DbType.Double; + } + else if (type == typeof (Boolean)) + { + return DbType.Boolean; + } + else if (type == typeof (Byte[])) + { + return DbType.Binary; + } + else + { + return DbType.String; + } + } + + /// + /// + /// a Type + /// a string + /// this is something we'll need to implement for each db slightly differently. + public static string sqliteType(Type type) + { + if (type == typeof (String)) + { + return "varchar(255)"; + } + else if (type == typeof (Int32)) + { + return "integer"; + } + else if (type == typeof (UInt32)) + { + return "integer"; + } + else if (type == typeof (Int64)) + { + return "varchar(255)"; + } + else if (type == typeof (UInt64)) + { + return "varchar(255)"; + } + else if (type == typeof (Double)) + { + return "float"; + } + else if (type == typeof (Boolean)) + { + return "integer"; + } + else if (type == typeof (Byte[])) + { + return "blob"; + } + else + { + return "string"; + } + } + } +} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteXInventoryData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteXInventoryData.cs new file mode 100644 index 0000000..5422cbf --- /dev/null +++ b/OpenSim/Data/SQLiteLegacy/SQLiteXInventoryData.cs @@ -0,0 +1,155 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Data; +using System.Reflection; +using System.Collections.Generic; +using Mono.Data.SqliteClient; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data.SQLiteLegacy +{ + /// + /// A MySQL Interface for the Asset Server + /// + public class SQLiteXInventoryData : IXInventoryData + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private SQLiteGenericTableHandler m_Folders; + private SqliteItemHandler m_Items; + + public SQLiteXInventoryData(string conn, string realm) + { + m_Folders = new SQLiteGenericTableHandler( + conn, "inventoryfolders", "InventoryStore"); + m_Items = new SqliteItemHandler( + conn, "inventoryitems", String.Empty); + } + + public XInventoryFolder[] GetFolders(string[] fields, string[] vals) + { + return m_Folders.Get(fields, vals); + } + + public XInventoryItem[] GetItems(string[] fields, string[] vals) + { + return m_Items.Get(fields, vals); + } + + public bool StoreFolder(XInventoryFolder folder) + { + return m_Folders.Store(folder); + } + + public bool StoreItem(XInventoryItem item) + { + return m_Items.Store(item); + } + + public bool DeleteFolders(string field, string val) + { + return m_Folders.Delete(field, val); + } + + public bool DeleteItems(string field, string val) + { + return m_Items.Delete(field, val); + } + + public bool MoveItem(string id, string newParent) + { + return m_Items.MoveItem(id, newParent); + } + + public XInventoryItem[] GetActiveGestures(UUID principalID) + { + return m_Items.GetActiveGestures(principalID); + } + + public int GetAssetPermissions(UUID principalID, UUID assetID) + { + return m_Items.GetAssetPermissions(principalID, assetID); + } + } + + public class SqliteItemHandler : SQLiteGenericTableHandler + { + public SqliteItemHandler(string c, string t, string m) : + base(c, t, m) + { + } + + public bool MoveItem(string id, string newParent) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("update {0} set parentFolderID = :ParentFolderID where inventoryID = :InventoryID", m_Realm); + cmd.Parameters.Add(new SqliteParameter(":ParentFolderID", newParent)); + cmd.Parameters.Add(new SqliteParameter(":InventoryID", id)); + + return ExecuteNonQuery(cmd, m_Connection) == 0 ? false : true; + } + + public XInventoryItem[] GetActiveGestures(UUID principalID) + { + SqliteCommand cmd = new SqliteCommand(); + cmd.CommandText = String.Format("select * from inventoryitems where avatarId = :uuid and assetType = :type and flags = 1", m_Realm); + + cmd.Parameters.Add(new SqliteParameter(":uuid", principalID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":type", (int)AssetType.Gesture)); + + return DoQuery(cmd); + } + + public int GetAssetPermissions(UUID principalID, UUID assetID) + { + SqliteCommand cmd = new SqliteCommand(); + + cmd.CommandText = String.Format("select inventoryCurrentPermissions from inventoryitems where avatarID = :PrincipalID and assetID = :AssetID", m_Realm); + cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); + cmd.Parameters.Add(new SqliteParameter(":AssetID", assetID.ToString())); + + IDataReader reader = ExecuteReader(cmd, m_Connection); + + int perms = 0; + + while (reader.Read()) + { + perms |= Convert.ToInt32(reader["inventoryCurrentPermissions"]); + } + + reader.Close(); + CloseCommand(cmd); + + return perms; + } + } +} diff --git a/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs b/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs deleted file mode 100644 index 4aeb67b..0000000 --- a/OpenSim/Data/SQLiteNG/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Reflection; -using System.Runtime.InteropServices; - -// General information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly : AssemblyTitle("OpenSim.Data.SQLiteNG")] -[assembly : AssemblyDescription("")] -[assembly : AssemblyConfiguration("")] -[assembly : AssemblyCompany("http://opensimulator.org")] -[assembly : AssemblyProduct("OpenSim.Data.SQLiteNG")] -[assembly : AssemblyCopyright("Copyright (c) OpenSimulator.org Developers 2007-2009")] -[assembly : AssemblyTrademark("")] -[assembly : AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly : ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly : Guid("6113d5ce-4547-49f4-9236-0dcc503457b1")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Revision and Build Numbers -// by using the '*' as shown below: - -[assembly : AssemblyVersion("0.6.5.*")] -[assembly : AssemblyFileVersion("0.6.5.0")] diff --git a/OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql deleted file mode 100644 index 2e026ca..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/001_AssetStore.sql +++ /dev/null @@ -1,12 +0,0 @@ -BEGIN TRANSACTION; -CREATE TABLE assets( - UUID varchar(255) primary key, - Name varchar(255), - Description varchar(255), - Type integer, - InvType integer, - Local integer, - Temporary integer, - Data blob); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql deleted file mode 100644 index 468567d..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/001_AuthStore.sql +++ /dev/null @@ -1,18 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE auth ( - UUID char(36) NOT NULL, - passwordHash char(32) NOT NULL default '', - passwordSalt char(32) NOT NULL default '', - webLoginKey varchar(255) NOT NULL default '', - accountType VARCHAR(32) NOT NULL DEFAULT 'UserAccount', - PRIMARY KEY (`UUID`) -); - -CREATE TABLE tokens ( - UUID char(36) NOT NULL, - token varchar(255) NOT NULL, - validity datetime NOT NULL -); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql b/OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql deleted file mode 100644 index 7ec906b..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/001_Avatar.sql +++ /dev/null @@ -1,9 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE Avatars ( - PrincipalID CHAR(36) NOT NULL, - Name VARCHAR(32) NOT NULL, - Value VARCHAR(255) NOT NULL DEFAULT '', - PRIMARY KEY(PrincipalID, Name)); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_FriendsStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_FriendsStore.sql deleted file mode 100644 index f1b9ab9..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/001_FriendsStore.sql +++ /dev/null @@ -1,10 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE `Friends` ( - `PrincipalID` CHAR(36) NOT NULL, - `Friend` VARCHAR(255) NOT NULL, - `Flags` VARCHAR(16) NOT NULL DEFAULT 0, - `Offered` VARCHAR(32) NOT NULL DEFAULT 0, - PRIMARY KEY(`PrincipalID`, `Friend`)); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_InventoryStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_InventoryStore.sql deleted file mode 100644 index 554d5c2..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/001_InventoryStore.sql +++ /dev/null @@ -1,32 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE inventoryfolders( - UUID varchar(255) primary key, - name varchar(255), - agentID varchar(255), - parentID varchar(255), - type integer, - version integer); - -CREATE TABLE inventoryitems( - UUID varchar(255) primary key, - assetID varchar(255), - assetType integer, - invType integer, - parentFolderID varchar(255), - avatarID varchar(255), - creatorsID varchar(255), - inventoryName varchar(255), - inventoryDescription varchar(255), - inventoryNextPermissions integer, - inventoryCurrentPermissions integer, - inventoryBasePermissions integer, - inventoryEveryOnePermissions integer, - salePrice integer default 99, - saleType integer default 0, - creationDate integer default 2000, - groupID varchar(255) default '00000000-0000-0000-0000-000000000000', - groupOwned integer default 0, - flags integer default 0); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_RegionStore.sql deleted file mode 100644 index 39e8180..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/001_RegionStore.sql +++ /dev/null @@ -1,144 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE prims( - UUID varchar(255) primary key, - RegionUUID varchar(255), - ParentID integer, - CreationDate integer, - Name varchar(255), - SceneGroupID varchar(255), - Text varchar(255), - Description varchar(255), - SitName varchar(255), - TouchName varchar(255), - CreatorID varchar(255), - OwnerID varchar(255), - GroupID varchar(255), - LastOwnerID varchar(255), - OwnerMask integer, - NextOwnerMask integer, - GroupMask integer, - EveryoneMask integer, - BaseMask integer, - PositionX float, - PositionY float, - PositionZ float, - GroupPositionX float, - GroupPositionY float, - GroupPositionZ float, - VelocityX float, - VelocityY float, - VelocityZ float, - AngularVelocityX float, - AngularVelocityY float, - AngularVelocityZ float, - AccelerationX float, - AccelerationY float, - AccelerationZ float, - RotationX float, - RotationY float, - RotationZ float, - RotationW float, - ObjectFlags integer, - SitTargetOffsetX float NOT NULL default 0, - SitTargetOffsetY float NOT NULL default 0, - SitTargetOffsetZ float NOT NULL default 0, - SitTargetOrientW float NOT NULL default 0, - SitTargetOrientX float NOT NULL default 0, - SitTargetOrientY float NOT NULL default 0, - SitTargetOrientZ float NOT NULL default 0); - -CREATE TABLE primshapes( - UUID varchar(255) primary key, - Shape integer, - ScaleX float, - ScaleY float, - ScaleZ float, - PCode integer, - PathBegin integer, - PathEnd integer, - PathScaleX integer, - PathScaleY integer, - PathShearX integer, - PathShearY integer, - PathSkew integer, - PathCurve integer, - PathRadiusOffset integer, - PathRevolutions integer, - PathTaperX integer, - PathTaperY integer, - PathTwist integer, - PathTwistBegin integer, - ProfileBegin integer, - ProfileEnd integer, - ProfileCurve integer, - ProfileHollow integer, - Texture blob, - ExtraParams blob, - State Integer NOT NULL default 0); - -CREATE TABLE primitems( - itemID varchar(255) primary key, - primID varchar(255), - assetID varchar(255), - parentFolderID varchar(255), - invType integer, - assetType integer, - name varchar(255), - description varchar(255), - creationDate integer, - creatorID varchar(255), - ownerID varchar(255), - lastOwnerID varchar(255), - groupID varchar(255), - nextPermissions string, - currentPermissions string, - basePermissions string, - everyonePermissions string, - groupPermissions string); - -CREATE TABLE terrain( - RegionUUID varchar(255), - Revision integer, - Heightfield blob); - -CREATE TABLE land( - UUID varchar(255) primary key, - RegionUUID varchar(255), - LocalLandID string, - Bitmap blob, - Name varchar(255), - Desc varchar(255), - OwnerUUID varchar(255), - IsGroupOwned string, - Area integer, - AuctionID integer, - Category integer, - ClaimDate integer, - ClaimPrice integer, - GroupUUID varchar(255), - SalePrice integer, - LandStatus integer, - LandFlags string, - LandingType string, - MediaAutoScale string, - MediaTextureUUID varchar(255), - MediaURL varchar(255), - MusicURL varchar(255), - PassHours float, - PassPrice string, - SnapshotUUID varchar(255), - UserLocationX float, - UserLocationY float, - UserLocationZ float, - UserLookAtX float, - UserLookAtY float, - UserLookAtZ float, - AuthbuyerID varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'); - -CREATE TABLE landaccesslist( - LandUUID varchar(255), - AccessUUID varchar(255), - Flags string); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/001_UserAccount.sql b/OpenSim/Data/SQLiteNG/Resources/001_UserAccount.sql deleted file mode 100644 index c38d9a7..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/001_UserAccount.sql +++ /dev/null @@ -1,17 +0,0 @@ -BEGIN TRANSACTION; - --- useraccounts table -CREATE TABLE UserAccounts ( - PrincipalID CHAR(36) primary key, - ScopeID CHAR(36) NOT NULL, - FirstName VARCHAR(64) NOT NULL, - LastName VARCHAR(64) NOT NULL, - Email VARCHAR(64), - ServiceURLs TEXT, - Created INT(11), - UserLevel integer NOT NULL DEFAULT 0, - UserFlags integer NOT NULL DEFAULT 0, - UserTitle varchar(64) NOT NULL DEFAULT '' -); - -COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql deleted file mode 100644 index b584594..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/001_UserStore.sql +++ /dev/null @@ -1,39 +0,0 @@ -BEGIN TRANSACTION; - --- users table -CREATE TABLE users( - UUID varchar(255) primary key, - username varchar(255), - surname varchar(255), - passwordHash varchar(255), - passwordSalt varchar(255), - homeRegionX integer, - homeRegionY integer, - homeLocationX float, - homeLocationY float, - homeLocationZ float, - homeLookAtX float, - homeLookAtY float, - homeLookAtZ float, - created integer, - lastLogin integer, - rootInventoryFolderID varchar(255), - userInventoryURI varchar(255), - userAssetURI varchar(255), - profileCanDoMask integer, - profileWantDoMask integer, - profileAboutText varchar(255), - profileFirstText varchar(255), - profileImage varchar(255), - profileFirstImage varchar(255), - webLoginKey text default '00000000-0000-0000-0000-000000000000'); --- friends table -CREATE TABLE userfriends( - ownerID varchar(255), - friendID varchar(255), - friendPerms integer, - ownerPerms integer, - datetimestamp integer); - -COMMIT; - diff --git a/OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql deleted file mode 100644 index 5339b84..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/002_AssetStore.sql +++ /dev/null @@ -1,10 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TEMPORARY TABLE assets_backup(UUID,Name,Description,Type,Local,Temporary,Data); -INSERT INTO assets_backup SELECT UUID,Name,Description,Type,Local,Temporary,Data FROM assets; -DROP TABLE assets; -CREATE TABLE assets(UUID,Name,Description,Type,Local,Temporary,Data); -INSERT INTO assets SELECT UUID,Name,Description,Type,Local,Temporary,Data FROM assets_backup; -DROP TABLE assets_backup; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql deleted file mode 100644 index 3237b68..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/002_AuthStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN TRANSACTION; - -INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey) SELECT `UUID` AS UUID, `passwordHash` AS passwordHash, `passwordSalt` AS passwordSalt, `webLoginKey` AS webLoginKey FROM users; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/002_FriendsStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_FriendsStore.sql deleted file mode 100644 index 6733502..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/002_FriendsStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN TRANSACTION; - -INSERT INTO `Friends` SELECT `ownerID`, `friendID`, `friendPerms`, 0 FROM `userfriends`; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/002_InventoryStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_InventoryStore.sql deleted file mode 100644 index 01951d6..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/002_InventoryStore.sql +++ /dev/null @@ -1,8 +0,0 @@ -BEGIN TRANSACTION; - -create index inventoryfolders_agentid on inventoryfolders(agentid); -create index inventoryfolders_parentid on inventoryfolders(parentid); -create index inventoryitems_parentfolderid on inventoryitems(parentfolderid); -create index inventoryitems_avatarid on inventoryitems(avatarid); - -COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/002_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_RegionStore.sql deleted file mode 100644 index c5c7c99..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/002_RegionStore.sql +++ /dev/null @@ -1,10 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE regionban( - regionUUID varchar (255), - bannedUUID varchar (255), - bannedIp varchar (255), - bannedIpHostMask varchar (255) - ); - -COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/002_UserAccount.sql b/OpenSim/Data/SQLiteNG/Resources/002_UserAccount.sql deleted file mode 100644 index c7a6293..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/002_UserAccount.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN TRANSACTION; - -INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT `UUID` AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, username AS FirstName, surname AS LastName, '' as Email, '' AS ServiceURLs, created as Created FROM users; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql deleted file mode 100644 index 48fc680..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/002_UserStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE users add homeRegionID varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql b/OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql deleted file mode 100644 index f54f8d9..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/003_AssetStore.sql +++ /dev/null @@ -1 +0,0 @@ -DELETE FROM assets WHERE UUID = 'dc4b9f0bd00845c696a401dd947ac621' diff --git a/OpenSim/Data/SQLiteNG/Resources/003_InventoryStore.sql b/OpenSim/Data/SQLiteNG/Resources/003_InventoryStore.sql deleted file mode 100644 index 4c6da91..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/003_InventoryStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -alter table inventoryitems add column inventoryGroupPermissions integer unsigned not null default 0; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/003_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/003_RegionStore.sql deleted file mode 100644 index 4db2f75..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/003_RegionStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE primitems add flags integer not null default 0; - -COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql deleted file mode 100644 index 6f890ee..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/003_UserStore.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE users add userFlags integer NOT NULL default 0; -ALTER TABLE users add godLevel integer NOT NULL default 0; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql b/OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql deleted file mode 100644 index 39421c4..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/004_AssetStore.sql +++ /dev/null @@ -1,7 +0,0 @@ -BEGIN; - -update assets - set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) - where UUID not like '%-%'; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/004_InventoryStore.sql b/OpenSim/Data/SQLiteNG/Resources/004_InventoryStore.sql deleted file mode 100644 index e8f4d46..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/004_InventoryStore.sql +++ /dev/null @@ -1,36 +0,0 @@ -BEGIN; - -update inventoryitems - set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) - where UUID not like '%-%'; - -update inventoryitems - set assetID = substr(assetID, 1, 8) || "-" || substr(assetID, 9, 4) || "-" || substr(assetID, 13, 4) || "-" || substr(assetID, 17, 4) || "-" || substr(assetID, 21, 12) - where assetID not like '%-%'; - -update inventoryitems - set parentFolderID = substr(parentFolderID, 1, 8) || "-" || substr(parentFolderID, 9, 4) || "-" || substr(parentFolderID, 13, 4) || "-" || substr(parentFolderID, 17, 4) || "-" || substr(parentFolderID, 21, 12) - where parentFolderID not like '%-%'; - -update inventoryitems - set avatarID = substr(avatarID, 1, 8) || "-" || substr(avatarID, 9, 4) || "-" || substr(avatarID, 13, 4) || "-" || substr(avatarID, 17, 4) || "-" || substr(avatarID, 21, 12) - where avatarID not like '%-%'; - -update inventoryitems - set creatorsID = substr(creatorsID, 1, 8) || "-" || substr(creatorsID, 9, 4) || "-" || substr(creatorsID, 13, 4) || "-" || substr(creatorsID, 17, 4) || "-" || substr(creatorsID, 21, 12) - where creatorsID not like '%-%'; - - -update inventoryfolders - set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) - where UUID not like '%-%'; - -update inventoryfolders - set agentID = substr(agentID, 1, 8) || "-" || substr(agentID, 9, 4) || "-" || substr(agentID, 13, 4) || "-" || substr(agentID, 17, 4) || "-" || substr(agentID, 21, 12) - where agentID not like '%-%'; - -update inventoryfolders - set parentID = substr(parentID, 1, 8) || "-" || substr(parentID, 9, 4) || "-" || substr(parentID, 13, 4) || "-" || substr(parentID, 17, 4) || "-" || substr(parentID, 21, 12) - where parentID not like '%-%'; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/004_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/004_RegionStore.sql deleted file mode 100644 index de328cb..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/004_RegionStore.sql +++ /dev/null @@ -1,38 +0,0 @@ -BEGIN; - -create table regionsettings ( - regionUUID char(36) not null, - block_terraform integer not null, - block_fly integer not null, - allow_damage integer not null, - restrict_pushing integer not null, - allow_land_resell integer not null, - allow_land_join_divide integer not null, - block_show_in_search integer not null, - agent_limit integer not null, - object_bonus float not null, - maturity integer not null, - disable_scripts integer not null, - disable_collisions integer not null, - disable_physics integer not null, - terrain_texture_1 char(36) not null, - terrain_texture_2 char(36) not null, - terrain_texture_3 char(36) not null, - terrain_texture_4 char(36) not null, - elevation_1_nw float not null, - elevation_2_nw float not null, - elevation_1_ne float not null, - elevation_2_ne float not null, - elevation_1_se float not null, - elevation_2_se float not null, - elevation_1_sw float not null, - elevation_2_sw float not null, - water_height float not null, - terrain_raise_limit float not null, - terrain_lower_limit float not null, - use_estate_sun integer not null, - fixed_sun integer not null, - sun_position float not null, - covenant char(36)); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql deleted file mode 100644 index 03142af..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/004_UserStore.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE users add customType varchar(32) not null default ''; -ALTER TABLE users add partner char(36) not null default '00000000-0000-0000-0000-000000000000'; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/005_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/005_RegionStore.sql deleted file mode 100644 index 1f6d1bd..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/005_RegionStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -delete from regionsettings; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql deleted file mode 100644 index e45c09a..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/005_UserStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -CREATE TABLE `avatarattachments` (`UUID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', `attachpoint` int(11) NOT NULL DEFAULT 0, `item` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', `asset` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/006_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/006_RegionStore.sql deleted file mode 100644 index 94ed818..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/006_RegionStore.sql +++ /dev/null @@ -1,102 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE estate_groups ( - EstateID int(10) NOT NULL, - uuid char(36) NOT NULL -); - -CREATE TABLE estate_managers ( - EstateID int(10) NOT NULL, - uuid char(36) NOT NULL -); - -CREATE TABLE estate_map ( - RegionID char(36) NOT NULL default '00000000-0000-0000-0000-000000000000', - EstateID int(11) NOT NULL -); - -CREATE TABLE estate_settings ( - EstateID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - EstateName varchar(64) default NULL, - AbuseEmailToEstateOwner tinyint(4) NOT NULL, - DenyAnonymous tinyint(4) NOT NULL, - ResetHomeOnTeleport tinyint(4) NOT NULL, - FixedSun tinyint(4) NOT NULL, - DenyTransacted tinyint(4) NOT NULL, - BlockDwell tinyint(4) NOT NULL, - DenyIdentified tinyint(4) NOT NULL, - AllowVoice tinyint(4) NOT NULL, - UseGlobalTime tinyint(4) NOT NULL, - PricePerMeter int(11) NOT NULL, - TaxFree tinyint(4) NOT NULL, - AllowDirectTeleport tinyint(4) NOT NULL, - RedirectGridX int(11) NOT NULL, - RedirectGridY int(11) NOT NULL, - ParentEstateID int(10) NOT NULL, - SunPosition double NOT NULL, - EstateSkipScripts tinyint(4) NOT NULL, - BillableFactor float NOT NULL, - PublicAccess tinyint(4) NOT NULL -); -insert into estate_settings (EstateID,EstateName,AbuseEmailToEstateOwner,DenyAnonymous,ResetHomeOnTeleport,FixedSun,DenyTransacted,BlockDwell,DenyIdentified,AllowVoice,UseGlobalTime,PricePerMeter,TaxFree,AllowDirectTeleport,RedirectGridX,RedirectGridY,ParentEstateID,SunPosition,PublicAccess,EstateSkipScripts,BillableFactor) values ( 99, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''); -delete from estate_settings; -CREATE TABLE estate_users ( - EstateID int(10) NOT NULL, - uuid char(36) NOT NULL -); - -CREATE TABLE estateban ( - EstateID int(10) NOT NULL, - bannedUUID varchar(36) NOT NULL, - bannedIp varchar(16) NOT NULL, - bannedIpHostMask varchar(16) NOT NULL, - bannedNameMask varchar(64) default NULL -); - -drop table regionsettings; -CREATE TABLE regionsettings ( - regionUUID char(36) NOT NULL, - block_terraform int(11) NOT NULL, - block_fly int(11) NOT NULL, - allow_damage int(11) NOT NULL, - restrict_pushing int(11) NOT NULL, - allow_land_resell int(11) NOT NULL, - allow_land_join_divide int(11) NOT NULL, - block_show_in_search int(11) NOT NULL, - agent_limit int(11) NOT NULL, - object_bonus float NOT NULL, - maturity int(11) NOT NULL, - disable_scripts int(11) NOT NULL, - disable_collisions int(11) NOT NULL, - disable_physics int(11) NOT NULL, - terrain_texture_1 char(36) NOT NULL, - terrain_texture_2 char(36) NOT NULL, - terrain_texture_3 char(36) NOT NULL, - terrain_texture_4 char(36) NOT NULL, - elevation_1_nw float NOT NULL, - elevation_2_nw float NOT NULL, - elevation_1_ne float NOT NULL, - elevation_2_ne float NOT NULL, - elevation_1_se float NOT NULL, - elevation_2_se float NOT NULL, - elevation_1_sw float NOT NULL, - elevation_2_sw float NOT NULL, - water_height float NOT NULL, - terrain_raise_limit float NOT NULL, - terrain_lower_limit float NOT NULL, - use_estate_sun int(11) NOT NULL, - fixed_sun int(11) NOT NULL, - sun_position float NOT NULL, - covenant char(36) default NULL, - Sandbox tinyint(4) NOT NULL, - PRIMARY KEY (regionUUID) -); - -CREATE INDEX estate_ban_estate_id on estateban(EstateID); -CREATE INDEX estate_groups_estate_id on estate_groups(EstateID); -CREATE INDEX estate_managers_estate_id on estate_managers(EstateID); -CREATE INDEX estate_map_estate_id on estate_map(EstateID); -CREATE UNIQUE INDEX estate_map_region_id on estate_map(RegionID); -CREATE INDEX estate_users_estate_id on estate_users(EstateID); - -COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql deleted file mode 100644 index f9454c5..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/006_UserStore.sql +++ /dev/null @@ -1,20 +0,0 @@ -BEGIN TRANSACTION; - --- usersagents table -CREATE TABLE IF NOT EXISTS useragents( - UUID varchar(255) primary key, - agentIP varchar(255), - agentPort integer, - agentOnline boolean, - sessionID varchar(255), - secureSessionID varchar(255), - regionID varchar(255), - loginTime integer, - logoutTime integer, - currentRegion varchar(255), - currentHandle varchar(255), - currentPosX float, - currentPosY float, - currentPosZ float); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/007_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/007_RegionStore.sql deleted file mode 100644 index 1c813a0..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/007_RegionStore.sql +++ /dev/null @@ -1,8 +0,0 @@ -begin; - -alter table estate_settings add column AbuseEmail varchar(255) not null default ''; - -alter table estate_settings add column EstateOwner varchar(36) not null default ''; - -commit; - diff --git a/OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql deleted file mode 100644 index 8b0cd28..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/007_UserStore.sql +++ /dev/null @@ -1,7 +0,0 @@ -BEGIN TRANSACTION; - -ALTER TABLE useragents add currentLookAtX float not null default 128; -ALTER TABLE useragents add currentLookAtY float not null default 128; -ALTER TABLE useragents add currentLookAtZ float not null default 70; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/008_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/008_RegionStore.sql deleted file mode 100644 index 28bfbf5..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/008_RegionStore.sql +++ /dev/null @@ -1,6 +0,0 @@ -begin; - -alter table estate_settings add column DenyMinors tinyint not null default 0; - -commit; - diff --git a/OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql deleted file mode 100644 index 97da818..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/008_UserStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN TRANSACTION; - -ALTER TABLE users add email varchar(250); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/009_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/009_RegionStore.sql deleted file mode 100644 index 1f40548..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/009_RegionStore.sql +++ /dev/null @@ -1,8 +0,0 @@ -BEGIN; - -ALTER TABLE prims ADD COLUMN ColorR integer not null default 0; -ALTER TABLE prims ADD COLUMN ColorG integer not null default 0; -ALTER TABLE prims ADD COLUMN ColorB integer not null default 0; -ALTER TABLE prims ADD COLUMN ColorA integer not null default 0; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql deleted file mode 100644 index 8ab03ef..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/009_UserStore.sql +++ /dev/null @@ -1,11 +0,0 @@ -BEGIN; - -update users - set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) - where UUID not like '%-%'; - -update useragents - set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) - where UUID not like '%-%'; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/010_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/010_RegionStore.sql deleted file mode 100644 index b91ccf0..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/010_RegionStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE prims ADD COLUMN ClickAction INTEGER NOT NULL default 0; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql b/OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql deleted file mode 100644 index 5f956da..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/010_UserStore.sql +++ /dev/null @@ -1,37 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE IF NOT EXISTS avatarappearance( - Owner varchar(36) NOT NULL primary key, - BodyItem varchar(36) DEFAULT NULL, - BodyAsset varchar(36) DEFAULT NULL, - SkinItem varchar(36) DEFAULT NULL, - SkinAsset varchar(36) DEFAULT NULL, - HairItem varchar(36) DEFAULT NULL, - HairAsset varchar(36) DEFAULT NULL, - EyesItem varchar(36) DEFAULT NULL, - EyesAsset varchar(36) DEFAULT NULL, - ShirtItem varchar(36) DEFAULT NULL, - ShirtAsset varchar(36) DEFAULT NULL, - PantsItem varchar(36) DEFAULT NULL, - PantsAsset varchar(36) DEFAULT NULL, - ShoesItem varchar(36) DEFAULT NULL, - ShoesAsset varchar(36) DEFAULT NULL, - SocksItem varchar(36) DEFAULT NULL, - SocksAsset varchar(36) DEFAULT NULL, - JacketItem varchar(36) DEFAULT NULL, - JacketAsset varchar(36) DEFAULT NULL, - GlovesItem varchar(36) DEFAULT NULL, - GlovesAsset varchar(36) DEFAULT NULL, - UnderShirtItem varchar(36) DEFAULT NULL, - UnderShirtAsset varchar(36) DEFAULT NULL, - UnderPantsItem varchar(36) DEFAULT NULL, - UnderPantsAsset varchar(36) DEFAULT NULL, - SkirtItem varchar(36) DEFAULT NULL, - SkirtAsset varchar(36) DEFAULT NULL, - Texture blob, - VisualParams blob, - Serial int DEFAULT NULL, - AvatarHeight float DEFAULT NULL -); - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/011_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/011_RegionStore.sql deleted file mode 100644 index 42bef89..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/011_RegionStore.sql +++ /dev/null @@ -1,28 +0,0 @@ -BEGIN; - -ALTER TABLE prims ADD COLUMN PayPrice INTEGER NOT NULL default 0; -ALTER TABLE prims ADD COLUMN PayButton1 INTEGER NOT NULL default 0; -ALTER TABLE prims ADD COLUMN PayButton2 INTEGER NOT NULL default 0; -ALTER TABLE prims ADD COLUMN PayButton3 INTEGER NOT NULL default 0; -ALTER TABLE prims ADD COLUMN PayButton4 INTEGER NOT NULL default 0; -ALTER TABLE prims ADD COLUMN LoopedSound varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'; -ALTER TABLE prims ADD COLUMN LoopedSoundGain float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN TextureAnimation string; -ALTER TABLE prims ADD COLUMN ParticleSystem string; -ALTER TABLE prims ADD COLUMN OmegaX float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN OmegaY float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN OmegaZ float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN CameraEyeOffsetX float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN CameraEyeOffsetY float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN CameraEyeOffsetZ float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN CameraAtOffsetX float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN CameraAtOffsetY float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN CameraAtOffsetZ float NOT NULL default 0; -ALTER TABLE prims ADD COLUMN ForceMouselook string NOT NULL default 0; -ALTER TABLE prims ADD COLUMN ScriptAccessPin INTEGER NOT NULL default 0; -ALTER TABLE prims ADD COLUMN AllowedDrop INTEGER NOT NULL default 0; -ALTER TABLE prims ADD COLUMN DieAtEdge string NOT NULL default 0; -ALTER TABLE prims ADD COLUMN SalePrice INTEGER NOT NULL default 0; -ALTER TABLE prims ADD COLUMN SaleType string NOT NULL default 0; - -COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/012_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/012_RegionStore.sql deleted file mode 100644 index d952b78..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/012_RegionStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE prims ADD COLUMN Material INTEGER NOT NULL default 3; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/013_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/013_RegionStore.sql deleted file mode 100644 index 11529cd..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/013_RegionStore.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE land ADD COLUMN OtherCleanTime INTEGER NOT NULL default 0; -ALTER TABLE land ADD COLUMN Dwell INTEGER NOT NULL default 0; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/014_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/014_RegionStore.sql deleted file mode 100644 index c59b27e..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/014_RegionStore.sql +++ /dev/null @@ -1,8 +0,0 @@ -begin; - -ALTER TABLE regionsettings ADD COLUMN sunvectorx double NOT NULL default 0; -ALTER TABLE regionsettings ADD COLUMN sunvectory double NOT NULL default 0; -ALTER TABLE regionsettings ADD COLUMN sunvectorz double NOT NULL default 0; - -commit; - diff --git a/OpenSim/Data/SQLiteNG/Resources/015_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/015_RegionStore.sql deleted file mode 100644 index c43f356..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/015_RegionStore.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE prims ADD COLUMN CollisionSound varchar(36) NOT NULL default '00000000-0000-0000-0000-000000000000'; -ALTER TABLE prims ADD COLUMN CollisionSoundVolume float NOT NULL default 0; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/016_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/016_RegionStore.sql deleted file mode 100644 index 52f160c..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/016_RegionStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE prims ADD COLUMN VolumeDetect INTEGER NOT NULL DEFAULT 0; - -COMMIT; diff --git a/OpenSim/Data/SQLiteNG/Resources/017_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/017_RegionStore.sql deleted file mode 100644 index 6c6b7b5..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/017_RegionStore.sql +++ /dev/null @@ -1,8 +0,0 @@ -BEGIN; -CREATE TEMPORARY TABLE prims_backup(UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect); -INSERT INTO prims_backup SELECT UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect FROM prims; -DROP TABLE prims; -CREATE TABLE prims(UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect); -INSERT INTO prims SELECT UUID,RegionUUID,CreationDate,Name,SceneGroupID,Text,Description,SitName,TouchName,CreatorID,OwnerID,GroupID,LastOwnerID,OwnerMask,NextOwnerMask,GroupMask,EveryoneMask,BaseMask,PositionX,PositionY,PositionZ,GroupPositionX,GroupPositionY,GroupPositionZ,VelocityX,VelocityY,VelocityZ,AngularVelocityX,AngularVelocityY,AngularVelocityZ,AccelerationX,AccelerationY,AccelerationZ,RotationX,RotationY,RotationZ,RotationW,ObjectFlags,SitTargetOffsetX,SitTargetOffsetY,SitTargetOffsetZ,SitTargetOrientW,SitTargetOrientX,SitTargetOrientY,SitTargetOrientZ,ColorR,ColorG,ColorB,ColorA,ClickAction,PayPrice,PayButton1,PayButton2,PayButton3,PayButton4,LoopedSound,LoopedSoundGain,TextureAnimation,ParticleSystem,OmegaX,OmegaY,OmegaZ,CameraEyeOffsetX,CameraEyeOffsetY,CameraEyeOffsetZ,CameraAtOffsetX,CameraAtOffsetY,CameraAtOffsetZ,ForceMouselook,ScriptAccessPin,AllowedDrop,DieAtEdge,SalePrice,SaleType,Material,CollisionSound,CollisionSoundVolume,VolumeDetect FROM prims_backup; -DROP TABLE prims_backup; -COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/018_RegionStore.sql b/OpenSim/Data/SQLiteNG/Resources/018_RegionStore.sql deleted file mode 100644 index 6a390c2..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/018_RegionStore.sql +++ /dev/null @@ -1,79 +0,0 @@ -BEGIN; - -update terrain - set RegionUUID = substr(RegionUUID, 1, 8) || "-" || substr(RegionUUID, 9, 4) || "-" || substr(RegionUUID, 13, 4) || "-" || substr(RegionUUID, 17, 4) || "-" || substr(RegionUUID, 21, 12) - where RegionUUID not like '%-%'; - - -update landaccesslist - set LandUUID = substr(LandUUID, 1, 8) || "-" || substr(LandUUID, 9, 4) || "-" || substr(LandUUID, 13, 4) || "-" || substr(LandUUID, 17, 4) || "-" || substr(LandUUID, 21, 12) - where LandUUID not like '%-%'; - -update landaccesslist - set AccessUUID = substr(AccessUUID, 1, 8) || "-" || substr(AccessUUID, 9, 4) || "-" || substr(AccessUUID, 13, 4) || "-" || substr(AccessUUID, 17, 4) || "-" || substr(AccessUUID, 21, 12) - where AccessUUID not like '%-%'; - - -update prims - set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) - where UUID not like '%-%'; - -update prims - set RegionUUID = substr(RegionUUID, 1, 8) || "-" || substr(RegionUUID, 9, 4) || "-" || substr(RegionUUID, 13, 4) || "-" || substr(RegionUUID, 17, 4) || "-" || substr(RegionUUID, 21, 12) - where RegionUUID not like '%-%'; - -update prims - set SceneGroupID = substr(SceneGroupID, 1, 8) || "-" || substr(SceneGroupID, 9, 4) || "-" || substr(SceneGroupID, 13, 4) || "-" || substr(SceneGroupID, 17, 4) || "-" || substr(SceneGroupID, 21, 12) - where SceneGroupID not like '%-%'; - -update prims - set CreatorID = substr(CreatorID, 1, 8) || "-" || substr(CreatorID, 9, 4) || "-" || substr(CreatorID, 13, 4) || "-" || substr(CreatorID, 17, 4) || "-" || substr(CreatorID, 21, 12) - where CreatorID not like '%-%'; - -update prims - set OwnerID = substr(OwnerID, 1, 8) || "-" || substr(OwnerID, 9, 4) || "-" || substr(OwnerID, 13, 4) || "-" || substr(OwnerID, 17, 4) || "-" || substr(OwnerID, 21, 12) - where OwnerID not like '%-%'; - -update prims - set GroupID = substr(GroupID, 1, 8) || "-" || substr(GroupID, 9, 4) || "-" || substr(GroupID, 13, 4) || "-" || substr(GroupID, 17, 4) || "-" || substr(GroupID, 21, 12) - where GroupID not like '%-%'; - -update prims - set LastOwnerID = substr(LastOwnerID, 1, 8) || "-" || substr(LastOwnerID, 9, 4) || "-" || substr(LastOwnerID, 13, 4) || "-" || substr(LastOwnerID, 17, 4) || "-" || substr(LastOwnerID, 21, 12) - where LastOwnerID not like '%-%'; - - -update primshapes - set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) - where UUID not like '%-%'; - - -update land - set UUID = substr(UUID, 1, 8) || "-" || substr(UUID, 9, 4) || "-" || substr(UUID, 13, 4) || "-" || substr(UUID, 17, 4) || "-" || substr(UUID, 21, 12) - where UUID not like '%-%'; - -update land - set RegionUUID = substr(RegionUUID, 1, 8) || "-" || substr(RegionUUID, 9, 4) || "-" || substr(RegionUUID, 13, 4) || "-" || substr(RegionUUID, 17, 4) || "-" || substr(RegionUUID, 21, 12) - where RegionUUID not like '%-%'; - -update land - set OwnerUUID = substr(OwnerUUID, 1, 8) || "-" || substr(OwnerUUID, 9, 4) || "-" || substr(OwnerUUID, 13, 4) || "-" || substr(OwnerUUID, 17, 4) || "-" || substr(OwnerUUID, 21, 12) - where OwnerUUID not like '%-%'; - -update land - set GroupUUID = substr(GroupUUID, 1, 8) || "-" || substr(GroupUUID, 9, 4) || "-" || substr(GroupUUID, 13, 4) || "-" || substr(GroupUUID, 17, 4) || "-" || substr(GroupUUID, 21, 12) - where GroupUUID not like '%-%'; - -update land - set MediaTextureUUID = substr(MediaTextureUUID, 1, 8) || "-" || substr(MediaTextureUUID, 9, 4) || "-" || substr(MediaTextureUUID, 13, 4) || "-" || substr(MediaTextureUUID, 17, 4) || "-" || substr(MediaTextureUUID, 21, 12) - where MediaTextureUUID not like '%-%'; - -update land - set SnapshotUUID = substr(SnapshotUUID, 1, 8) || "-" || substr(SnapshotUUID, 9, 4) || "-" || substr(SnapshotUUID, 13, 4) || "-" || substr(SnapshotUUID, 17, 4) || "-" || substr(SnapshotUUID, 21, 12) - where SnapshotUUID not like '%-%'; - -update land - set AuthbuyerID = substr(AuthbuyerID, 1, 8) || "-" || substr(AuthbuyerID, 9, 4) || "-" || substr(AuthbuyerID, 13, 4) || "-" || substr(AuthbuyerID, 17, 4) || "-" || substr(AuthbuyerID, 21, 12) - where AuthbuyerID not like '%-%'; - -COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteNG/Resources/OpenSim.Data.SQLite.addin.xml b/OpenSim/Data/SQLiteNG/Resources/OpenSim.Data.SQLite.addin.xml deleted file mode 100644 index e6764fa..0000000 --- a/OpenSim/Data/SQLiteNG/Resources/OpenSim.Data.SQLite.addin.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs b/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs deleted file mode 100644 index 9b34a21..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteAssetData.cs +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Data; -using System.Reflection; -using System.Collections.Generic; -using log4net; -using Mono.Data.Sqlite; -using OpenMetaverse; -using OpenSim.Framework; - -namespace OpenSim.Data.SQLiteNG -{ - /// - /// An asset storage interface for the SQLite database system - /// - public class SQLiteAssetData : AssetDataBase - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private const string SelectAssetSQL = "select * from assets where UUID=:UUID"; - private const string SelectAssetMetadataSQL = "select Name, Description, Type, Temporary, UUID from assets limit :start, :count"; - private const string DeleteAssetSQL = "delete from assets where UUID=:UUID"; - private const string InsertAssetSQL = "insert into assets(UUID, Name, Description, Type, Local, Temporary, Data) values(:UUID, :Name, :Description, :Type, :Local, :Temporary, :Data)"; - private const string UpdateAssetSQL = "update assets set Name=:Name, Description=:Description, Type=:Type, Local=:Local, Temporary=:Temporary, Data=:Data where UUID=:UUID"; - private const string assetSelect = "select * from assets"; - - private SqliteConnection m_conn; - - override public void Dispose() - { - if (m_conn != null) - { - m_conn.Close(); - m_conn = null; - } - } - - /// - /// - /// Initialises AssetData interface - /// Loads and initialises a new SQLite connection and maintains it. - /// use default URI if connect string is empty. - /// - /// - /// connect string - override public void Initialise(string dbconnect) - { - if (dbconnect == string.Empty) - { - dbconnect = "URI=file:Asset.db,version=3"; - } - m_conn = new SqliteConnection(dbconnect); - m_conn.Open(); - - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_conn, assem, "AssetStore"); - m.Update(); - - return; - } - - /// - /// Fetch Asset - /// - /// UUID of ... ? - /// Asset base - override public AssetBase GetAsset(UUID uuid) - { - lock (this) - { - using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); - using (IDataReader reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - AssetBase asset = buildAsset(reader); - reader.Close(); - return asset; - } - else - { - reader.Close(); - return null; - } - } - } - } - } - - /// - /// Create an asset - /// - /// Asset Base - override public void StoreAsset(AssetBase asset) - { - //m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString()); - if (ExistsAsset(asset.FullID)) - { - //LogAssetLoad(asset); - - lock (this) - { - using (SqliteCommand cmd = new SqliteCommand(UpdateAssetSQL, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":UUID", asset.FullID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":Name", asset.Name)); - cmd.Parameters.Add(new SqliteParameter(":Description", asset.Description)); - cmd.Parameters.Add(new SqliteParameter(":Type", asset.Type)); - cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); - cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); - cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); - - cmd.ExecuteNonQuery(); - } - } - } - else - { - lock (this) - { - using (SqliteCommand cmd = new SqliteCommand(InsertAssetSQL, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":UUID", asset.FullID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":Name", asset.Name)); - cmd.Parameters.Add(new SqliteParameter(":Description", asset.Description)); - cmd.Parameters.Add(new SqliteParameter(":Type", asset.Type)); - cmd.Parameters.Add(new SqliteParameter(":Local", asset.Local)); - cmd.Parameters.Add(new SqliteParameter(":Temporary", asset.Temporary)); - cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); - - cmd.ExecuteNonQuery(); - } - } - } - } - -// /// -// /// Some... logging functionnality -// /// -// /// -// private static void LogAssetLoad(AssetBase asset) -// { -// string temporary = asset.Temporary ? "Temporary" : "Stored"; -// string local = asset.Local ? "Local" : "Remote"; -// -// int assetLength = (asset.Data != null) ? asset.Data.Length : 0; -// -// m_log.Debug("[ASSET DB]: " + -// string.Format("Loaded {5} {4} Asset: [{0}][{3}] \"{1}\":{2} ({6} bytes)", -// asset.FullID, asset.Name, asset.Description, asset.Type, -// temporary, local, assetLength)); -// } - - /// - /// Check if an asset exist in database - /// - /// The asset UUID - /// True if exist, or false. - override public bool ExistsAsset(UUID uuid) - { - lock (this) { - using (SqliteCommand cmd = new SqliteCommand(SelectAssetSQL, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); - using (IDataReader reader = cmd.ExecuteReader()) - { - if (reader.Read()) - { - reader.Close(); - return true; - } - else - { - reader.Close(); - return false; - } - } - } - } - } - - /// - /// Delete an asset from database - /// - /// - public void DeleteAsset(UUID uuid) - { - using (SqliteCommand cmd = new SqliteCommand(DeleteAssetSQL, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":UUID", uuid.ToString())); - - cmd.ExecuteNonQuery(); - } - } - - /// - /// - /// - /// - /// - private static AssetBase buildAsset(IDataReader row) - { - // TODO: this doesn't work yet because something more - // interesting has to be done to actually get these values - // back out. Not enough time to figure it out yet. - AssetBase asset = new AssetBase( - new UUID((String)row["UUID"]), - (String)row["Name"], - Convert.ToSByte(row["Type"]), - UUID.Zero.ToString() - ); - - asset.Description = (String) row["Description"]; - asset.Local = Convert.ToBoolean(row["Local"]); - asset.Temporary = Convert.ToBoolean(row["Temporary"]); - asset.Data = (byte[]) row["Data"]; - return asset; - } - - private static AssetMetadata buildAssetMetadata(IDataReader row) - { - AssetMetadata metadata = new AssetMetadata(); - - metadata.FullID = new UUID((string) row["UUID"]); - metadata.Name = (string) row["Name"]; - metadata.Description = (string) row["Description"]; - metadata.Type = Convert.ToSByte(row["Type"]); - metadata.Temporary = Convert.ToBoolean(row["Temporary"]); // Not sure if this is correct. - - // Current SHA1s are not stored/computed. - metadata.SHA1 = new byte[] {}; - - return metadata; - } - - /// - /// Returns a list of AssetMetadata objects. The list is a subset of - /// the entire data set offset by containing - /// elements. - /// - /// The number of results to discard from the total data set. - /// The number of rows the returned list should contain. - /// A list of AssetMetadata objects. - public override List FetchAssetMetadataSet(int start, int count) - { - List retList = new List(count); - - lock (this) - { - using (SqliteCommand cmd = new SqliteCommand(SelectAssetMetadataSQL, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":start", start)); - cmd.Parameters.Add(new SqliteParameter(":count", count)); - - using (IDataReader reader = cmd.ExecuteReader()) - { - while (reader.Read()) - { - AssetMetadata metadata = buildAssetMetadata(reader); - retList.Add(metadata); - } - } - } - } - - return retList; - } - - /*********************************************************************** - * - * Database Binding functions - * - * These will be db specific due to typing, and minor differences - * in databases. - * - **********************************************************************/ - - #region IPlugin interface - - /// - /// - /// - override public string Version - { - get - { - Module module = GetType().Module; - // string dllName = module.Assembly.ManifestModule.Name; - Version dllVersion = module.Assembly.GetName().Version; - - return - string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, - dllVersion.Revision); - } - } - - /// - /// Initialise the AssetData interface using default URI - /// - override public void Initialise() - { - Initialise("URI=file:Asset.db,version=3"); - } - - /// - /// Name of this DB provider - /// - override public string Name - { - get { return "SQLite Asset storage engine"; } - } - - #endregion - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs deleted file mode 100644 index 4a5dc2e..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteAuthenticationData.cs +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.Sqlite; - -namespace OpenSim.Data.SQLiteNG -{ - public class SQLiteAuthenticationData : SQLiteFramework, IAuthenticationData - { - private string m_Realm; - private List m_ColumnNames; - private int m_LastExpire; - private string m_connectionString; - - protected static SqliteConnection m_Connection; - private static bool m_initialized = false; - - public SQLiteAuthenticationData(string connectionString, string realm) - : base(connectionString) - { - m_Realm = realm; - m_connectionString = connectionString; - - if (!m_initialized) - { - m_Connection = new SqliteConnection(connectionString); - m_Connection.Open(); - - Migration m = new Migration(m_Connection, GetType().Assembly, "AuthStore"); - m.Update(); - - m_initialized = true; - } - } - - public AuthenticationData Get(UUID principalID) - { - AuthenticationData ret = new AuthenticationData(); - ret.Data = new Dictionary(); - - SqliteCommand cmd = new SqliteCommand("select * from `" + m_Realm + "` where UUID = :PrincipalID"); - cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); - - IDataReader result = ExecuteReader(cmd, m_Connection); - - try - { - if (result.Read()) - { - ret.PrincipalID = principalID; - - if (m_ColumnNames == null) - { - m_ColumnNames = new List(); - - DataTable schemaTable = result.GetSchemaTable(); - foreach (DataRow row in schemaTable.Rows) - m_ColumnNames.Add(row["ColumnName"].ToString()); - } - - foreach (string s in m_ColumnNames) - { - if (s == "UUID") - continue; - - ret.Data[s] = result[s].ToString(); - } - - return ret; - } - else - { - return null; - } - } - catch - { - } - finally - { - //CloseCommand(cmd); - } - - return null; - } - - public bool Store(AuthenticationData data) - { - if (data.Data.ContainsKey("UUID")) - data.Data.Remove("UUID"); - - string[] fields = new List(data.Data.Keys).ToArray(); - string[] values = new string[data.Data.Count]; - int i = 0; - foreach (object o in data.Data.Values) - values[i++] = o.ToString(); - - SqliteCommand cmd = new SqliteCommand(); - - if (Get(data.PrincipalID) != null) - { - - - string update = "update `" + m_Realm + "` set "; - bool first = true; - foreach (string field in fields) - { - if (!first) - update += ", "; - update += "`" + field + "` = :" + field; - cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); - - first = false; - } - - update += " where UUID = :UUID"; - cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); - - cmd.CommandText = update; - try - { - if (ExecuteNonQuery(cmd, m_Connection) < 1) - { - //CloseCommand(cmd); - return false; - } - } - catch (Exception e) - { - Console.WriteLine(e.ToString()); - //CloseCommand(cmd); - return false; - } - } - - else - { - string insert = "insert into `" + m_Realm + "` (`UUID`, `" + - String.Join("`, `", fields) + - "`) values (:UUID, :" + String.Join(", :", fields) + ")"; - - cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); - foreach (string field in fields) - cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); - - cmd.CommandText = insert; - - try - { - if (ExecuteNonQuery(cmd, m_Connection) < 1) - { - //CloseCommand(cmd); - return false; - } - } - catch (Exception e) - { - Console.WriteLine(e.ToString()); - //CloseCommand(cmd); - return false; - } - } - - //CloseCommand(cmd); - - return true; - } - - public bool SetDataItem(UUID principalID, string item, string value) - { - SqliteCommand cmd = new SqliteCommand("update `" + m_Realm + - "` set `" + item + "` = " + value + " where UUID = '" + principalID.ToString() + "'"); - - if (ExecuteNonQuery(cmd, m_Connection) > 0) - return true; - - return false; - } - - public bool SetToken(UUID principalID, string token, int lifetime) - { - if (System.Environment.TickCount - m_LastExpire > 30000) - DoExpire(); - - SqliteCommand cmd = new SqliteCommand("insert into tokens (UUID, token, validity) values ('" + principalID.ToString() + - "', '" + token + "', datetime('now', 'localtime', '+" + lifetime.ToString() + " minutes'))"); - - if (ExecuteNonQuery(cmd, m_Connection) > 0) - { - cmd.Dispose(); - return true; - } - - cmd.Dispose(); - return false; - } - - public bool CheckToken(UUID principalID, string token, int lifetime) - { - if (System.Environment.TickCount - m_LastExpire > 30000) - DoExpire(); - - SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now', 'localtime', '+" + lifetime.ToString() + - " minutes') where UUID = '" + principalID.ToString() + "' and token = '" + token + "' and validity > datetime('now', 'localtime')"); - - if (ExecuteNonQuery(cmd, m_Connection) > 0) - { - cmd.Dispose(); - return true; - } - - cmd.Dispose(); - - return false; - } - - private void DoExpire() - { - SqliteCommand cmd = new SqliteCommand("delete from tokens where validity < datetime('now', 'localtime')"); - ExecuteNonQuery(cmd, m_Connection); - - cmd.Dispose(); - - m_LastExpire = System.Environment.TickCount; - } - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs b/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs deleted file mode 100644 index d0fd49c..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteAvatarData.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Data; -using System.Reflection; -using System.Threading; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.Sqlite; - -namespace OpenSim.Data.SQLiteNG -{ - /// - /// A SQLite Interface for Avatar Data - /// - public class SQLiteAvatarData : SQLiteGenericTableHandler, - IAvatarData - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public SQLiteAvatarData(string connectionString, string realm) : - base(connectionString, realm, "Avatar") - { - } - - public bool Delete(UUID principalID, string name) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("delete from {0} where `PrincipalID` = :PrincipalID and `Name` = :Name", m_Realm); - cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString()); - cmd.Parameters.AddWithValue(":Name", name); - - try - { - if (ExecuteNonQuery(cmd, m_Connection) > 0) - return true; - - return false; - } - finally - { - //CloseCommand(cmd); - } - } - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs b/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs deleted file mode 100644 index 2e2d717..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteEstateData.cs +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Data; -using System.Reflection; -using log4net; -using Mono.Data.Sqlite; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Data.SQLiteNG -{ - public class SQLiteEstateStore : IEstateDataStore - { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private SqliteConnection m_connection; - private string m_connectionString; - - private FieldInfo[] m_Fields; - private Dictionary m_FieldMap = - new Dictionary(); - - public void Initialise(string connectionString) - { - m_connectionString = connectionString; - - m_log.Info("[ESTATE DB]: Sqlite - connecting: "+m_connectionString); - - m_connection = new SqliteConnection(m_connectionString); - m_connection.Open(); - - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_connection, assem, "EstateStore"); - m.Update(); - - //m_connection.Close(); - // m_connection.Open(); - - Type t = typeof(EstateSettings); - m_Fields = t.GetFields(BindingFlags.NonPublic | - BindingFlags.Instance | - BindingFlags.DeclaredOnly); - - foreach (FieldInfo f in m_Fields) - if (f.Name.Substring(0, 2) == "m_") - m_FieldMap[f.Name.Substring(2)] = f; - } - - private string[] FieldList - { - get { return new List(m_FieldMap.Keys).ToArray(); } - } - - public EstateSettings LoadEstateSettings(UUID regionID, bool create) - { - string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = :RegionID"; - - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = sql; - cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); - - return DoLoad(cmd, regionID, create); - } - - private EstateSettings DoLoad(SqliteCommand cmd, UUID regionID, bool create) - { - EstateSettings es = new EstateSettings(); - es.OnSave += StoreEstateSettings; - - IDataReader r = cmd.ExecuteReader(); - - if (r.Read()) - { - foreach (string name in FieldList) - { - if (m_FieldMap[name].GetValue(es) is bool) - { - int v = Convert.ToInt32(r[name]); - if (v != 0) - m_FieldMap[name].SetValue(es, true); - else - m_FieldMap[name].SetValue(es, false); - } - else if (m_FieldMap[name].GetValue(es) is UUID) - { - UUID uuid = UUID.Zero; - - UUID.TryParse(r[name].ToString(), out uuid); - m_FieldMap[name].SetValue(es, uuid); - } - else - { - m_FieldMap[name].SetValue(es, Convert.ChangeType(r[name], m_FieldMap[name].FieldType)); - } - } - r.Close(); - } - else if (create) - { - r.Close(); - - List names = new List(FieldList); - - names.Remove("EstateID"); - - string sql = "insert into estate_settings ("+String.Join(",", names.ToArray())+") values ( :"+String.Join(", :", names.ToArray())+")"; - - cmd.CommandText = sql; - cmd.Parameters.Clear(); - - foreach (string name in FieldList) - { - if (m_FieldMap[name].GetValue(es) is bool) - { - if ((bool)m_FieldMap[name].GetValue(es)) - cmd.Parameters.AddWithValue(":"+name, "1"); - else - cmd.Parameters.AddWithValue(":"+name, "0"); - } - else - { - cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString()); - } - } - - cmd.ExecuteNonQuery(); - - cmd.CommandText = "select LAST_INSERT_ROWID() as id"; - cmd.Parameters.Clear(); - - r = cmd.ExecuteReader(); - - r.Read(); - - es.EstateID = Convert.ToUInt32(r["id"]); - - r.Close(); - - cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; - cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); - cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); - - // This will throw on dupe key - try - { - cmd.ExecuteNonQuery(); - } - catch (Exception) - { - } - - es.Save(); - } - - LoadBanList(es); - - es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers"); - es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users"); - es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups"); - return es; - } - - public void StoreEstateSettings(EstateSettings es) - { - List fields = new List(FieldList); - fields.Remove("EstateID"); - - List terms = new List(); - - foreach (string f in fields) - terms.Add(f+" = :"+f); - - string sql = "update estate_settings set "+String.Join(", ", terms.ToArray())+" where EstateID = :EstateID"; - - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = sql; - - foreach (string name in FieldList) - { - if (m_FieldMap[name].GetValue(es) is bool) - { - if ((bool)m_FieldMap[name].GetValue(es)) - cmd.Parameters.AddWithValue(":"+name, "1"); - else - cmd.Parameters.AddWithValue(":"+name, "0"); - } - else - { - cmd.Parameters.AddWithValue(":"+name, m_FieldMap[name].GetValue(es).ToString()); - } - } - - cmd.ExecuteNonQuery(); - - SaveBanList(es); - SaveUUIDList(es.EstateID, "estate_managers", es.EstateManagers); - SaveUUIDList(es.EstateID, "estate_users", es.EstateAccess); - SaveUUIDList(es.EstateID, "estate_groups", es.EstateGroups); - } - - private void LoadBanList(EstateSettings es) - { - es.ClearBans(); - - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = "select bannedUUID from estateban where EstateID = :EstateID"; - cmd.Parameters.AddWithValue(":EstateID", es.EstateID); - - IDataReader r = cmd.ExecuteReader(); - - while (r.Read()) - { - EstateBan eb = new EstateBan(); - - UUID uuid = new UUID(); - UUID.TryParse(r["bannedUUID"].ToString(), out uuid); - - eb.BannedUserID = uuid; - eb.BannedHostAddress = "0.0.0.0"; - eb.BannedHostIPMask = "0.0.0.0"; - es.AddBan(eb); - } - r.Close(); - } - - private void SaveBanList(EstateSettings es) - { - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = "delete from estateban where EstateID = :EstateID"; - cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); - - cmd.ExecuteNonQuery(); - - cmd.Parameters.Clear(); - - cmd.CommandText = "insert into estateban (EstateID, bannedUUID, bannedIp, bannedIpHostMask, bannedNameMask) values ( :EstateID, :bannedUUID, '', '', '' )"; - - foreach (EstateBan b in es.EstateBans) - { - cmd.Parameters.AddWithValue(":EstateID", es.EstateID.ToString()); - cmd.Parameters.AddWithValue(":bannedUUID", b.BannedUserID.ToString()); - - cmd.ExecuteNonQuery(); - cmd.Parameters.Clear(); - } - } - - void SaveUUIDList(uint EstateID, string table, UUID[] data) - { - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = "delete from "+table+" where EstateID = :EstateID"; - cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString()); - - cmd.ExecuteNonQuery(); - - cmd.Parameters.Clear(); - - cmd.CommandText = "insert into "+table+" (EstateID, uuid) values ( :EstateID, :uuid )"; - - foreach (UUID uuid in data) - { - cmd.Parameters.AddWithValue(":EstateID", EstateID.ToString()); - cmd.Parameters.AddWithValue(":uuid", uuid.ToString()); - - cmd.ExecuteNonQuery(); - cmd.Parameters.Clear(); - } - } - - UUID[] LoadUUIDList(uint EstateID, string table) - { - List uuids = new List(); - - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = "select uuid from "+table+" where EstateID = :EstateID"; - cmd.Parameters.AddWithValue(":EstateID", EstateID); - - IDataReader r = cmd.ExecuteReader(); - - while (r.Read()) - { - // EstateBan eb = new EstateBan(); - - UUID uuid = new UUID(); - UUID.TryParse(r["uuid"].ToString(), out uuid); - - uuids.Add(uuid); - } - r.Close(); - - return uuids.ToArray(); - } - - public EstateSettings LoadEstateSettings(int estateID) - { - string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID :EstateID"; - - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = sql; - cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); - - return DoLoad(cmd, UUID.Zero, false); - } - - public List GetEstates(string search) - { - List result = new List(); - - string sql = "select EstateID from estate_settings where estate_settings.EstateName :EstateName"; - - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = sql; - cmd.Parameters.AddWithValue(":EstateName", search); - - IDataReader r = cmd.ExecuteReader(); - - while (r.Read()) - { - result.Add(Convert.ToInt32(r["EstateID"])); - } - r.Close(); - - return result; - } - - public bool LinkRegion(UUID regionID, int estateID) - { - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; - cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); - cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); - - if (cmd.ExecuteNonQuery() == 0) - return false; - - return true; - } - - public List GetRegions(int estateID) - { - return new List(); - } - - public bool DeleteEstate(int estateID) - { - return false; - } - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteFramework.cs b/OpenSim/Data/SQLiteNG/SQLiteFramework.cs deleted file mode 100644 index f0ddc59..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteFramework.cs +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.Sqlite; - -namespace OpenSim.Data.SQLiteNG -{ - /// - /// A database interface class to a user profile storage system - /// - public class SQLiteFramework - { - protected Object m_lockObject = new Object(); - - protected SQLiteFramework(string connectionString) - { - } - - ////////////////////////////////////////////////////////////// - // - // All non queries are funneled through one connection - // to increase performance a little - // - protected int ExecuteNonQuery(SqliteCommand cmd, SqliteConnection connection) - { - lock (connection) - { -/* - SqliteConnection newConnection = - (SqliteConnection)((ICloneable)connection).Clone(); - newConnection.Open(); - - cmd.Connection = newConnection; -*/ - cmd.Connection = connection; - //Console.WriteLine("XXX " + cmd.CommandText); - - return cmd.ExecuteNonQuery(); - } - } - - protected IDataReader ExecuteReader(SqliteCommand cmd, SqliteConnection connection) - { - lock (connection) - { - //SqliteConnection newConnection = - // (SqliteConnection)((ICloneable)connection).Clone(); - //newConnection.Open(); - - //cmd.Connection = newConnection; - cmd.Connection = connection; - //Console.WriteLine("XXX " + cmd.CommandText); - - return cmd.ExecuteReader(); - } - } - - protected void CloseCommand(SqliteCommand cmd) - { - cmd.Connection.Close(); - cmd.Connection.Dispose(); - cmd.Dispose(); - } - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs b/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs deleted file mode 100644 index 702a1d8..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteFriendsData.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.Sqlite; - -namespace OpenSim.Data.SQLiteNG -{ - public class SQLiteFriendsData : SQLiteGenericTableHandler, IFriendsData - { - public SQLiteFriendsData(string connectionString, string realm) - : base(connectionString, realm, "FriendsStore") - { - } - - public FriendsData[] GetFriends(UUID userID) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = :PrincipalID", m_Realm); - cmd.Parameters.AddWithValue(":PrincipalID", userID.ToString()); - - return DoQuery(cmd); - - } - - public bool Delete(UUID principalID, string friend) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm); - cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString()); - cmd.Parameters.AddWithValue(":Friend", friend); - - ExecuteNonQuery(cmd, cmd.Connection); - - return true; - } - - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs deleted file mode 100644 index 632c5bf..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteGenericTableHandler.cs +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Data; -using System.Reflection; -using log4net; -using Mono.Data.Sqlite; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Data.SQLiteNG -{ - public class SQLiteGenericTableHandler : SQLiteFramework where T: class, new() - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Dictionary m_Fields = - new Dictionary(); - - protected List m_ColumnNames = null; - protected string m_Realm; - protected FieldInfo m_DataField = null; - - protected static SqliteConnection m_Connection; - private static bool m_initialized; - - public SQLiteGenericTableHandler(string connectionString, - string realm, string storeName) : base(connectionString) - { - m_Realm = realm; - - if (!m_initialized) - { - m_Connection = new SqliteConnection(connectionString); - Console.WriteLine(string.Format("OPENING CONNECTION FOR {0} USING {1}", storeName, connectionString)); - m_Connection.Open(); - - if (storeName != String.Empty) - { - Assembly assem = GetType().Assembly; - //SqliteConnection newConnection = - // (SqliteConnection)((ICloneable)m_Connection).Clone(); - //newConnection.Open(); - - //Migration m = new Migration(newConnection, assem, storeName); - Migration m = new Migration(m_Connection, assem, storeName); - m.Update(); - //newConnection.Close(); - //newConnection.Dispose(); - } - - m_initialized = true; - } - - Type t = typeof(T); - FieldInfo[] fields = t.GetFields(BindingFlags.Public | - BindingFlags.Instance | - BindingFlags.DeclaredOnly); - - if (fields.Length == 0) - return; - - foreach (FieldInfo f in fields) - { - if (f.Name != "Data") - m_Fields[f.Name] = f; - else - m_DataField = f; - } - } - - private void CheckColumnNames(IDataReader reader) - { - if (m_ColumnNames != null) - return; - - m_ColumnNames = new List(); - - DataTable schemaTable = reader.GetSchemaTable(); - foreach (DataRow row in schemaTable.Rows) - { - if (row["ColumnName"] != null && - (!m_Fields.ContainsKey(row["ColumnName"].ToString()))) - m_ColumnNames.Add(row["ColumnName"].ToString()); - } - } - - public T[] Get(string field, string key) - { - return Get(new string[] { field }, new string[] { key }); - } - - public T[] Get(string[] fields, string[] keys) - { - if (fields.Length != keys.Length) - return new T[0]; - - List terms = new List(); - - SqliteCommand cmd = new SqliteCommand(); - - for (int i = 0 ; i < fields.Length ; i++) - { - cmd.Parameters.Add(new SqliteParameter(":" + fields[i], keys[i])); - terms.Add("`" + fields[i] + "` = :" + fields[i]); - } - - string where = String.Join(" and ", terms.ToArray()); - - string query = String.Format("select * from {0} where {1}", - m_Realm, where); - - cmd.CommandText = query; - - return DoQuery(cmd); - } - - protected T[] DoQuery(SqliteCommand cmd) - { - IDataReader reader = ExecuteReader(cmd, m_Connection); - if (reader == null) - return new T[0]; - - CheckColumnNames(reader); - - List result = new List(); - - while (reader.Read()) - { - T row = new T(); - - foreach (string name in m_Fields.Keys) - { - if (m_Fields[name].GetValue(row) is bool) - { - int v = Convert.ToInt32(reader[name]); - m_Fields[name].SetValue(row, v != 0 ? true : false); - } - else if (m_Fields[name].GetValue(row) is UUID) - { - UUID uuid = UUID.Zero; - - UUID.TryParse(reader[name].ToString(), out uuid); - m_Fields[name].SetValue(row, uuid); - } - else if (m_Fields[name].GetValue(row) is int) - { - int v = Convert.ToInt32(reader[name]); - m_Fields[name].SetValue(row, v); - } - else - { - m_Fields[name].SetValue(row, reader[name]); - } - } - - if (m_DataField != null) - { - Dictionary data = - new Dictionary(); - - foreach (string col in m_ColumnNames) - { - data[col] = reader[col].ToString(); - if (data[col] == null) - data[col] = String.Empty; - } - - m_DataField.SetValue(row, data); - } - - result.Add(row); - } - - //CloseCommand(cmd); - - return result.ToArray(); - } - - public T[] Get(string where) - { - SqliteCommand cmd = new SqliteCommand(); - - string query = String.Format("select * from {0} where {1}", - m_Realm, where); - - cmd.CommandText = query; - - return DoQuery(cmd); - } - - public bool Store(T row) - { - SqliteCommand cmd = new SqliteCommand(); - - string query = ""; - List names = new List(); - List values = new List(); - - foreach (FieldInfo fi in m_Fields.Values) - { - names.Add(fi.Name); - values.Add(":" + fi.Name); - cmd.Parameters.Add(new SqliteParameter(":" + fi.Name, fi.GetValue(row).ToString())); - } - - if (m_DataField != null) - { - Dictionary data = - (Dictionary)m_DataField.GetValue(row); - - foreach (KeyValuePair kvp in data) - { - names.Add(kvp.Key); - values.Add(":" + kvp.Key); - cmd.Parameters.Add(new SqliteParameter(":" + kvp.Key, kvp.Value)); - } - } - - query = String.Format("replace into {0} (`", m_Realm) + String.Join("`,`", names.ToArray()) + "`) values (" + String.Join(",", values.ToArray()) + ")"; - - cmd.CommandText = query; - - if (ExecuteNonQuery(cmd, m_Connection) > 0) - return true; - - return false; - } - - public bool Delete(string field, string val) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("delete from {0} where `{1}` = :{1}", m_Realm, field); - cmd.Parameters.Add(new SqliteParameter(field, val)); - - if (ExecuteNonQuery(cmd, m_Connection) > 0) - return true; - - return false; - } - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs b/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs deleted file mode 100644 index 9207ca3..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteInventoryStore.cs +++ /dev/null @@ -1,909 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Data; -using System.Reflection; -using log4net; -using Mono.Data.Sqlite; -using OpenMetaverse; -using OpenSim.Framework; - -namespace OpenSim.Data.SQLiteNG -{ - /// - /// An Inventory Interface to the SQLite database - /// - public class SQLiteInventoryStore : SQLiteUtil, IInventoryDataPlugin - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private const string invItemsSelect = "select * from inventoryitems"; - private const string invFoldersSelect = "select * from inventoryfolders"; - - private static SqliteConnection conn; - private static DataSet ds; - private static SqliteDataAdapter invItemsDa; - private static SqliteDataAdapter invFoldersDa; - - private static bool m_Initialized = false; - - public void Initialise() - { - m_log.Info("[SQLiteInventoryData]: " + Name + " cannot be default-initialized!"); - throw new PluginNotInitialisedException(Name); - } - - /// - /// - /// Initialises Inventory interface - /// Loads and initialises a new SQLite connection and maintains it. - /// use default URI if connect string string is empty. - /// - /// - /// connect string - public void Initialise(string dbconnect) - { - if (!m_Initialized) - { - m_Initialized = true; - - if (dbconnect == string.Empty) - { - dbconnect = "URI=file:inventoryStore.db,version=3"; - } - m_log.Info("[INVENTORY DB]: Sqlite - connecting: " + dbconnect); - conn = new SqliteConnection(dbconnect); - - conn.Open(); - - Assembly assem = GetType().Assembly; - Migration m = new Migration(conn, assem, "InventoryStore"); - m.Update(); - - SqliteCommand itemsSelectCmd = new SqliteCommand(invItemsSelect, conn); - invItemsDa = new SqliteDataAdapter(itemsSelectCmd); - // SqliteCommandBuilder primCb = new SqliteCommandBuilder(primDa); - - SqliteCommand foldersSelectCmd = new SqliteCommand(invFoldersSelect, conn); - invFoldersDa = new SqliteDataAdapter(foldersSelectCmd); - - ds = new DataSet(); - - ds.Tables.Add(createInventoryFoldersTable()); - invFoldersDa.Fill(ds.Tables["inventoryfolders"]); - setupFoldersCommands(invFoldersDa, conn); - CreateDataSetMapping(invFoldersDa, "inventoryfolders"); - m_log.Info("[INVENTORY DB]: Populated Inventory Folders Definitions"); - - ds.Tables.Add(createInventoryItemsTable()); - invItemsDa.Fill(ds.Tables["inventoryitems"]); - setupItemsCommands(invItemsDa, conn); - CreateDataSetMapping(invItemsDa, "inventoryitems"); - m_log.Info("[INVENTORY DB]: Populated Inventory Items Definitions"); - - ds.AcceptChanges(); - } - } - - /// - /// Closes the inventory interface - /// - public void Dispose() - { - if (conn != null) - { - conn.Close(); - conn = null; - } - if (invItemsDa != null) - { - invItemsDa.Dispose(); - invItemsDa = null; - } - if (invFoldersDa != null) - { - invFoldersDa.Dispose(); - invFoldersDa = null; - } - if (ds != null) - { - ds.Dispose(); - ds = null; - } - } - - /// - /// - /// - /// - /// - public InventoryItemBase buildItem(DataRow row) - { - InventoryItemBase item = new InventoryItemBase(); - item.ID = new UUID((string) row["UUID"]); - item.AssetID = new UUID((string) row["assetID"]); - item.AssetType = Convert.ToInt32(row["assetType"]); - item.InvType = Convert.ToInt32(row["invType"]); - item.Folder = new UUID((string) row["parentFolderID"]); - item.Owner = new UUID((string) row["avatarID"]); - item.CreatorId = (string)row["creatorsID"]; - item.Name = (string) row["inventoryName"]; - item.Description = (string) row["inventoryDescription"]; - - item.NextPermissions = Convert.ToUInt32(row["inventoryNextPermissions"]); - item.CurrentPermissions = Convert.ToUInt32(row["inventoryCurrentPermissions"]); - item.BasePermissions = Convert.ToUInt32(row["inventoryBasePermissions"]); - item.EveryOnePermissions = Convert.ToUInt32(row["inventoryEveryOnePermissions"]); - item.GroupPermissions = Convert.ToUInt32(row["inventoryGroupPermissions"]); - - // new fields - if (!Convert.IsDBNull(row["salePrice"])) - item.SalePrice = Convert.ToInt32(row["salePrice"]); - - if (!Convert.IsDBNull(row["saleType"])) - item.SaleType = Convert.ToByte(row["saleType"]); - - if (!Convert.IsDBNull(row["creationDate"])) - item.CreationDate = Convert.ToInt32(row["creationDate"]); - - if (!Convert.IsDBNull(row["groupID"])) - item.GroupID = new UUID((string)row["groupID"]); - - if (!Convert.IsDBNull(row["groupOwned"])) - item.GroupOwned = Convert.ToBoolean(row["groupOwned"]); - - if (!Convert.IsDBNull(row["Flags"])) - item.Flags = Convert.ToUInt32(row["Flags"]); - - return item; - } - - /// - /// Fill a database row with item data - /// - /// - /// - private static void fillItemRow(DataRow row, InventoryItemBase item) - { - row["UUID"] = item.ID.ToString(); - row["assetID"] = item.AssetID.ToString(); - row["assetType"] = item.AssetType; - row["invType"] = item.InvType; - row["parentFolderID"] = item.Folder.ToString(); - row["avatarID"] = item.Owner.ToString(); - row["creatorsID"] = item.CreatorId.ToString(); - row["inventoryName"] = item.Name; - row["inventoryDescription"] = item.Description; - - row["inventoryNextPermissions"] = item.NextPermissions; - row["inventoryCurrentPermissions"] = item.CurrentPermissions; - row["inventoryBasePermissions"] = item.BasePermissions; - row["inventoryEveryOnePermissions"] = item.EveryOnePermissions; - row["inventoryGroupPermissions"] = item.GroupPermissions; - - // new fields - row["salePrice"] = item.SalePrice; - row["saleType"] = item.SaleType; - row["creationDate"] = item.CreationDate; - row["groupID"] = item.GroupID.ToString(); - row["groupOwned"] = item.GroupOwned; - row["flags"] = item.Flags; - } - - /// - /// Add inventory folder - /// - /// Folder base - /// true=create folder. false=update existing folder - /// nasty - private void addFolder(InventoryFolderBase folder, bool add) - { - lock (ds) - { - DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; - - DataRow inventoryRow = inventoryFolderTable.Rows.Find(folder.ID.ToString()); - if (inventoryRow == null) - { - if (! add) - m_log.ErrorFormat("Interface Misuse: Attempting to Update non-existant inventory folder: {0}", folder.ID); - - inventoryRow = inventoryFolderTable.NewRow(); - fillFolderRow(inventoryRow, folder); - inventoryFolderTable.Rows.Add(inventoryRow); - } - else - { - if (add) - m_log.ErrorFormat("Interface Misuse: Attempting to Add inventory folder that already exists: {0}", folder.ID); - - fillFolderRow(inventoryRow, folder); - } - - invFoldersDa.Update(ds, "inventoryfolders"); - } - } - - /// - /// Move an inventory folder - /// - /// folder base - private void moveFolder(InventoryFolderBase folder) - { - lock (ds) - { - DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; - - DataRow inventoryRow = inventoryFolderTable.Rows.Find(folder.ID.ToString()); - if (inventoryRow == null) - { - inventoryRow = inventoryFolderTable.NewRow(); - fillFolderRow(inventoryRow, folder); - inventoryFolderTable.Rows.Add(inventoryRow); - } - else - { - moveFolderRow(inventoryRow, folder); - } - - invFoldersDa.Update(ds, "inventoryfolders"); - } - } - - /// - /// add an item in inventory - /// - /// the item - /// true=add item ; false=update existing item - private void addItem(InventoryItemBase item, bool add) - { - lock (ds) - { - DataTable inventoryItemTable = ds.Tables["inventoryitems"]; - - DataRow inventoryRow = inventoryItemTable.Rows.Find(item.ID.ToString()); - if (inventoryRow == null) - { - if (!add) - m_log.ErrorFormat("[INVENTORY DB]: Interface Misuse: Attempting to Update non-existant inventory item: {0}", item.ID); - - inventoryRow = inventoryItemTable.NewRow(); - fillItemRow(inventoryRow, item); - inventoryItemTable.Rows.Add(inventoryRow); - } - else - { - if (add) - m_log.ErrorFormat("[INVENTORY DB]: Interface Misuse: Attempting to Add inventory item that already exists: {0}", item.ID); - - fillItemRow(inventoryRow, item); - } - - invItemsDa.Update(ds, "inventoryitems"); - - DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; - - inventoryRow = inventoryFolderTable.Rows.Find(item.Folder.ToString()); - if (inventoryRow != null) //MySQL doesn't throw an exception here, so sqlite shouldn't either. - inventoryRow["version"] = (int)inventoryRow["version"] + 1; - - invFoldersDa.Update(ds, "inventoryfolders"); - } - } - - /// - /// TODO : DataSet commit - /// - public void Shutdown() - { - // TODO: DataSet commit - } - - /// - /// The name of this DB provider - /// - /// Name of DB provider - public string Name - { - get { return "SQLite Inventory Data Interface"; } - } - - /// - /// Returns the version of this DB provider - /// - /// A string containing the DB provider version - public string Version - { - get - { - Module module = GetType().Module; - // string dllName = module.Assembly.ManifestModule.Name; - Version dllVersion = module.Assembly.GetName().Version; - - - return - string.Format("{0}.{1}.{2}.{3}", dllVersion.Major, dllVersion.Minor, dllVersion.Build, - dllVersion.Revision); - } - } - - /// - /// Returns a list of inventory items contained within the specified folder - /// - /// The UUID of the target folder - /// A List of InventoryItemBase items - public List getInventoryInFolder(UUID folderID) - { - lock (ds) - { - List retval = new List(); - DataTable inventoryItemTable = ds.Tables["inventoryitems"]; - string selectExp = "parentFolderID = '" + folderID + "'"; - DataRow[] rows = inventoryItemTable.Select(selectExp); - foreach (DataRow row in rows) - { - retval.Add(buildItem(row)); - } - - return retval; - } - } - - /// - /// Returns a list of the root folders within a users inventory - /// - /// The user whos inventory is to be searched - /// A list of folder objects - public List getUserRootFolders(UUID user) - { - return new List(); - } - - // see InventoryItemBase.getUserRootFolder - public InventoryFolderBase getUserRootFolder(UUID user) - { - lock (ds) - { - List folders = new List(); - DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; - string selectExp = "agentID = '" + user + "' AND parentID = '" + UUID.Zero + "'"; - DataRow[] rows = inventoryFolderTable.Select(selectExp); - foreach (DataRow row in rows) - { - folders.Add(buildFolder(row)); - } - - // There should only ever be one root folder for a user. However, if there's more - // than one we'll simply use the first one rather than failing. It would be even - // nicer to print some message to this effect, but this feels like it's too low a - // to put such a message out, and it's too minor right now to spare the time to - // suitably refactor. - if (folders.Count > 0) - { - return folders[0]; - } - - return null; - } - } - - /// - /// Append a list of all the child folders of a parent folder - /// - /// list where folders will be appended - /// ID of parent - protected void getInventoryFolders(ref List folders, UUID parentID) - { - lock (ds) - { - DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; - string selectExp = "parentID = '" + parentID + "'"; - DataRow[] rows = inventoryFolderTable.Select(selectExp); - foreach (DataRow row in rows) - { - folders.Add(buildFolder(row)); - } - - } - } - - /// - /// Returns a list of inventory folders contained in the folder 'parentID' - /// - /// The folder to get subfolders for - /// A list of inventory folders - public List getInventoryFolders(UUID parentID) - { - List folders = new List(); - getInventoryFolders(ref folders, parentID); - return folders; - } - - /// - /// See IInventoryDataPlugin - /// - /// - /// - public List getFolderHierarchy(UUID parentID) - { - /* Note: There are subtle changes between this implementation of getFolderHierarchy and the previous one - * - We will only need to hit the database twice instead of n times. - * - We assume the database is well-formed - no stranded/dangling folders, all folders in heirarchy owned - * by the same person, each user only has 1 inventory heirarchy - * - The returned list is not ordered, instead of breadth-first ordered - There are basically 2 usage cases for getFolderHeirarchy: - 1) Getting the user's entire inventory heirarchy when they log in - 2) Finding a subfolder heirarchy to delete when emptying the trash. - This implementation will pull all inventory folders from the database, and then prune away any folder that - is not part of the requested sub-heirarchy. The theory is that it is cheaper to make 1 request from the - database than to make n requests. This pays off only if requested heirarchy is large. - By making this choice, we are making the worst case better at the cost of making the best case worse - - Francis - */ - - List folders = new List(); - DataRow[] folderRows = null, parentRow; - InventoryFolderBase parentFolder = null; - lock (ds) - { - /* Fetch the parent folder from the database to determine the agent ID. - * Then fetch all inventory folders for that agent from the agent ID. - */ - DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; - string selectExp = "UUID = '" + parentID + "'"; - parentRow = inventoryFolderTable.Select(selectExp); // Assume at most 1 result - if (parentRow.GetLength(0) >= 1) // No result means parent folder does not exist - { - parentFolder = buildFolder(parentRow[0]); - UUID agentID = parentFolder.Owner; - selectExp = "agentID = '" + agentID + "'"; - folderRows = inventoryFolderTable.Select(selectExp); - } - - if (folderRows != null && folderRows.GetLength(0) >= 1) // No result means parent folder does not exist - { // or has no children - /* if we're querying the root folder, just return an unordered list of all folders in the user's - * inventory - */ - if (parentFolder.ParentID == UUID.Zero) - { - foreach (DataRow row in folderRows) - { - InventoryFolderBase curFolder = buildFolder(row); - if (curFolder.ID != parentID) // Return all folders except the parent folder of heirarchy - folders.Add(buildFolder(row)); - } - } // If requesting root folder - /* else we are querying a non-root folder. We currently have a list of all of the user's folders, - * we must construct a list of all folders in the heirarchy below parentID. - * Our first step will be to construct a hash table of all folders, indexed by parent ID. - * Once we have constructed the hash table, we will do a breadth-first traversal on the tree using the - * hash table to find child folders. - */ - else - { // Querying a non-root folder - - // Build a hash table of all user's inventory folders, indexed by each folder's parent ID - Dictionary> hashtable = - new Dictionary>(folderRows.GetLength(0)); - - foreach (DataRow row in folderRows) - { - InventoryFolderBase curFolder = buildFolder(row); - if (curFolder.ParentID != UUID.Zero) // Discard root of tree - not needed - { - if (hashtable.ContainsKey(curFolder.ParentID)) - { - // Current folder already has a sibling - append to sibling list - hashtable[curFolder.ParentID].Add(curFolder); - } - else - { - List siblingList = new List(); - siblingList.Add(curFolder); - // Current folder has no known (yet) siblings - hashtable.Add(curFolder.ParentID, siblingList); - } - } - } // For all inventory folders - - // Note: Could release the ds lock here - we don't access folderRows or the database anymore. - // This is somewhat of a moot point as the callers of this function usually lock db anyways. - - if (hashtable.ContainsKey(parentID)) // if requested folder does have children - folders.AddRange(hashtable[parentID]); - - // BreadthFirstSearch build inventory tree **Note: folders.Count is *not* static - for (int i = 0; i < folders.Count; i++) - if (hashtable.ContainsKey(folders[i].ID)) - folders.AddRange(hashtable[folders[i].ID]); - - } // if requesting a subfolder heirarchy - } // if folder parentID exists and has children - } // lock ds - return folders; - } - - /// - /// Returns an inventory item by its UUID - /// - /// The UUID of the item to be returned - /// A class containing item information - public InventoryItemBase getInventoryItem(UUID item) - { - lock (ds) - { - DataRow row = ds.Tables["inventoryitems"].Rows.Find(item.ToString()); - if (row != null) - { - return buildItem(row); - } - else - { - return null; - } - } - } - - /// - /// Returns a specified inventory folder by its UUID - /// - /// The UUID of the folder to be returned - /// A class containing folder information - public InventoryFolderBase getInventoryFolder(UUID folder) - { - // TODO: Deep voodoo here. If you enable this code then - // multi region breaks. No idea why, but I figured it was - // better to leave multi region at this point. It does mean - // that you don't get to see system textures why creating - // clothes and the like. :( - lock (ds) - { - DataRow row = ds.Tables["inventoryfolders"].Rows.Find(folder.ToString()); - if (row != null) - { - return buildFolder(row); - } - else - { - return null; - } - } - } - - /// - /// Creates a new inventory item based on item - /// - /// The item to be created - public void addInventoryItem(InventoryItemBase item) - { - addItem(item, true); - } - - /// - /// Updates an inventory item with item (updates based on ID) - /// - /// The updated item - public void updateInventoryItem(InventoryItemBase item) - { - addItem(item, false); - } - - /// - /// Delete an inventory item - /// - /// The item UUID - public void deleteInventoryItem(UUID itemID) - { - lock (ds) - { - DataTable inventoryItemTable = ds.Tables["inventoryitems"]; - - DataRow inventoryRow = inventoryItemTable.Rows.Find(itemID.ToString()); - if (inventoryRow != null) - { - inventoryRow.Delete(); - } - - invItemsDa.Update(ds, "inventoryitems"); - } - } - - public InventoryItemBase queryInventoryItem(UUID itemID) - { - return getInventoryItem(itemID); - } - - public InventoryFolderBase queryInventoryFolder(UUID folderID) - { - return getInventoryFolder(folderID); - } - - /// - /// Delete all items in the specified folder - /// - /// id of the folder, whose item content should be deleted - /// this is horribly inefficient, but I don't want to ruin the overall structure of this implementation - private void deleteItemsInFolder(UUID folderId) - { - List items = getInventoryInFolder(folderId); - - foreach (InventoryItemBase i in items) - deleteInventoryItem(i.ID); - } - - /// - /// Adds a new folder specified by folder - /// - /// The inventory folder - public void addInventoryFolder(InventoryFolderBase folder) - { - addFolder(folder, true); - } - - /// - /// Updates a folder based on its ID with folder - /// - /// The inventory folder - public void updateInventoryFolder(InventoryFolderBase folder) - { - addFolder(folder, false); - } - - /// - /// Moves a folder based on its ID with folder - /// - /// The inventory folder - public void moveInventoryFolder(InventoryFolderBase folder) - { - moveFolder(folder); - } - - /// - /// Delete a folder - /// - /// - /// This will clean-up any child folders and child items as well - /// - /// the folder UUID - public void deleteInventoryFolder(UUID folderID) - { - lock (ds) - { - List subFolders = getFolderHierarchy(folderID); - - DataTable inventoryFolderTable = ds.Tables["inventoryfolders"]; - DataRow inventoryRow; - - //Delete all sub-folders - foreach (InventoryFolderBase f in subFolders) - { - inventoryRow = inventoryFolderTable.Rows.Find(f.ID.ToString()); - if (inventoryRow != null) - { - deleteItemsInFolder(f.ID); - inventoryRow.Delete(); - } - } - - //Delete the actual row - inventoryRow = inventoryFolderTable.Rows.Find(folderID.ToString()); - if (inventoryRow != null) - { - deleteItemsInFolder(folderID); - inventoryRow.Delete(); - } - - invFoldersDa.Update(ds, "inventoryfolders"); - } - } - - /*********************************************************************** - * - * Data Table definitions - * - **********************************************************************/ - - protected void CreateDataSetMapping(IDataAdapter da, string tableName) - { - ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName); - foreach (DataColumn col in ds.Tables[tableName].Columns) - { - dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName); - } - } - - /// - /// Create the "inventoryitems" table - /// - private static DataTable createInventoryItemsTable() - { - DataTable inv = new DataTable("inventoryitems"); - - createCol(inv, "UUID", typeof (String)); //inventoryID - createCol(inv, "assetID", typeof (String)); - createCol(inv, "assetType", typeof (Int32)); - createCol(inv, "invType", typeof (Int32)); - createCol(inv, "parentFolderID", typeof (String)); - createCol(inv, "avatarID", typeof (String)); - createCol(inv, "creatorsID", typeof (String)); - - createCol(inv, "inventoryName", typeof (String)); - createCol(inv, "inventoryDescription", typeof (String)); - // permissions - createCol(inv, "inventoryNextPermissions", typeof (Int32)); - createCol(inv, "inventoryCurrentPermissions", typeof (Int32)); - createCol(inv, "inventoryBasePermissions", typeof (Int32)); - createCol(inv, "inventoryEveryOnePermissions", typeof (Int32)); - createCol(inv, "inventoryGroupPermissions", typeof (Int32)); - - // sale info - createCol(inv, "salePrice", typeof(Int32)); - createCol(inv, "saleType", typeof(Byte)); - - // creation date - createCol(inv, "creationDate", typeof(Int32)); - - // group info - createCol(inv, "groupID", typeof(String)); - createCol(inv, "groupOwned", typeof(Boolean)); - - // Flags - createCol(inv, "flags", typeof(UInt32)); - - inv.PrimaryKey = new DataColumn[] { inv.Columns["UUID"] }; - return inv; - } - - /// - /// Creates the "inventoryfolders" table - /// - /// - private static DataTable createInventoryFoldersTable() - { - DataTable fol = new DataTable("inventoryfolders"); - - createCol(fol, "UUID", typeof (String)); //folderID - createCol(fol, "name", typeof (String)); - createCol(fol, "agentID", typeof (String)); - createCol(fol, "parentID", typeof (String)); - createCol(fol, "type", typeof (Int32)); - createCol(fol, "version", typeof (Int32)); - - fol.PrimaryKey = new DataColumn[] {fol.Columns["UUID"]}; - return fol; - } - - /// - /// - /// - /// - /// - private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) - { - lock (ds) - { - da.InsertCommand = createInsertCommand("inventoryitems", ds.Tables["inventoryitems"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("inventoryitems", "UUID=:UUID", ds.Tables["inventoryitems"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from inventoryitems where UUID = :UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - } - - /// - /// - /// - /// - /// - private void setupFoldersCommands(SqliteDataAdapter da, SqliteConnection conn) - { - lock (ds) - { - da.InsertCommand = createInsertCommand("inventoryfolders", ds.Tables["inventoryfolders"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("inventoryfolders", "UUID=:UUID", ds.Tables["inventoryfolders"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from inventoryfolders where UUID = :UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - } - - /// - /// - /// - /// - /// - private static InventoryFolderBase buildFolder(DataRow row) - { - InventoryFolderBase folder = new InventoryFolderBase(); - folder.ID = new UUID((string) row["UUID"]); - folder.Name = (string) row["name"]; - folder.Owner = new UUID((string) row["agentID"]); - folder.ParentID = new UUID((string) row["parentID"]); - folder.Type = Convert.ToInt16(row["type"]); - folder.Version = Convert.ToUInt16(row["version"]); - return folder; - } - - /// - /// - /// - /// - /// - private static void fillFolderRow(DataRow row, InventoryFolderBase folder) - { - row["UUID"] = folder.ID.ToString(); - row["name"] = folder.Name; - row["agentID"] = folder.Owner.ToString(); - row["parentID"] = folder.ParentID.ToString(); - row["type"] = folder.Type; - row["version"] = folder.Version; - } - - /// - /// - /// - /// - /// - private static void moveFolderRow(DataRow row, InventoryFolderBase folder) - { - row["UUID"] = folder.ID.ToString(); - row["parentID"] = folder.ParentID.ToString(); - } - - public List fetchActiveGestures (UUID avatarID) - { - lock (ds) - { - List items = new List(); - - DataTable inventoryItemTable = ds.Tables["inventoryitems"]; - string selectExp - = "avatarID = '" + avatarID + "' AND assetType = " + (int)AssetType.Gesture + " AND flags = 1"; - //m_log.DebugFormat("[SQL]: sql = " + selectExp); - DataRow[] rows = inventoryItemTable.Select(selectExp); - foreach (DataRow row in rows) - { - items.Add(buildItem(row)); - } - return items; - } - } - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs b/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs deleted file mode 100644 index 289d626..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteRegionData.cs +++ /dev/null @@ -1,2321 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Data; -using System.Drawing; -using System.IO; -using System.Reflection; -using log4net; -using Mono.Data.Sqlite; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Data.SQLiteNG -{ - /// - /// A RegionData Interface to the SQLite database - /// - public class SQLiteRegionData : IRegionDataStore - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private const string primSelect = "select * from prims"; - private const string shapeSelect = "select * from primshapes"; - private const string itemsSelect = "select * from primitems"; - private const string terrainSelect = "select * from terrain limit 1"; - private const string landSelect = "select * from land"; - private const string landAccessListSelect = "select distinct * from landaccesslist"; - private const string regionbanListSelect = "select * from regionban"; - private const string regionSettingsSelect = "select * from regionsettings"; - - private DataSet ds; - private SqliteDataAdapter primDa; - private SqliteDataAdapter shapeDa; - private SqliteDataAdapter itemsDa; - private SqliteDataAdapter terrainDa; - private SqliteDataAdapter landDa; - private SqliteDataAdapter landAccessListDa; - private SqliteDataAdapter regionSettingsDa; - - private SqliteConnection m_conn; - - private String m_connectionString; - - // Temporary attribute while this is experimental - - /*********************************************************************** - * - * Public Interface Functions - * - **********************************************************************/ - - /// - /// See IRegionDataStore - /// - /// Initialises RegionData Interface - /// Loads and initialises a new SQLite connection and maintains it. - /// - /// - /// the connection string - public void Initialise(string connectionString) - { - try - { - m_connectionString = connectionString; - - ds = new DataSet("Region"); - - m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); - m_conn = new SqliteConnection(m_connectionString); - m_conn.Open(); - - SqliteCommand primSelectCmd = new SqliteCommand(primSelect, m_conn); - primDa = new SqliteDataAdapter(primSelectCmd); - - SqliteCommand shapeSelectCmd = new SqliteCommand(shapeSelect, m_conn); - shapeDa = new SqliteDataAdapter(shapeSelectCmd); - // SqliteCommandBuilder shapeCb = new SqliteCommandBuilder(shapeDa); - - SqliteCommand itemsSelectCmd = new SqliteCommand(itemsSelect, m_conn); - itemsDa = new SqliteDataAdapter(itemsSelectCmd); - - SqliteCommand terrainSelectCmd = new SqliteCommand(terrainSelect, m_conn); - terrainDa = new SqliteDataAdapter(terrainSelectCmd); - - SqliteCommand landSelectCmd = new SqliteCommand(landSelect, m_conn); - landDa = new SqliteDataAdapter(landSelectCmd); - - SqliteCommand landAccessListSelectCmd = new SqliteCommand(landAccessListSelect, m_conn); - landAccessListDa = new SqliteDataAdapter(landAccessListSelectCmd); - - SqliteCommand regionSettingsSelectCmd = new SqliteCommand(regionSettingsSelect, m_conn); - regionSettingsDa = new SqliteDataAdapter(regionSettingsSelectCmd); - // This actually does the roll forward assembly stuff - Assembly assem = GetType().Assembly; - Migration m = new Migration(m_conn, assem, "RegionStore"); - m.Update(); - - lock (ds) - { - ds.Tables.Add(createPrimTable()); - setupPrimCommands(primDa, m_conn); - - ds.Tables.Add(createShapeTable()); - setupShapeCommands(shapeDa, m_conn); - - ds.Tables.Add(createItemsTable()); - setupItemsCommands(itemsDa, m_conn); - - ds.Tables.Add(createTerrainTable()); - setupTerrainCommands(terrainDa, m_conn); - - ds.Tables.Add(createLandTable()); - setupLandCommands(landDa, m_conn); - - ds.Tables.Add(createLandAccessListTable()); - setupLandAccessCommands(landAccessListDa, m_conn); - - ds.Tables.Add(createRegionSettingsTable()); - setupRegionSettingsCommands(regionSettingsDa, m_conn); - - // WORKAROUND: This is a work around for sqlite on - // windows, which gets really unhappy with blob columns - // that have no sample data in them. At some point we - // need to actually find a proper way to handle this. - try - { - primDa.Fill(ds.Tables["prims"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on prims table"); - } - - try - { - shapeDa.Fill(ds.Tables["primshapes"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on primshapes table"); - } - - try - { - terrainDa.Fill(ds.Tables["terrain"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on terrain table"); - } - - try - { - landDa.Fill(ds.Tables["land"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on land table"); - } - - try - { - landAccessListDa.Fill(ds.Tables["landaccesslist"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); - } - - try - { - regionSettingsDa.Fill(ds.Tables["regionsettings"]); - } - catch (Exception) - { - m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); - } - - // We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values! - // Not sure exactly why this is - this kind of thing was not necessary before - justincc 20100409 - // Possibly because we manually set up our own DataTables before connecting to the database - CreateDataSetMapping(primDa, "prims"); - CreateDataSetMapping(shapeDa, "primshapes"); - CreateDataSetMapping(itemsDa, "primitems"); - CreateDataSetMapping(terrainDa, "terrain"); - CreateDataSetMapping(landDa, "land"); - CreateDataSetMapping(landAccessListDa, "landaccesslist"); - CreateDataSetMapping(regionSettingsDa, "regionsettings"); - } - } - catch (Exception e) - { - m_log.Error(e); - Environment.Exit(23); - } - - return; - } - - public void Dispose() - { - if (m_conn != null) - { - m_conn.Close(); - m_conn = null; - } - if (ds != null) - { - ds.Dispose(); - ds = null; - } - if (primDa != null) - { - primDa.Dispose(); - primDa = null; - } - if (shapeDa != null) - { - shapeDa.Dispose(); - shapeDa = null; - } - if (itemsDa != null) - { - itemsDa.Dispose(); - itemsDa = null; - } - if (terrainDa != null) - { - terrainDa.Dispose(); - terrainDa = null; - } - if (landDa != null) - { - landDa.Dispose(); - landDa = null; - } - if (landAccessListDa != null) - { - landAccessListDa.Dispose(); - landAccessListDa = null; - } - if (regionSettingsDa != null) - { - regionSettingsDa.Dispose(); - regionSettingsDa = null; - } - } - - public void StoreRegionSettings(RegionSettings rs) - { - lock (ds) - { - DataTable regionsettings = ds.Tables["regionsettings"]; - - DataRow settingsRow = regionsettings.Rows.Find(rs.RegionUUID.ToString()); - if (settingsRow == null) - { - settingsRow = regionsettings.NewRow(); - fillRegionSettingsRow(settingsRow, rs); - regionsettings.Rows.Add(settingsRow); - } - else - { - fillRegionSettingsRow(settingsRow, rs); - } - - Commit(); - } - } - public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) - { - //This connector doesn't support the windlight module yet - //Return default LL windlight settings - return new RegionLightShareData(); - } - public void StoreRegionWindlightSettings(RegionLightShareData wl) - { - //This connector doesn't support the windlight module yet - } - public RegionSettings LoadRegionSettings(UUID regionUUID) - { - lock (ds) - { - DataTable regionsettings = ds.Tables["regionsettings"]; - - string searchExp = "regionUUID = '" + regionUUID.ToString() + "'"; - DataRow[] rawsettings = regionsettings.Select(searchExp); - if (rawsettings.Length == 0) - { - RegionSettings rs = new RegionSettings(); - rs.RegionUUID = regionUUID; - rs.OnSave += StoreRegionSettings; - - StoreRegionSettings(rs); - - return rs; - } - DataRow row = rawsettings[0]; - - RegionSettings newSettings = buildRegionSettings(row); - newSettings.OnSave += StoreRegionSettings; - - return newSettings; - } - } - - /// - /// Adds an object into region storage - /// - /// the object - /// the region UUID - public void StoreObject(SceneObjectGroup obj, UUID regionUUID) - { - uint flags = obj.RootPart.GetEffectiveObjectFlags(); - - // Eligibility check - // - if ((flags & (uint)PrimFlags.Temporary) != 0) - return; - if ((flags & (uint)PrimFlags.TemporaryOnRez) != 0) - return; - - lock (ds) - { - foreach (SceneObjectPart prim in obj.Children.Values) - { -// m_log.Info("[REGION DB]: Adding obj: " + obj.UUID + " to region: " + regionUUID); - addPrim(prim, obj.UUID, regionUUID); - } - } - - Commit(); - // m_log.Info("[Dump of prims]: " + ds.GetXml()); - } - - /// - /// Removes an object from region storage - /// - /// the object - /// the region UUID - public void RemoveObject(UUID obj, UUID regionUUID) - { - // m_log.InfoFormat("[REGION DB]: Removing obj: {0} from region: {1}", obj.Guid, regionUUID); - - DataTable prims = ds.Tables["prims"]; - DataTable shapes = ds.Tables["primshapes"]; - - string selectExp = "SceneGroupID = '" + obj + "' and RegionUUID = '" + regionUUID + "'"; - lock (ds) - { - DataRow[] primRows = prims.Select(selectExp); - foreach (DataRow row in primRows) - { - // Remove shape rows - UUID uuid = new UUID((string) row["UUID"]); - DataRow shapeRow = shapes.Rows.Find(uuid.ToString()); - if (shapeRow != null) - { - shapeRow.Delete(); - } - - RemoveItems(uuid); - - // Remove prim row - row.Delete(); - } - } - - Commit(); - } - - /// - /// Remove all persisted items of the given prim. - /// The caller must acquire the necessrary synchronization locks and commit or rollback changes. - /// - /// The item UUID - private void RemoveItems(UUID uuid) - { - DataTable items = ds.Tables["primitems"]; - - String sql = String.Format("primID = '{0}'", uuid); - DataRow[] itemRows = items.Select(sql); - - foreach (DataRow itemRow in itemRows) - { - itemRow.Delete(); - } - } - - /// - /// Load persisted objects from region storage. - /// - /// The region UUID - /// List of loaded groups - public List LoadObjects(UUID regionUUID) - { - Dictionary createdObjects = new Dictionary(); - - List retvals = new List(); - - DataTable prims = ds.Tables["prims"]; - DataTable shapes = ds.Tables["primshapes"]; - - string byRegion = "RegionUUID = '" + regionUUID + "'"; - - lock (ds) - { - DataRow[] primsForRegion = prims.Select(byRegion); - m_log.Info("[REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); - - // First, create all groups - foreach (DataRow primRow in primsForRegion) - { - try - { - SceneObjectPart prim = null; - - string uuid = (string) primRow["UUID"]; - string objID = (string) primRow["SceneGroupID"]; - - if (uuid == objID) //is new SceneObjectGroup ? - { - prim = buildPrim(primRow); - DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); - if (shapeRow != null) - { - prim.Shape = buildShape(shapeRow); - } - else - { - m_log.Info( - "[REGION DB]: No shape found for prim in storage, so setting default box shape"); - prim.Shape = PrimitiveBaseShape.Default; - } - - SceneObjectGroup group = new SceneObjectGroup(prim); - createdObjects.Add(group.UUID, group); - retvals.Add(group); - LoadItems(prim); - } - } - catch (Exception e) - { - m_log.Error("[REGION DB]: Failed create prim object in new group, exception and data follows"); - m_log.Info("[REGION DB]: " + e.ToString()); - foreach (DataColumn col in prims.Columns) - { - m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); - } - } - } - - // Now fill the groups with part data - foreach (DataRow primRow in primsForRegion) - { - try - { - SceneObjectPart prim = null; - - string uuid = (string) primRow["UUID"]; - string objID = (string) primRow["SceneGroupID"]; - if (uuid != objID) //is new SceneObjectGroup ? - { - prim = buildPrim(primRow); - DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); - if (shapeRow != null) - { - prim.Shape = buildShape(shapeRow); - } - else - { - m_log.Warn( - "[REGION DB]: No shape found for prim in storage, so setting default box shape"); - prim.Shape = PrimitiveBaseShape.Default; - } - - createdObjects[new UUID(objID)].AddPart(prim); - LoadItems(prim); - } - } - catch (Exception e) - { - m_log.Error("[REGION DB]: Failed create prim object in group, exception and data follows"); - m_log.Info("[REGION DB]: " + e.ToString()); - foreach (DataColumn col in prims.Columns) - { - m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); - } - } - } - } - return retvals; - } - - /// - /// Load in a prim's persisted inventory. - /// - /// the prim - private void LoadItems(SceneObjectPart prim) - { - //m_log.DebugFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); - - DataTable dbItems = ds.Tables["primitems"]; - String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); - DataRow[] dbItemRows = dbItems.Select(sql); - IList inventory = new List(); - - foreach (DataRow row in dbItemRows) - { - TaskInventoryItem item = buildItem(row); - inventory.Add(item); - - //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); - } - - prim.Inventory.RestoreInventoryItems(inventory); - } - - /// - /// Store a terrain revision in region storage - /// - /// terrain heightfield - /// region UUID - public void StoreTerrain(double[,] ter, UUID regionID) - { - lock (ds) - { - int revision = Util.UnixTimeSinceEpoch(); - - // This is added to get rid of the infinitely growing - // terrain databases which negatively impact on SQLite - // over time. Before reenabling this feature there - // needs to be a limitter put on the number of - // revisions in the database, as this old - // implementation is a DOS attack waiting to happen. - - using ( - SqliteCommand cmd = - new SqliteCommand("delete from terrain where RegionUUID=:RegionUUID and Revision <= :Revision", - m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); - cmd.ExecuteNonQuery(); - } - - // the following is an work around for .NET. The perf - // issues associated with it aren't as bad as you think. - m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString()); - String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + - " values(:RegionUUID, :Revision, :Heightfield)"; - - using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":Revision", revision)); - cmd.Parameters.Add(new SqliteParameter(":Heightfield", serializeTerrain(ter))); - cmd.ExecuteNonQuery(); - } - } - } - - /// - /// Load the latest terrain revision from region storage - /// - /// the region UUID - /// Heightfield data - public double[,] LoadTerrain(UUID regionID) - { - lock (ds) - { - double[,] terret = new double[(int)Constants.RegionSize, (int)Constants.RegionSize]; - terret.Initialize(); - - String sql = "select RegionUUID, Revision, Heightfield from terrain" + - " where RegionUUID=:RegionUUID order by Revision desc"; - - using (SqliteCommand cmd = new SqliteCommand(sql, m_conn)) - { - cmd.Parameters.Add(new SqliteParameter(":RegionUUID", regionID.ToString())); - - using (IDataReader row = cmd.ExecuteReader()) - { - int rev = 0; - if (row.Read()) - { - // TODO: put this into a function - using (MemoryStream str = new MemoryStream((byte[])row["Heightfield"])) - { - using (BinaryReader br = new BinaryReader(str)) - { - for (int x = 0; x < (int)Constants.RegionSize; x++) - { - for (int y = 0; y < (int)Constants.RegionSize; y++) - { - terret[x, y] = br.ReadDouble(); - } - } - } - } - rev = Convert.ToInt32(row["Revision"]); - } - else - { - m_log.Info("[REGION DB]: No terrain found for region"); - return null; - } - - m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString()); - } - } - return terret; - } - } - - /// - /// - /// - /// - public void RemoveLandObject(UUID globalID) - { - lock (ds) - { - // Can't use blanket SQL statements when using SqlAdapters unless you re-read the data into the adapter - // after you're done. - // replaced below code with the SqliteAdapter version. - //using (SqliteCommand cmd = new SqliteCommand("delete from land where UUID=:UUID", m_conn)) - //{ - // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); - // cmd.ExecuteNonQuery(); - //} - - //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:UUID", m_conn)) - //{ - // cmd.Parameters.Add(new SqliteParameter(":UUID", globalID.ToString())); - // cmd.ExecuteNonQuery(); - //} - - DataTable land = ds.Tables["land"]; - DataTable landaccesslist = ds.Tables["landaccesslist"]; - DataRow landRow = land.Rows.Find(globalID.ToString()); - if (landRow != null) - { - land.Rows.Remove(landRow); - } - List rowsToDelete = new List(); - foreach (DataRow rowToCheck in landaccesslist.Rows) - { - if (rowToCheck["LandUUID"].ToString() == globalID.ToString()) - rowsToDelete.Add(rowToCheck); - } - for (int iter = 0; iter < rowsToDelete.Count; iter++) - { - landaccesslist.Rows.Remove(rowsToDelete[iter]); - } - - - } - Commit(); - } - - /// - /// - /// - /// - public void StoreLandObject(ILandObject parcel) - { - lock (ds) - { - DataTable land = ds.Tables["land"]; - DataTable landaccesslist = ds.Tables["landaccesslist"]; - - DataRow landRow = land.Rows.Find(parcel.LandData.GlobalID.ToString()); - if (landRow == null) - { - landRow = land.NewRow(); - fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); - land.Rows.Add(landRow); - } - else - { - fillLandRow(landRow, parcel.LandData, parcel.RegionUUID); - } - - // I know this caused someone issues before, but OpenSim is unusable if we leave this stuff around - //using (SqliteCommand cmd = new SqliteCommand("delete from landaccesslist where LandUUID=:LandUUID", m_conn)) - //{ - // cmd.Parameters.Add(new SqliteParameter(":LandUUID", parcel.LandData.GlobalID.ToString())); - // cmd.ExecuteNonQuery(); - -// } - - // This is the slower.. but more appropriate thing to do - - // We can't modify the table with direct queries before calling Commit() and re-filling them. - List rowsToDelete = new List(); - foreach (DataRow rowToCheck in landaccesslist.Rows) - { - if (rowToCheck["LandUUID"].ToString() == parcel.LandData.GlobalID.ToString()) - rowsToDelete.Add(rowToCheck); - } - for (int iter = 0; iter < rowsToDelete.Count; iter++) - { - landaccesslist.Rows.Remove(rowsToDelete[iter]); - } - rowsToDelete.Clear(); - foreach (ParcelManager.ParcelAccessEntry entry in parcel.LandData.ParcelAccessList) - { - DataRow newAccessRow = landaccesslist.NewRow(); - fillLandAccessRow(newAccessRow, entry, parcel.LandData.GlobalID); - landaccesslist.Rows.Add(newAccessRow); - } - } - - Commit(); - } - - /// - /// - /// - /// - /// - public List LoadLandObjects(UUID regionUUID) - { - List landDataForRegion = new List(); - lock (ds) - { - DataTable land = ds.Tables["land"]; - DataTable landaccesslist = ds.Tables["landaccesslist"]; - string searchExp = "RegionUUID = '" + regionUUID + "'"; - DataRow[] rawDataForRegion = land.Select(searchExp); - foreach (DataRow rawDataLand in rawDataForRegion) - { - LandData newLand = buildLandData(rawDataLand); - string accessListSearchExp = "LandUUID = '" + newLand.GlobalID + "'"; - DataRow[] rawDataForLandAccessList = landaccesslist.Select(accessListSearchExp); - foreach (DataRow rawDataLandAccess in rawDataForLandAccessList) - { - newLand.ParcelAccessList.Add(buildLandAccessData(rawDataLandAccess)); - } - - landDataForRegion.Add(newLand); - } - } - return landDataForRegion; - } - - /// - /// - /// - public void Commit() - { - m_log.Debug("[SQLITE]: Starting commit"); - lock (ds) - { - primDa.Update(ds, "prims"); - shapeDa.Update(ds, "primshapes"); - - itemsDa.Update(ds, "primitems"); - - terrainDa.Update(ds, "terrain"); - landDa.Update(ds, "land"); - landAccessListDa.Update(ds, "landaccesslist"); - try - { - regionSettingsDa.Update(ds, "regionsettings"); - } - catch (SqliteException SqlEx) - { - throw new Exception( - "There was a SQL error or connection string configuration error when saving the region settings. This could be a bug, it could also happen if ConnectionString is defined in the [DatabaseService] section of StandaloneCommon.ini in the config_include folder. This could also happen if the config_include folder doesn't exist or if the OpenSim.ini [Architecture] section isn't set. If this is your first time running OpenSimulator, please restart the simulator and bug a developer to fix this!", - SqlEx); - } - ds.AcceptChanges(); - } - } - - /// - /// See - /// - public void Shutdown() - { - Commit(); - } - - /*********************************************************************** - * - * Database Definition Functions - * - * This should be db agnostic as we define them in ADO.NET terms - * - **********************************************************************/ - - protected void CreateDataSetMapping(IDataAdapter da, string tableName) - { - ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName); - foreach (DataColumn col in ds.Tables[tableName].Columns) - { - dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName); - } - } - - /// - /// - /// - /// - /// - /// - private static void createCol(DataTable dt, string name, Type type) - { - DataColumn col = new DataColumn(name, type); - dt.Columns.Add(col); - } - - /// - /// Creates the "terrain" table - /// - /// terrain table DataTable - private static DataTable createTerrainTable() - { - DataTable terrain = new DataTable("terrain"); - - createCol(terrain, "RegionUUID", typeof (String)); - createCol(terrain, "Revision", typeof (Int32)); - createCol(terrain, "Heightfield", typeof (Byte[])); - - return terrain; - } - - /// - /// Creates the "prims" table - /// - /// prim table DataTable - private static DataTable createPrimTable() - { - DataTable prims = new DataTable("prims"); - - createCol(prims, "UUID", typeof (String)); - createCol(prims, "RegionUUID", typeof (String)); - createCol(prims, "CreationDate", typeof (Int32)); - createCol(prims, "Name", typeof (String)); - createCol(prims, "SceneGroupID", typeof (String)); - // various text fields - createCol(prims, "Text", typeof (String)); - createCol(prims, "ColorR", typeof (Int32)); - createCol(prims, "ColorG", typeof (Int32)); - createCol(prims, "ColorB", typeof (Int32)); - createCol(prims, "ColorA", typeof (Int32)); - createCol(prims, "Description", typeof (String)); - createCol(prims, "SitName", typeof (String)); - createCol(prims, "TouchName", typeof (String)); - // permissions - createCol(prims, "ObjectFlags", typeof (Int32)); - createCol(prims, "CreatorID", typeof (String)); - createCol(prims, "OwnerID", typeof (String)); - createCol(prims, "GroupID", typeof (String)); - createCol(prims, "LastOwnerID", typeof (String)); - createCol(prims, "OwnerMask", typeof (Int32)); - createCol(prims, "NextOwnerMask", typeof (Int32)); - createCol(prims, "GroupMask", typeof (Int32)); - createCol(prims, "EveryoneMask", typeof (Int32)); - createCol(prims, "BaseMask", typeof (Int32)); - // vectors - createCol(prims, "PositionX", typeof (Double)); - createCol(prims, "PositionY", typeof (Double)); - createCol(prims, "PositionZ", typeof (Double)); - createCol(prims, "GroupPositionX", typeof (Double)); - createCol(prims, "GroupPositionY", typeof (Double)); - createCol(prims, "GroupPositionZ", typeof (Double)); - createCol(prims, "VelocityX", typeof (Double)); - createCol(prims, "VelocityY", typeof (Double)); - createCol(prims, "VelocityZ", typeof (Double)); - createCol(prims, "AngularVelocityX", typeof (Double)); - createCol(prims, "AngularVelocityY", typeof (Double)); - createCol(prims, "AngularVelocityZ", typeof (Double)); - createCol(prims, "AccelerationX", typeof (Double)); - createCol(prims, "AccelerationY", typeof (Double)); - createCol(prims, "AccelerationZ", typeof (Double)); - // quaternions - createCol(prims, "RotationX", typeof (Double)); - createCol(prims, "RotationY", typeof (Double)); - createCol(prims, "RotationZ", typeof (Double)); - createCol(prims, "RotationW", typeof (Double)); - - // sit target - createCol(prims, "SitTargetOffsetX", typeof (Double)); - createCol(prims, "SitTargetOffsetY", typeof (Double)); - createCol(prims, "SitTargetOffsetZ", typeof (Double)); - - createCol(prims, "SitTargetOrientW", typeof (Double)); - createCol(prims, "SitTargetOrientX", typeof (Double)); - createCol(prims, "SitTargetOrientY", typeof (Double)); - createCol(prims, "SitTargetOrientZ", typeof (Double)); - - createCol(prims, "PayPrice", typeof(Int32)); - createCol(prims, "PayButton1", typeof(Int32)); - createCol(prims, "PayButton2", typeof(Int32)); - createCol(prims, "PayButton3", typeof(Int32)); - createCol(prims, "PayButton4", typeof(Int32)); - - createCol(prims, "LoopedSound", typeof(String)); - createCol(prims, "LoopedSoundGain", typeof(Double)); - createCol(prims, "TextureAnimation", typeof(String)); - createCol(prims, "ParticleSystem", typeof(String)); - - createCol(prims, "OmegaX", typeof(Double)); - createCol(prims, "OmegaY", typeof(Double)); - createCol(prims, "OmegaZ", typeof(Double)); - - createCol(prims, "CameraEyeOffsetX", typeof(Double)); - createCol(prims, "CameraEyeOffsetY", typeof(Double)); - createCol(prims, "CameraEyeOffsetZ", typeof(Double)); - - createCol(prims, "CameraAtOffsetX", typeof(Double)); - createCol(prims, "CameraAtOffsetY", typeof(Double)); - createCol(prims, "CameraAtOffsetZ", typeof(Double)); - - createCol(prims, "ForceMouselook", typeof(Int16)); - - createCol(prims, "ScriptAccessPin", typeof(Int32)); - - createCol(prims, "AllowedDrop", typeof(Int16)); - createCol(prims, "DieAtEdge", typeof(Int16)); - - createCol(prims, "SalePrice", typeof(Int32)); - createCol(prims, "SaleType", typeof(Int16)); - - // click action - createCol(prims, "ClickAction", typeof (Byte)); - - createCol(prims, "Material", typeof(Byte)); - - createCol(prims, "CollisionSound", typeof(String)); - createCol(prims, "CollisionSoundVolume", typeof(Double)); - - createCol(prims, "VolumeDetect", typeof(Int16)); - - // Add in contraints - prims.PrimaryKey = new DataColumn[] {prims.Columns["UUID"]}; - - return prims; - } - - /// - /// Creates "primshapes" table - /// - /// shape table DataTable - private static DataTable createShapeTable() - { - DataTable shapes = new DataTable("primshapes"); - createCol(shapes, "UUID", typeof (String)); - // shape is an enum - createCol(shapes, "Shape", typeof (Int32)); - // vectors - createCol(shapes, "ScaleX", typeof (Double)); - createCol(shapes, "ScaleY", typeof (Double)); - createCol(shapes, "ScaleZ", typeof (Double)); - // paths - createCol(shapes, "PCode", typeof (Int32)); - createCol(shapes, "PathBegin", typeof (Int32)); - createCol(shapes, "PathEnd", typeof (Int32)); - createCol(shapes, "PathScaleX", typeof (Int32)); - createCol(shapes, "PathScaleY", typeof (Int32)); - createCol(shapes, "PathShearX", typeof (Int32)); - createCol(shapes, "PathShearY", typeof (Int32)); - createCol(shapes, "PathSkew", typeof (Int32)); - createCol(shapes, "PathCurve", typeof (Int32)); - createCol(shapes, "PathRadiusOffset", typeof (Int32)); - createCol(shapes, "PathRevolutions", typeof (Int32)); - createCol(shapes, "PathTaperX", typeof (Int32)); - createCol(shapes, "PathTaperY", typeof (Int32)); - createCol(shapes, "PathTwist", typeof (Int32)); - createCol(shapes, "PathTwistBegin", typeof (Int32)); - // profile - createCol(shapes, "ProfileBegin", typeof (Int32)); - createCol(shapes, "ProfileEnd", typeof (Int32)); - createCol(shapes, "ProfileCurve", typeof (Int32)); - createCol(shapes, "ProfileHollow", typeof (Int32)); - createCol(shapes, "State", typeof(Int32)); - // text TODO: this isn't right, but I'm not sure the right - // way to specify this as a blob atm - createCol(shapes, "Texture", typeof (Byte[])); - createCol(shapes, "ExtraParams", typeof (Byte[])); - - shapes.PrimaryKey = new DataColumn[] {shapes.Columns["UUID"]}; - - return shapes; - } - - /// - /// creates "primitems" table - /// - /// item table DataTable - private static DataTable createItemsTable() - { - DataTable items = new DataTable("primitems"); - - createCol(items, "itemID", typeof (String)); - createCol(items, "primID", typeof (String)); - createCol(items, "assetID", typeof (String)); - createCol(items, "parentFolderID", typeof (String)); - - createCol(items, "invType", typeof (Int32)); - createCol(items, "assetType", typeof (Int32)); - - createCol(items, "name", typeof (String)); - createCol(items, "description", typeof (String)); - - createCol(items, "creationDate", typeof (Int64)); - createCol(items, "creatorID", typeof (String)); - createCol(items, "ownerID", typeof (String)); - createCol(items, "lastOwnerID", typeof (String)); - createCol(items, "groupID", typeof (String)); - - createCol(items, "nextPermissions", typeof (UInt32)); - createCol(items, "currentPermissions", typeof (UInt32)); - createCol(items, "basePermissions", typeof (UInt32)); - createCol(items, "everyonePermissions", typeof (UInt32)); - createCol(items, "groupPermissions", typeof (UInt32)); - createCol(items, "flags", typeof (UInt32)); - - items.PrimaryKey = new DataColumn[] { items.Columns["itemID"] }; - - return items; - } - - /// - /// Creates "land" table - /// - /// land table DataTable - private static DataTable createLandTable() - { - DataTable land = new DataTable("land"); - createCol(land, "UUID", typeof (String)); - createCol(land, "RegionUUID", typeof (String)); - createCol(land, "LocalLandID", typeof (UInt32)); - - // Bitmap is a byte[512] - createCol(land, "Bitmap", typeof (Byte[])); - - createCol(land, "Name", typeof (String)); - createCol(land, "Desc", typeof (String)); - createCol(land, "OwnerUUID", typeof (String)); - createCol(land, "IsGroupOwned", typeof (Boolean)); - createCol(land, "Area", typeof (Int32)); - createCol(land, "AuctionID", typeof (Int32)); //Unemplemented - createCol(land, "Category", typeof (Int32)); //Enum OpenMetaverse.Parcel.ParcelCategory - createCol(land, "ClaimDate", typeof (Int32)); - createCol(land, "ClaimPrice", typeof (Int32)); - createCol(land, "GroupUUID", typeof (string)); - createCol(land, "SalePrice", typeof (Int32)); - createCol(land, "LandStatus", typeof (Int32)); //Enum. OpenMetaverse.Parcel.ParcelStatus - createCol(land, "LandFlags", typeof (UInt32)); - createCol(land, "LandingType", typeof (Byte)); - createCol(land, "MediaAutoScale", typeof (Byte)); - createCol(land, "MediaTextureUUID", typeof (String)); - createCol(land, "MediaURL", typeof (String)); - createCol(land, "MusicURL", typeof (String)); - createCol(land, "PassHours", typeof (Double)); - createCol(land, "PassPrice", typeof (UInt32)); - createCol(land, "SnapshotUUID", typeof (String)); - createCol(land, "UserLocationX", typeof (Double)); - createCol(land, "UserLocationY", typeof (Double)); - createCol(land, "UserLocationZ", typeof (Double)); - createCol(land, "UserLookAtX", typeof (Double)); - createCol(land, "UserLookAtY", typeof (Double)); - createCol(land, "UserLookAtZ", typeof (Double)); - createCol(land, "AuthbuyerID", typeof(String)); - createCol(land, "OtherCleanTime", typeof(Int32)); - createCol(land, "Dwell", typeof(Int32)); - - land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; - - return land; - } - - /// - /// create "landaccesslist" table - /// - /// Landacceslist DataTable - private static DataTable createLandAccessListTable() - { - DataTable landaccess = new DataTable("landaccesslist"); - createCol(landaccess, "LandUUID", typeof (String)); - createCol(landaccess, "AccessUUID", typeof (String)); - createCol(landaccess, "Flags", typeof (UInt32)); - - return landaccess; - } - - private static DataTable createRegionSettingsTable() - { - DataTable regionsettings = new DataTable("regionsettings"); - createCol(regionsettings, "regionUUID", typeof(String)); - createCol(regionsettings, "block_terraform", typeof (Int32)); - createCol(regionsettings, "block_fly", typeof (Int32)); - createCol(regionsettings, "allow_damage", typeof (Int32)); - createCol(regionsettings, "restrict_pushing", typeof (Int32)); - createCol(regionsettings, "allow_land_resell", typeof (Int32)); - createCol(regionsettings, "allow_land_join_divide", typeof (Int32)); - createCol(regionsettings, "block_show_in_search", typeof (Int32)); - createCol(regionsettings, "agent_limit", typeof (Int32)); - createCol(regionsettings, "object_bonus", typeof (Double)); - createCol(regionsettings, "maturity", typeof (Int32)); - createCol(regionsettings, "disable_scripts", typeof (Int32)); - createCol(regionsettings, "disable_collisions", typeof (Int32)); - createCol(regionsettings, "disable_physics", typeof (Int32)); - createCol(regionsettings, "terrain_texture_1", typeof(String)); - createCol(regionsettings, "terrain_texture_2", typeof(String)); - createCol(regionsettings, "terrain_texture_3", typeof(String)); - createCol(regionsettings, "terrain_texture_4", typeof(String)); - createCol(regionsettings, "elevation_1_nw", typeof (Double)); - createCol(regionsettings, "elevation_2_nw", typeof (Double)); - createCol(regionsettings, "elevation_1_ne", typeof (Double)); - createCol(regionsettings, "elevation_2_ne", typeof (Double)); - createCol(regionsettings, "elevation_1_se", typeof (Double)); - createCol(regionsettings, "elevation_2_se", typeof (Double)); - createCol(regionsettings, "elevation_1_sw", typeof (Double)); - createCol(regionsettings, "elevation_2_sw", typeof (Double)); - createCol(regionsettings, "water_height", typeof (Double)); - createCol(regionsettings, "terrain_raise_limit", typeof (Double)); - createCol(regionsettings, "terrain_lower_limit", typeof (Double)); - createCol(regionsettings, "use_estate_sun", typeof (Int32)); - createCol(regionsettings, "sandbox", typeof (Int32)); - createCol(regionsettings, "sunvectorx",typeof (Double)); - createCol(regionsettings, "sunvectory",typeof (Double)); - createCol(regionsettings, "sunvectorz",typeof (Double)); - createCol(regionsettings, "fixed_sun", typeof (Int32)); - createCol(regionsettings, "sun_position", typeof (Double)); - createCol(regionsettings, "covenant", typeof(String)); - regionsettings.PrimaryKey = new DataColumn[] { regionsettings.Columns["regionUUID"] }; - return regionsettings; - } - - /*********************************************************************** - * - * Convert between ADO.NET <=> OpenSim Objects - * - * These should be database independant - * - **********************************************************************/ - - /// - /// - /// - /// - /// - private SceneObjectPart buildPrim(DataRow row) - { - // Code commented. Uncomment to test the unit test inline. - - // The unit test mentions this commented code for the purposes - // of debugging a unit test failure - - // SceneObjectGroup sog = new SceneObjectGroup(); - // SceneObjectPart sop = new SceneObjectPart(); - // sop.LocalId = 1; - // sop.Name = "object1"; - // sop.Description = "object1"; - // sop.Text = ""; - // sop.SitName = ""; - // sop.TouchName = ""; - // sop.UUID = UUID.Random(); - // sop.Shape = PrimitiveBaseShape.Default; - // sog.SetRootPart(sop); - // Add breakpoint in above line. Check sop fields. - - // TODO: this doesn't work yet because something more - // interesting has to be done to actually get these values - // back out. Not enough time to figure it out yet. - - SceneObjectPart prim = new SceneObjectPart(); - prim.UUID = new UUID((String) row["UUID"]); - // explicit conversion of integers is required, which sort - // of sucks. No idea if there is a shortcut here or not. - prim.CreationDate = Convert.ToInt32(row["CreationDate"]); - prim.Name = row["Name"] == DBNull.Value ? string.Empty : (string)row["Name"]; - // various text fields - prim.Text = (String) row["Text"]; - prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), - Convert.ToInt32(row["ColorR"]), - Convert.ToInt32(row["ColorG"]), - Convert.ToInt32(row["ColorB"])); - prim.Description = (String) row["Description"]; - prim.SitName = (String) row["SitName"]; - prim.TouchName = (String) row["TouchName"]; - // permissions - prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); - prim.CreatorID = new UUID((String) row["CreatorID"]); - prim.OwnerID = new UUID((String) row["OwnerID"]); - prim.GroupID = new UUID((String) row["GroupID"]); - prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); - prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); - prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); - prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); - prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); - prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); - // vectors - prim.OffsetPosition = new Vector3( - Convert.ToSingle(row["PositionX"]), - Convert.ToSingle(row["PositionY"]), - Convert.ToSingle(row["PositionZ"]) - ); - prim.GroupPosition = new Vector3( - Convert.ToSingle(row["GroupPositionX"]), - Convert.ToSingle(row["GroupPositionY"]), - Convert.ToSingle(row["GroupPositionZ"]) - ); - prim.Velocity = new Vector3( - Convert.ToSingle(row["VelocityX"]), - Convert.ToSingle(row["VelocityY"]), - Convert.ToSingle(row["VelocityZ"]) - ); - prim.AngularVelocity = new Vector3( - Convert.ToSingle(row["AngularVelocityX"]), - Convert.ToSingle(row["AngularVelocityY"]), - Convert.ToSingle(row["AngularVelocityZ"]) - ); - prim.Acceleration = new Vector3( - Convert.ToSingle(row["AccelerationX"]), - Convert.ToSingle(row["AccelerationY"]), - Convert.ToSingle(row["AccelerationZ"]) - ); - // quaternions - prim.RotationOffset = new Quaternion( - Convert.ToSingle(row["RotationX"]), - Convert.ToSingle(row["RotationY"]), - Convert.ToSingle(row["RotationZ"]), - Convert.ToSingle(row["RotationW"]) - ); - - prim.SitTargetPositionLL = new Vector3( - Convert.ToSingle(row["SitTargetOffsetX"]), - Convert.ToSingle(row["SitTargetOffsetY"]), - Convert.ToSingle(row["SitTargetOffsetZ"])); - prim.SitTargetOrientationLL = new Quaternion( - Convert.ToSingle( - row["SitTargetOrientX"]), - Convert.ToSingle( - row["SitTargetOrientY"]), - Convert.ToSingle( - row["SitTargetOrientZ"]), - Convert.ToSingle( - row["SitTargetOrientW"])); - - prim.ClickAction = Convert.ToByte(row["ClickAction"]); - prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); - prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); - prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); - prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); - prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); - - prim.Sound = new UUID(row["LoopedSound"].ToString()); - prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); - prim.SoundFlags = 1; // If it's persisted at all, it's looped - - if (!row.IsNull("TextureAnimation")) - prim.TextureAnimation = Convert.FromBase64String(row["TextureAnimation"].ToString()); - if (!row.IsNull("ParticleSystem")) - prim.ParticleSystem = Convert.FromBase64String(row["ParticleSystem"].ToString()); - - prim.AngularVelocity = new Vector3( - Convert.ToSingle(row["OmegaX"]), - Convert.ToSingle(row["OmegaY"]), - Convert.ToSingle(row["OmegaZ"]) - ); - - prim.SetCameraEyeOffset(new Vector3( - Convert.ToSingle(row["CameraEyeOffsetX"]), - Convert.ToSingle(row["CameraEyeOffsetY"]), - Convert.ToSingle(row["CameraEyeOffsetZ"]) - )); - - prim.SetCameraAtOffset(new Vector3( - Convert.ToSingle(row["CameraAtOffsetX"]), - Convert.ToSingle(row["CameraAtOffsetY"]), - Convert.ToSingle(row["CameraAtOffsetZ"]) - )); - - if (Convert.ToInt16(row["ForceMouselook"]) != 0) - prim.SetForceMouselook(true); - - prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); - - if (Convert.ToInt16(row["AllowedDrop"]) != 0) - prim.AllowedDrop = true; - - if (Convert.ToInt16(row["DieAtEdge"]) != 0) - prim.DIE_AT_EDGE = true; - - prim.SalePrice = Convert.ToInt32(row["SalePrice"]); - prim.ObjectSaleType = Convert.ToByte(row["SaleType"]); - - prim.Material = Convert.ToByte(row["Material"]); - - prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); - prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); - - if (Convert.ToInt16(row["VolumeDetect"]) != 0) - prim.VolumeDetectActive = true; - - return prim; - } - - /// - /// Build a prim inventory item from the persisted data. - /// - /// - /// - private static TaskInventoryItem buildItem(DataRow row) - { - TaskInventoryItem taskItem = new TaskInventoryItem(); - - taskItem.ItemID = new UUID((String)row["itemID"]); - taskItem.ParentPartID = new UUID((String)row["primID"]); - taskItem.AssetID = new UUID((String)row["assetID"]); - taskItem.ParentID = new UUID((String)row["parentFolderID"]); - - taskItem.InvType = Convert.ToInt32(row["invType"]); - taskItem.Type = Convert.ToInt32(row["assetType"]); - - taskItem.Name = (String)row["name"]; - taskItem.Description = (String)row["description"]; - taskItem.CreationDate = Convert.ToUInt32(row["creationDate"]); - taskItem.CreatorID = new UUID((String)row["creatorID"]); - taskItem.OwnerID = new UUID((String)row["ownerID"]); - taskItem.LastOwnerID = new UUID((String)row["lastOwnerID"]); - taskItem.GroupID = new UUID((String)row["groupID"]); - - taskItem.NextPermissions = Convert.ToUInt32(row["nextPermissions"]); - taskItem.CurrentPermissions = Convert.ToUInt32(row["currentPermissions"]); - taskItem.BasePermissions = Convert.ToUInt32(row["basePermissions"]); - taskItem.EveryonePermissions = Convert.ToUInt32(row["everyonePermissions"]); - taskItem.GroupPermissions = Convert.ToUInt32(row["groupPermissions"]); - taskItem.Flags = Convert.ToUInt32(row["flags"]); - - return taskItem; - } - - /// - /// Build a Land Data from the persisted data. - /// - /// - /// - private LandData buildLandData(DataRow row) - { - LandData newData = new LandData(); - - newData.GlobalID = new UUID((String) row["UUID"]); - newData.LocalID = Convert.ToInt32(row["LocalLandID"]); - - // Bitmap is a byte[512] - newData.Bitmap = (Byte[]) row["Bitmap"]; - - newData.Name = (String) row["Name"]; - newData.Description = (String) row["Desc"]; - newData.OwnerID = (UUID)(String) row["OwnerUUID"]; - newData.IsGroupOwned = (Boolean) row["IsGroupOwned"]; - newData.Area = Convert.ToInt32(row["Area"]); - newData.AuctionID = Convert.ToUInt32(row["AuctionID"]); //Unemplemented - newData.Category = (ParcelCategory) Convert.ToInt32(row["Category"]); - //Enum OpenMetaverse.Parcel.ParcelCategory - newData.ClaimDate = Convert.ToInt32(row["ClaimDate"]); - newData.ClaimPrice = Convert.ToInt32(row["ClaimPrice"]); - newData.GroupID = new UUID((String) row["GroupUUID"]); - newData.SalePrice = Convert.ToInt32(row["SalePrice"]); - newData.Status = (ParcelStatus) Convert.ToInt32(row["LandStatus"]); - //Enum. OpenMetaverse.Parcel.ParcelStatus - newData.Flags = Convert.ToUInt32(row["LandFlags"]); - newData.LandingType = (Byte) row["LandingType"]; - newData.MediaAutoScale = (Byte) row["MediaAutoScale"]; - newData.MediaID = new UUID((String) row["MediaTextureUUID"]); - newData.MediaURL = (String) row["MediaURL"]; - newData.MusicURL = (String) row["MusicURL"]; - newData.PassHours = Convert.ToSingle(row["PassHours"]); - newData.PassPrice = Convert.ToInt32(row["PassPrice"]); - newData.SnapshotID = (UUID)(String) row["SnapshotUUID"]; - try - { - - newData.UserLocation = - new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), - Convert.ToSingle(row["UserLocationZ"])); - newData.UserLookAt = - new Vector3(Convert.ToSingle(row["UserLookAtX"]), Convert.ToSingle(row["UserLookAtY"]), - Convert.ToSingle(row["UserLookAtZ"])); - - } - catch (InvalidCastException) - { - m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); - newData.UserLocation = Vector3.Zero; - newData.UserLookAt = Vector3.Zero; - } - newData.ParcelAccessList = new List(); - UUID authBuyerID = UUID.Zero; - - UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID); - - newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); - newData.Dwell = Convert.ToInt32(row["Dwell"]); - - return newData; - } - - private RegionSettings buildRegionSettings(DataRow row) - { - RegionSettings newSettings = new RegionSettings(); - - newSettings.RegionUUID = new UUID((string) row["regionUUID"]); - newSettings.BlockTerraform = Convert.ToBoolean(row["block_terraform"]); - newSettings.AllowDamage = Convert.ToBoolean(row["allow_damage"]); - newSettings.BlockFly = Convert.ToBoolean(row["block_fly"]); - newSettings.RestrictPushing = Convert.ToBoolean(row["restrict_pushing"]); - newSettings.AllowLandResell = Convert.ToBoolean(row["allow_land_resell"]); - newSettings.AllowLandJoinDivide = Convert.ToBoolean(row["allow_land_join_divide"]); - newSettings.BlockShowInSearch = Convert.ToBoolean(row["block_show_in_search"]); - newSettings.AgentLimit = Convert.ToInt32(row["agent_limit"]); - newSettings.ObjectBonus = Convert.ToDouble(row["object_bonus"]); - newSettings.Maturity = Convert.ToInt32(row["maturity"]); - newSettings.DisableScripts = Convert.ToBoolean(row["disable_scripts"]); - newSettings.DisableCollisions = Convert.ToBoolean(row["disable_collisions"]); - newSettings.DisablePhysics = Convert.ToBoolean(row["disable_physics"]); - newSettings.TerrainTexture1 = new UUID((String) row["terrain_texture_1"]); - newSettings.TerrainTexture2 = new UUID((String) row["terrain_texture_2"]); - newSettings.TerrainTexture3 = new UUID((String) row["terrain_texture_3"]); - newSettings.TerrainTexture4 = new UUID((String) row["terrain_texture_4"]); - newSettings.Elevation1NW = Convert.ToDouble(row["elevation_1_nw"]); - newSettings.Elevation2NW = Convert.ToDouble(row["elevation_2_nw"]); - newSettings.Elevation1NE = Convert.ToDouble(row["elevation_1_ne"]); - newSettings.Elevation2NE = Convert.ToDouble(row["elevation_2_ne"]); - newSettings.Elevation1SE = Convert.ToDouble(row["elevation_1_se"]); - newSettings.Elevation2SE = Convert.ToDouble(row["elevation_2_se"]); - newSettings.Elevation1SW = Convert.ToDouble(row["elevation_1_sw"]); - newSettings.Elevation2SW = Convert.ToDouble(row["elevation_2_sw"]); - newSettings.WaterHeight = Convert.ToDouble(row["water_height"]); - newSettings.TerrainRaiseLimit = Convert.ToDouble(row["terrain_raise_limit"]); - newSettings.TerrainLowerLimit = Convert.ToDouble(row["terrain_lower_limit"]); - newSettings.UseEstateSun = Convert.ToBoolean(row["use_estate_sun"]); - newSettings.Sandbox = Convert.ToBoolean(row["sandbox"]); - newSettings.SunVector = new Vector3 ( - Convert.ToSingle(row["sunvectorx"]), - Convert.ToSingle(row["sunvectory"]), - Convert.ToSingle(row["sunvectorz"]) - ); - newSettings.FixedSun = Convert.ToBoolean(row["fixed_sun"]); - newSettings.SunPosition = Convert.ToDouble(row["sun_position"]); - newSettings.Covenant = new UUID((String) row["covenant"]); - - return newSettings; - } - - /// - /// Build a land access entry from the persisted data. - /// - /// - /// - private static ParcelManager.ParcelAccessEntry buildLandAccessData(DataRow row) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = new UUID((string) row["AccessUUID"]); - entry.Flags = (AccessList) row["Flags"]; - entry.Time = new DateTime(); - return entry; - } - - /// - /// - /// - /// - /// - private static Array serializeTerrain(double[,] val) - { - MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize) *sizeof (double)); - BinaryWriter bw = new BinaryWriter(str); - - // TODO: COMPATIBILITY - Add byte-order conversions - for (int x = 0; x < (int)Constants.RegionSize; x++) - for (int y = 0; y < (int)Constants.RegionSize; y++) - bw.Write(val[x, y]); - - return str.ToArray(); - } - -// private void fillTerrainRow(DataRow row, UUID regionUUID, int rev, double[,] val) -// { -// row["RegionUUID"] = regionUUID; -// row["Revision"] = rev; - - // MemoryStream str = new MemoryStream(((int)Constants.RegionSize * (int)Constants.RegionSize)*sizeof (double)); -// BinaryWriter bw = new BinaryWriter(str); - -// // TODO: COMPATIBILITY - Add byte-order conversions - // for (int x = 0; x < (int)Constants.RegionSize; x++) - // for (int y = 0; y < (int)Constants.RegionSize; y++) -// bw.Write(val[x, y]); - -// row["Heightfield"] = str.ToArray(); -// } - - /// - /// - /// - /// - /// - /// - /// - private static void fillPrimRow(DataRow row, SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) - { - row["UUID"] = prim.UUID.ToString(); - row["RegionUUID"] = regionUUID.ToString(); - row["CreationDate"] = prim.CreationDate; - row["Name"] = prim.Name; - row["SceneGroupID"] = sceneGroupID.ToString(); - // the UUID of the root part for this SceneObjectGroup - // various text fields - row["Text"] = prim.Text; - row["Description"] = prim.Description; - row["SitName"] = prim.SitName; - row["TouchName"] = prim.TouchName; - // permissions - row["ObjectFlags"] = prim.ObjectFlags; - row["CreatorID"] = prim.CreatorID.ToString(); - row["OwnerID"] = prim.OwnerID.ToString(); - row["GroupID"] = prim.GroupID.ToString(); - row["LastOwnerID"] = prim.LastOwnerID.ToString(); - row["OwnerMask"] = prim.OwnerMask; - row["NextOwnerMask"] = prim.NextOwnerMask; - row["GroupMask"] = prim.GroupMask; - row["EveryoneMask"] = prim.EveryoneMask; - row["BaseMask"] = prim.BaseMask; - // vectors - row["PositionX"] = prim.OffsetPosition.X; - row["PositionY"] = prim.OffsetPosition.Y; - row["PositionZ"] = prim.OffsetPosition.Z; - row["GroupPositionX"] = prim.GroupPosition.X; - row["GroupPositionY"] = prim.GroupPosition.Y; - row["GroupPositionZ"] = prim.GroupPosition.Z; - row["VelocityX"] = prim.Velocity.X; - row["VelocityY"] = prim.Velocity.Y; - row["VelocityZ"] = prim.Velocity.Z; - row["AngularVelocityX"] = prim.AngularVelocity.X; - row["AngularVelocityY"] = prim.AngularVelocity.Y; - row["AngularVelocityZ"] = prim.AngularVelocity.Z; - row["AccelerationX"] = prim.Acceleration.X; - row["AccelerationY"] = prim.Acceleration.Y; - row["AccelerationZ"] = prim.Acceleration.Z; - // quaternions - row["RotationX"] = prim.RotationOffset.X; - row["RotationY"] = prim.RotationOffset.Y; - row["RotationZ"] = prim.RotationOffset.Z; - row["RotationW"] = prim.RotationOffset.W; - - // Sit target - Vector3 sitTargetPos = prim.SitTargetPositionLL; - row["SitTargetOffsetX"] = sitTargetPos.X; - row["SitTargetOffsetY"] = sitTargetPos.Y; - row["SitTargetOffsetZ"] = sitTargetPos.Z; - - Quaternion sitTargetOrient = prim.SitTargetOrientationLL; - row["SitTargetOrientW"] = sitTargetOrient.W; - row["SitTargetOrientX"] = sitTargetOrient.X; - row["SitTargetOrientY"] = sitTargetOrient.Y; - row["SitTargetOrientZ"] = sitTargetOrient.Z; - row["ColorR"] = Convert.ToInt32(prim.Color.R); - row["ColorG"] = Convert.ToInt32(prim.Color.G); - row["ColorB"] = Convert.ToInt32(prim.Color.B); - row["ColorA"] = Convert.ToInt32(prim.Color.A); - row["PayPrice"] = prim.PayPrice[0]; - row["PayButton1"] = prim.PayPrice[1]; - row["PayButton2"] = prim.PayPrice[2]; - row["PayButton3"] = prim.PayPrice[3]; - row["PayButton4"] = prim.PayPrice[4]; - - - row["TextureAnimation"] = Convert.ToBase64String(prim.TextureAnimation); - row["ParticleSystem"] = Convert.ToBase64String(prim.ParticleSystem); - - row["OmegaX"] = prim.AngularVelocity.X; - row["OmegaY"] = prim.AngularVelocity.Y; - row["OmegaZ"] = prim.AngularVelocity.Z; - - row["CameraEyeOffsetX"] = prim.GetCameraEyeOffset().X; - row["CameraEyeOffsetY"] = prim.GetCameraEyeOffset().Y; - row["CameraEyeOffsetZ"] = prim.GetCameraEyeOffset().Z; - - row["CameraAtOffsetX"] = prim.GetCameraAtOffset().X; - row["CameraAtOffsetY"] = prim.GetCameraAtOffset().Y; - row["CameraAtOffsetZ"] = prim.GetCameraAtOffset().Z; - - - if ((prim.SoundFlags & 1) != 0) // Looped - { - row["LoopedSound"] = prim.Sound.ToString(); - row["LoopedSoundGain"] = prim.SoundGain; - } - else - { - row["LoopedSound"] = UUID.Zero.ToString(); - row["LoopedSoundGain"] = 0.0f; - } - - if (prim.GetForceMouselook()) - row["ForceMouselook"] = 1; - else - row["ForceMouselook"] = 0; - - row["ScriptAccessPin"] = prim.ScriptAccessPin; - - if (prim.AllowedDrop) - row["AllowedDrop"] = 1; - else - row["AllowedDrop"] = 0; - - if (prim.DIE_AT_EDGE) - row["DieAtEdge"] = 1; - else - row["DieAtEdge"] = 0; - - row["SalePrice"] = prim.SalePrice; - row["SaleType"] = Convert.ToInt16(prim.ObjectSaleType); - - // click action - row["ClickAction"] = prim.ClickAction; - - row["SalePrice"] = prim.SalePrice; - row["Material"] = prim.Material; - - row["CollisionSound"] = prim.CollisionSound.ToString(); - row["CollisionSoundVolume"] = prim.CollisionSoundVolume; - if (prim.VolumeDetectActive) - row["VolumeDetect"] = 1; - else - row["VolumeDetect"] = 0; - - } - - /// - /// - /// - /// - /// - private static void fillItemRow(DataRow row, TaskInventoryItem taskItem) - { - row["itemID"] = taskItem.ItemID.ToString(); - row["primID"] = taskItem.ParentPartID.ToString(); - row["assetID"] = taskItem.AssetID.ToString(); - row["parentFolderID"] = taskItem.ParentID.ToString(); - - row["invType"] = taskItem.InvType; - row["assetType"] = taskItem.Type; - - row["name"] = taskItem.Name; - row["description"] = taskItem.Description; - row["creationDate"] = taskItem.CreationDate; - row["creatorID"] = taskItem.CreatorID.ToString(); - row["ownerID"] = taskItem.OwnerID.ToString(); - row["lastOwnerID"] = taskItem.LastOwnerID.ToString(); - row["groupID"] = taskItem.GroupID.ToString(); - row["nextPermissions"] = taskItem.NextPermissions; - row["currentPermissions"] = taskItem.CurrentPermissions; - row["basePermissions"] = taskItem.BasePermissions; - row["everyonePermissions"] = taskItem.EveryonePermissions; - row["groupPermissions"] = taskItem.GroupPermissions; - row["flags"] = taskItem.Flags; - } - - /// - /// - /// - /// - /// - /// - private static void fillLandRow(DataRow row, LandData land, UUID regionUUID) - { - row["UUID"] = land.GlobalID.ToString(); - row["RegionUUID"] = regionUUID.ToString(); - row["LocalLandID"] = land.LocalID; - - // Bitmap is a byte[512] - row["Bitmap"] = land.Bitmap; - - row["Name"] = land.Name; - row["Desc"] = land.Description; - row["OwnerUUID"] = land.OwnerID.ToString(); - row["IsGroupOwned"] = land.IsGroupOwned; - row["Area"] = land.Area; - row["AuctionID"] = land.AuctionID; //Unemplemented - row["Category"] = land.Category; //Enum OpenMetaverse.Parcel.ParcelCategory - row["ClaimDate"] = land.ClaimDate; - row["ClaimPrice"] = land.ClaimPrice; - row["GroupUUID"] = land.GroupID.ToString(); - row["SalePrice"] = land.SalePrice; - row["LandStatus"] = land.Status; //Enum. OpenMetaverse.Parcel.ParcelStatus - row["LandFlags"] = land.Flags; - row["LandingType"] = land.LandingType; - row["MediaAutoScale"] = land.MediaAutoScale; - row["MediaTextureUUID"] = land.MediaID.ToString(); - row["MediaURL"] = land.MediaURL; - row["MusicURL"] = land.MusicURL; - row["PassHours"] = land.PassHours; - row["PassPrice"] = land.PassPrice; - row["SnapshotUUID"] = land.SnapshotID.ToString(); - row["UserLocationX"] = land.UserLocation.X; - row["UserLocationY"] = land.UserLocation.Y; - row["UserLocationZ"] = land.UserLocation.Z; - row["UserLookAtX"] = land.UserLookAt.X; - row["UserLookAtY"] = land.UserLookAt.Y; - row["UserLookAtZ"] = land.UserLookAt.Z; - row["AuthbuyerID"] = land.AuthBuyerID.ToString(); - row["OtherCleanTime"] = land.OtherCleanTime; - row["Dwell"] = land.Dwell; - } - - /// - /// - /// - /// - /// - /// - private static void fillLandAccessRow(DataRow row, ParcelManager.ParcelAccessEntry entry, UUID parcelID) - { - row["LandUUID"] = parcelID.ToString(); - row["AccessUUID"] = entry.AgentID.ToString(); - row["Flags"] = entry.Flags; - } - - private static void fillRegionSettingsRow(DataRow row, RegionSettings settings) - { - row["regionUUID"] = settings.RegionUUID.ToString(); - row["block_terraform"] = settings.BlockTerraform; - row["block_fly"] = settings.BlockFly; - row["allow_damage"] = settings.AllowDamage; - row["restrict_pushing"] = settings.RestrictPushing; - row["allow_land_resell"] = settings.AllowLandResell; - row["allow_land_join_divide"] = settings.AllowLandJoinDivide; - row["block_show_in_search"] = settings.BlockShowInSearch; - row["agent_limit"] = settings.AgentLimit; - row["object_bonus"] = settings.ObjectBonus; - row["maturity"] = settings.Maturity; - row["disable_scripts"] = settings.DisableScripts; - row["disable_collisions"] = settings.DisableCollisions; - row["disable_physics"] = settings.DisablePhysics; - row["terrain_texture_1"] = settings.TerrainTexture1.ToString(); - row["terrain_texture_2"] = settings.TerrainTexture2.ToString(); - row["terrain_texture_3"] = settings.TerrainTexture3.ToString(); - row["terrain_texture_4"] = settings.TerrainTexture4.ToString(); - row["elevation_1_nw"] = settings.Elevation1NW; - row["elevation_2_nw"] = settings.Elevation2NW; - row["elevation_1_ne"] = settings.Elevation1NE; - row["elevation_2_ne"] = settings.Elevation2NE; - row["elevation_1_se"] = settings.Elevation1SE; - row["elevation_2_se"] = settings.Elevation2SE; - row["elevation_1_sw"] = settings.Elevation1SW; - row["elevation_2_sw"] = settings.Elevation2SW; - row["water_height"] = settings.WaterHeight; - row["terrain_raise_limit"] = settings.TerrainRaiseLimit; - row["terrain_lower_limit"] = settings.TerrainLowerLimit; - row["use_estate_sun"] = settings.UseEstateSun; - row["Sandbox"] = settings.Sandbox; // database uses upper case S for sandbox - row["sunvectorx"] = settings.SunVector.X; - row["sunvectory"] = settings.SunVector.Y; - row["sunvectorz"] = settings.SunVector.Z; - row["fixed_sun"] = settings.FixedSun; - row["sun_position"] = settings.SunPosition; - row["covenant"] = settings.Covenant.ToString(); - } - - /// - /// - /// - /// - /// - private PrimitiveBaseShape buildShape(DataRow row) - { - PrimitiveBaseShape s = new PrimitiveBaseShape(); - s.Scale = new Vector3( - Convert.ToSingle(row["ScaleX"]), - Convert.ToSingle(row["ScaleY"]), - Convert.ToSingle(row["ScaleZ"]) - ); - // paths - s.PCode = Convert.ToByte(row["PCode"]); - s.PathBegin = Convert.ToUInt16(row["PathBegin"]); - s.PathEnd = Convert.ToUInt16(row["PathEnd"]); - s.PathScaleX = Convert.ToByte(row["PathScaleX"]); - s.PathScaleY = Convert.ToByte(row["PathScaleY"]); - s.PathShearX = Convert.ToByte(row["PathShearX"]); - s.PathShearY = Convert.ToByte(row["PathShearY"]); - s.PathSkew = Convert.ToSByte(row["PathSkew"]); - s.PathCurve = Convert.ToByte(row["PathCurve"]); - s.PathRadiusOffset = Convert.ToSByte(row["PathRadiusOffset"]); - s.PathRevolutions = Convert.ToByte(row["PathRevolutions"]); - s.PathTaperX = Convert.ToSByte(row["PathTaperX"]); - s.PathTaperY = Convert.ToSByte(row["PathTaperY"]); - s.PathTwist = Convert.ToSByte(row["PathTwist"]); - s.PathTwistBegin = Convert.ToSByte(row["PathTwistBegin"]); - // profile - s.ProfileBegin = Convert.ToUInt16(row["ProfileBegin"]); - s.ProfileEnd = Convert.ToUInt16(row["ProfileEnd"]); - s.ProfileCurve = Convert.ToByte(row["ProfileCurve"]); - s.ProfileHollow = Convert.ToUInt16(row["ProfileHollow"]); - s.State = Convert.ToByte(row["State"]); - - byte[] textureEntry = (byte[])row["Texture"]; - s.TextureEntry = textureEntry; - - s.ExtraParams = (byte[]) row["ExtraParams"]; - return s; - } - - /// - /// - /// - /// - /// - private static void fillShapeRow(DataRow row, SceneObjectPart prim) - { - PrimitiveBaseShape s = prim.Shape; - row["UUID"] = prim.UUID.ToString(); - // shape is an enum - row["Shape"] = 0; - // vectors - row["ScaleX"] = s.Scale.X; - row["ScaleY"] = s.Scale.Y; - row["ScaleZ"] = s.Scale.Z; - // paths - row["PCode"] = s.PCode; - row["PathBegin"] = s.PathBegin; - row["PathEnd"] = s.PathEnd; - row["PathScaleX"] = s.PathScaleX; - row["PathScaleY"] = s.PathScaleY; - row["PathShearX"] = s.PathShearX; - row["PathShearY"] = s.PathShearY; - row["PathSkew"] = s.PathSkew; - row["PathCurve"] = s.PathCurve; - row["PathRadiusOffset"] = s.PathRadiusOffset; - row["PathRevolutions"] = s.PathRevolutions; - row["PathTaperX"] = s.PathTaperX; - row["PathTaperY"] = s.PathTaperY; - row["PathTwist"] = s.PathTwist; - row["PathTwistBegin"] = s.PathTwistBegin; - // profile - row["ProfileBegin"] = s.ProfileBegin; - row["ProfileEnd"] = s.ProfileEnd; - row["ProfileCurve"] = s.ProfileCurve; - row["ProfileHollow"] = s.ProfileHollow; - row["State"] = s.State; - - row["Texture"] = s.TextureEntry; - row["ExtraParams"] = s.ExtraParams; - } - - /// - /// - /// - /// - /// - /// - private void addPrim(SceneObjectPart prim, UUID sceneGroupID, UUID regionUUID) - { - - DataTable prims = ds.Tables["prims"]; - DataTable shapes = ds.Tables["primshapes"]; - - DataRow primRow = prims.Rows.Find(prim.UUID.ToString()); - if (primRow == null) - { - primRow = prims.NewRow(); - fillPrimRow(primRow, prim, sceneGroupID, regionUUID); - prims.Rows.Add(primRow); - } - else - { - fillPrimRow(primRow, prim, sceneGroupID, regionUUID); - } - - DataRow shapeRow = shapes.Rows.Find(prim.UUID.ToString()); - if (shapeRow == null) - { - shapeRow = shapes.NewRow(); - fillShapeRow(shapeRow, prim); - shapes.Rows.Add(shapeRow); - } - else - { - fillShapeRow(shapeRow, prim); - } - } - - /// - /// see IRegionDatastore - /// - /// - /// - public void StorePrimInventory(UUID primID, ICollection items) - { - m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); - - DataTable dbItems = ds.Tables["primitems"]; - - // For now, we're just going to crudely remove all the previous inventory items - // no matter whether they have changed or not, and replace them with the current set. - lock (ds) - { - RemoveItems(primID); - - // repalce with current inventory details - foreach (TaskInventoryItem newItem in items) - { -// m_log.InfoFormat( -// "[DATASTORE]: ", -// "Adding item {0}, {1} to prim ID {2}", -// newItem.Name, newItem.ItemID, newItem.ParentPartID); - - DataRow newItemRow = dbItems.NewRow(); - fillItemRow(newItemRow, newItem); - dbItems.Rows.Add(newItemRow); - } - } - - Commit(); - } - - /*********************************************************************** - * - * SQL Statement Creation Functions - * - * These functions create SQL statements for update, insert, and create. - * They can probably be factored later to have a db independant - * portion and a db specific portion - * - **********************************************************************/ - - /// - /// Create an insert command - /// - /// table name - /// data table - /// the created command - /// - /// This is subtle enough to deserve some commentary. - /// Instead of doing *lots* and *lots of hardcoded strings - /// for database definitions we'll use the fact that - /// realistically all insert statements look like "insert - /// into A(b, c) values(:b, :c) on the parameterized query - /// front. If we just have a list of b, c, etc... we can - /// generate these strings instead of typing them out. - /// - private static SqliteCommand createInsertCommand(string table, DataTable dt) - { - string[] cols = new string[dt.Columns.Count]; - for (int i = 0; i < dt.Columns.Count; i++) - { - DataColumn col = dt.Columns[i]; - cols[i] = col.ColumnName; - } - - string sql = "insert into " + table + "("; - sql += String.Join(", ", cols); - // important, the first ':' needs to be here, the rest get added in the join - sql += ") values (:"; - sql += String.Join(", :", cols); - sql += ")"; - m_log.DebugFormat("[SQLITE]: Created insert command {0}", sql); - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - - /// - /// create an update command - /// - /// table name - /// - /// - /// the created command - private static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) - { - string sql = "update " + table + " set "; - string subsql = String.Empty; - foreach (DataColumn col in dt.Columns) - { - if (subsql.Length > 0) - { - // a map function would rock so much here - subsql += ", "; - } - subsql += col.ColumnName + "= :" + col.ColumnName; - } - sql += subsql; - sql += " where " + pk; - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - /// - /// create an update command - /// - /// table name - /// - /// - /// the created command - private static SqliteCommand createUpdateCommand(string table, string pk1, string pk2, DataTable dt) - { - string sql = "update " + table + " set "; - string subsql = String.Empty; - foreach (DataColumn col in dt.Columns) - { - if (subsql.Length > 0) - { - // a map function would rock so much here - subsql += ", "; - } - subsql += col.ColumnName + "= :" + col.ColumnName; - } - sql += subsql; - sql += " where " + pk1 + " and " + pk2; - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - /// - /// - /// - /// Data Table - /// - // private static string defineTable(DataTable dt) - // { - // string sql = "create table " + dt.TableName + "("; - // string subsql = String.Empty; - // foreach (DataColumn col in dt.Columns) - // { - // if (subsql.Length > 0) - // { - // // a map function would rock so much here - // subsql += ",\n"; - // } - // subsql += col.ColumnName + " " + sqliteType(col.DataType); - // if (dt.PrimaryKey.Length > 0 && col == dt.PrimaryKey[0]) - // { - // subsql += " primary key"; - // } - // } - // sql += subsql; - // sql += ")"; - // return sql; - // } - - /*********************************************************************** - * - * Database Binding functions - * - * These will be db specific due to typing, and minor differences - * in databases. - * - **********************************************************************/ - - /// - /// This is a convenience function that collapses 5 repetitive - /// lines for defining SqliteParameters to 2 parameters: - /// column name and database type. - /// - /// It assumes certain conventions like :param as the param - /// name to replace in parametrized queries, and that source - /// version is always current version, both of which are fine - /// for us. - /// - ///a built sqlite parameter - private static SqliteParameter createSqliteParameter(string name, Type type) - { - SqliteParameter param = new SqliteParameter(); - param.ParameterName = ":" + name; - param.DbType = dbtypeFromType(type); - param.SourceColumn = name; - param.SourceVersion = DataRowVersion.Current; - return param; - } - - /// - /// - /// - /// - /// - private void setupPrimCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("prims", ds.Tables["prims"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("prims", "UUID=:UUID", ds.Tables["prims"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from prims where UUID = :UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - - /// - /// - /// - /// - /// - private void setupItemsCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("primitems", ds.Tables["primitems"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("primitems", "itemID = :itemID", ds.Tables["primitems"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from primitems where itemID = :itemID"); - delete.Parameters.Add(createSqliteParameter("itemID", typeof (String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - - /// - /// - /// - /// - /// - private void setupTerrainCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("terrain", ds.Tables["terrain"]); - da.InsertCommand.Connection = conn; - } - - /// - /// - /// - /// - /// - private void setupLandCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("land", ds.Tables["land"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("land", "UUID=:UUID", ds.Tables["land"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from land where UUID=:UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof(String))); - da.DeleteCommand = delete; - da.DeleteCommand.Connection = conn; - } - - /// - /// - /// - /// - /// - private void setupLandAccessCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("landaccesslist", ds.Tables["landaccesslist"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("landaccesslist", "LandUUID=:landUUID", "AccessUUID=:AccessUUID", ds.Tables["landaccesslist"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from landaccesslist where LandUUID= :LandUUID and AccessUUID= :AccessUUID"); - delete.Parameters.Add(createSqliteParameter("LandUUID", typeof(String))); - delete.Parameters.Add(createSqliteParameter("AccessUUID", typeof(String))); - da.DeleteCommand = delete; - da.DeleteCommand.Connection = conn; - - } - - private void setupRegionSettingsCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("regionsettings", ds.Tables["regionsettings"]); - da.InsertCommand.Connection = conn; - da.UpdateCommand = createUpdateCommand("regionsettings", "regionUUID=:regionUUID", ds.Tables["regionsettings"]); - da.UpdateCommand.Connection = conn; - } - - /// - /// - /// - /// - /// - private void setupShapeCommands(SqliteDataAdapter da, SqliteConnection conn) - { - da.InsertCommand = createInsertCommand("primshapes", ds.Tables["primshapes"]); - da.InsertCommand.Connection = conn; - - da.UpdateCommand = createUpdateCommand("primshapes", "UUID=:UUID", ds.Tables["primshapes"]); - da.UpdateCommand.Connection = conn; - - SqliteCommand delete = new SqliteCommand("delete from primshapes where UUID = :UUID"); - delete.Parameters.Add(createSqliteParameter("UUID", typeof (String))); - delete.Connection = conn; - da.DeleteCommand = delete; - } - - /*********************************************************************** - * - * Type conversion functions - * - **********************************************************************/ - - /// - /// Type conversion function - /// - /// - /// - private static DbType dbtypeFromType(Type type) - { - if (type == typeof (String)) - { - return DbType.String; - } - else if (type == typeof (Int32)) - { - return DbType.Int32; - } - else if (type == typeof (Double)) - { - return DbType.Double; - } - else if (type == typeof (Byte)) - { - return DbType.Byte; - } - else if (type == typeof (Double)) - { - return DbType.Double; - } - else if (type == typeof (Byte[])) - { - return DbType.Binary; - } - else - { - return DbType.String; - } - } - - static void PrintDataSet(DataSet ds) - { - // Print out any name and extended properties. - Console.WriteLine("DataSet is named: {0}", ds.DataSetName); - foreach (System.Collections.DictionaryEntry de in ds.ExtendedProperties) - { - Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value); - } - Console.WriteLine(); - foreach (DataTable dt in ds.Tables) - { - Console.WriteLine("=> {0} Table:", dt.TableName); - // Print out the column names. - for (int curCol = 0; curCol < dt.Columns.Count; curCol++) - { - Console.Write(dt.Columns[curCol].ColumnName + "\t"); - } - Console.WriteLine("\n----------------------------------"); - // Print the DataTable. - for (int curRow = 0; curRow < dt.Rows.Count; curRow++) - { - for (int curCol = 0; curCol < dt.Columns.Count; curCol++) - { - Console.Write(dt.Rows[curRow][curCol].ToString() + "\t"); - } - Console.WriteLine(); - } - } - } - - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs b/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs deleted file mode 100644 index f77159c..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteUserAccountData.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.Sqlite; - -namespace OpenSim.Data.SQLiteNG -{ - public class SQLiteUserAccountData : SQLiteGenericTableHandler, IUserAccountData - { - public SQLiteUserAccountData(string connectionString, string realm) - : base(connectionString, realm, "UserAccount") - { - } - - public UserAccountData[] GetUsers(UUID scopeID, string query) - { - string[] words = query.Split(new char[] {' '}); - - for (int i = 0 ; i < words.Length ; i++) - { - if (words[i].Length < 3) - { - if (i != words.Length - 1) - Array.Copy(words, i + 1, words, i, words.Length - i - 1); - Array.Resize(ref words, words.Length - 1); - } - } - - if (words.Length == 0) - return new UserAccountData[0]; - - if (words.Length > 2) - return new UserAccountData[0]; - - SqliteCommand cmd = new SqliteCommand(); - - if (words.Length == 1) - { - cmd.CommandText = String.Format("select * from {0} where ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", - m_Realm, scopeID.ToString(), words[0]); - } - else - { - cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{3}%')", - m_Realm, scopeID.ToString(), words[0], words[1]); - } - - return DoQuery(cmd); - } - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteUtils.cs b/OpenSim/Data/SQLiteNG/SQLiteUtils.cs deleted file mode 100644 index 82a2e37..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteUtils.cs +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Data; -using Mono.Data.Sqlite; - -namespace OpenSim.Data.SQLiteNG -{ - /// - /// A base class for methods needed by all SQLite database classes - /// - public class SQLiteUtil - { - /*********************************************************************** - * - * Database Definition Helper Functions - * - * This should be db agnostic as we define them in ADO.NET terms - * - **********************************************************************/ - - /// - /// - /// - /// - /// - /// - public static void createCol(DataTable dt, string name, Type type) - { - DataColumn col = new DataColumn(name, type); - dt.Columns.Add(col); - } - - /*********************************************************************** - * - * SQL Statement Creation Functions - * - * These functions create SQL statements for update, insert, and create. - * They can probably be factored later to have a db independant - * portion and a db specific portion - * - **********************************************************************/ - - /// - /// Create an insert command - /// - /// table name - /// data table - /// the created command - /// - /// This is subtle enough to deserve some commentary. - /// Instead of doing *lots* and *lots of hardcoded strings - /// for database definitions we'll use the fact that - /// realistically all insert statements look like "insert - /// into A(b, c) values(:b, :c) on the parameterized query - /// front. If we just have a list of b, c, etc... we can - /// generate these strings instead of typing them out. - /// - public static SqliteCommand createInsertCommand(string table, DataTable dt) - { - - string[] cols = new string[dt.Columns.Count]; - for (int i = 0; i < dt.Columns.Count; i++) - { - DataColumn col = dt.Columns[i]; - cols[i] = col.ColumnName; - } - - string sql = "insert into " + table + "("; - sql += String.Join(", ", cols); - // important, the first ':' needs to be here, the rest get added in the join - sql += ") values (:"; - sql += String.Join(", :", cols); - sql += ")"; - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - /// - /// create an update command - /// - /// table name - /// - /// - /// the created command - public static SqliteCommand createUpdateCommand(string table, string pk, DataTable dt) - { - string sql = "update " + table + " set "; - string subsql = String.Empty; - foreach (DataColumn col in dt.Columns) - { - if (subsql.Length > 0) - { - // a map function would rock so much here - subsql += ", "; - } - subsql += col.ColumnName + "= :" + col.ColumnName; - } - sql += subsql; - sql += " where " + pk; - SqliteCommand cmd = new SqliteCommand(sql); - - // this provides the binding for all our parameters, so - // much less code than it used to be - - foreach (DataColumn col in dt.Columns) - { - cmd.Parameters.Add(createSqliteParameter(col.ColumnName, col.DataType)); - } - return cmd; - } - - /// - /// - /// - /// Data Table - /// - public static string defineTable(DataTable dt) - { - string sql = "create table " + dt.TableName + "("; - string subsql = String.Empty; - foreach (DataColumn col in dt.Columns) - { - if (subsql.Length > 0) - { - // a map function would rock so much here - subsql += ",\n"; - } - subsql += col.ColumnName + " " + sqliteType(col.DataType); - if (dt.PrimaryKey.Length > 0) - { - if (col == dt.PrimaryKey[0]) - { - subsql += " primary key"; - } - } - } - sql += subsql; - sql += ")"; - return sql; - } - - /*********************************************************************** - * - * Database Binding functions - * - * These will be db specific due to typing, and minor differences - * in databases. - * - **********************************************************************/ - - /// - /// - /// This is a convenience function that collapses 5 repetitive - /// lines for defining SqliteParameters to 2 parameters: - /// column name and database type. - /// - /// - /// - /// It assumes certain conventions like :param as the param - /// name to replace in parametrized queries, and that source - /// version is always current version, both of which are fine - /// for us. - /// - /// - /// - /// - ///a built sqlite parameter - public static SqliteParameter createSqliteParameter(string name, Type type) - { - SqliteParameter param = new SqliteParameter(); - param.ParameterName = ":" + name; - param.DbType = dbtypeFromType(type); - param.SourceColumn = name; - param.SourceVersion = DataRowVersion.Current; - return param; - } - - /*********************************************************************** - * - * Type conversion functions - * - **********************************************************************/ - - /// - /// Type conversion function - /// - /// a type - /// a DbType - public static DbType dbtypeFromType(Type type) - { - if (type == typeof (String)) - { - return DbType.String; - } - else if (type == typeof (Int32)) - { - return DbType.Int32; - } - else if (type == typeof (UInt32)) - { - return DbType.UInt32; - } - else if (type == typeof (Int64)) - { - return DbType.Int64; - } - else if (type == typeof (UInt64)) - { - return DbType.UInt64; - } - else if (type == typeof (Double)) - { - return DbType.Double; - } - else if (type == typeof (Boolean)) - { - return DbType.Boolean; - } - else if (type == typeof (Byte[])) - { - return DbType.Binary; - } - else - { - return DbType.String; - } - } - - /// - /// - /// a Type - /// a string - /// this is something we'll need to implement for each db slightly differently. - public static string sqliteType(Type type) - { - if (type == typeof (String)) - { - return "varchar(255)"; - } - else if (type == typeof (Int32)) - { - return "integer"; - } - else if (type == typeof (UInt32)) - { - return "integer"; - } - else if (type == typeof (Int64)) - { - return "varchar(255)"; - } - else if (type == typeof (UInt64)) - { - return "varchar(255)"; - } - else if (type == typeof (Double)) - { - return "float"; - } - else if (type == typeof (Boolean)) - { - return "integer"; - } - else if (type == typeof (Byte[])) - { - return "blob"; - } - else - { - return "string"; - } - } - } -} diff --git a/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs b/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs deleted file mode 100644 index a0c17f8..0000000 --- a/OpenSim/Data/SQLiteNG/SQLiteXInventoryData.cs +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Data; -using System.Reflection; -using System.Collections.Generic; -using Mono.Data.Sqlite; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; - -namespace OpenSim.Data.SQLiteNG -{ - /// - /// A MySQL Interface for the Asset Server - /// - public class SQLiteXInventoryData : IXInventoryData - { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private SQLiteGenericTableHandler m_Folders; - private SqliteItemHandler m_Items; - - public SQLiteXInventoryData(string conn, string realm) - { - m_Folders = new SQLiteGenericTableHandler( - conn, "inventoryfolders", "InventoryStore"); - m_Items = new SqliteItemHandler( - conn, "inventoryitems", String.Empty); - } - - public XInventoryFolder[] GetFolders(string[] fields, string[] vals) - { - return m_Folders.Get(fields, vals); - } - - public XInventoryItem[] GetItems(string[] fields, string[] vals) - { - return m_Items.Get(fields, vals); - } - - public bool StoreFolder(XInventoryFolder folder) - { - return m_Folders.Store(folder); - } - - public bool StoreItem(XInventoryItem item) - { - return m_Items.Store(item); - } - - public bool DeleteFolders(string field, string val) - { - return m_Folders.Delete(field, val); - } - - public bool DeleteItems(string field, string val) - { - return m_Items.Delete(field, val); - } - - public bool MoveItem(string id, string newParent) - { - return m_Items.MoveItem(id, newParent); - } - - public XInventoryItem[] GetActiveGestures(UUID principalID) - { - return m_Items.GetActiveGestures(principalID); - } - - public int GetAssetPermissions(UUID principalID, UUID assetID) - { - return m_Items.GetAssetPermissions(principalID, assetID); - } - } - - public class SqliteItemHandler : SQLiteGenericTableHandler - { - public SqliteItemHandler(string c, string t, string m) : - base(c, t, m) - { - } - - public bool MoveItem(string id, string newParent) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("update {0} set parentFolderID = :ParentFolderID where inventoryID = :InventoryID", m_Realm); - cmd.Parameters.Add(new SqliteParameter(":ParentFolderID", newParent)); - cmd.Parameters.Add(new SqliteParameter(":InventoryID", id)); - - return ExecuteNonQuery(cmd, m_Connection) == 0 ? false : true; - } - - public XInventoryItem[] GetActiveGestures(UUID principalID) - { - SqliteCommand cmd = new SqliteCommand(); - cmd.CommandText = String.Format("select * from inventoryitems where avatarId = :uuid and assetType = :type and flags = 1", m_Realm); - - cmd.Parameters.Add(new SqliteParameter(":uuid", principalID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":type", (int)AssetType.Gesture)); - - return DoQuery(cmd); - } - - public int GetAssetPermissions(UUID principalID, UUID assetID) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("select inventoryCurrentPermissions from inventoryitems where avatarID = :PrincipalID and assetID = :AssetID", m_Realm); - cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); - cmd.Parameters.Add(new SqliteParameter(":AssetID", assetID.ToString())); - - IDataReader reader = ExecuteReader(cmd, m_Connection); - - int perms = 0; - - while (reader.Read()) - { - perms |= Convert.ToInt32(reader["inventoryCurrentPermissions"]); - } - - reader.Close(); - //CloseCommand(cmd); - - return perms; - } - } -} diff --git a/OpenSim/Data/Tests/DataTestUtil.cs b/OpenSim/Data/Tests/DataTestUtil.cs index d211ab3..5393529 100644 --- a/OpenSim/Data/Tests/DataTestUtil.cs +++ b/OpenSim/Data/Tests/DataTestUtil.cs @@ -39,7 +39,8 @@ namespace OpenSim.Data.Tests public class DataTestUtil { public const uint UNSIGNED_INTEGER_MIN = uint.MinValue; - public const uint UNSIGNED_INTEGER_MAX = uint.MaxValue; + //public const uint UNSIGNED_INTEGER_MAX = uint.MaxValue; + public const uint UNSIGNED_INTEGER_MAX = INTEGER_MAX; public const int INTEGER_MIN = int.MinValue + 1; // Postgresql requires +1 to .NET int.MinValue public const int INTEGER_MAX = int.MaxValue; diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 5214718..3e9d376 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -126,9 +126,15 @@ ;storage_plugin = "OpenSim.Data.Null.dll" ; --- To use sqlite as region storage: - ; NOTE: SQLite and OpenSim are not functioning properly with Mono 2.4.3 or greater. - ; If you are using Mono you probably should be using MySQL + ; + ; PLEASE NOTE: Unfortunately, the current SQLite database plugin (necessary to use SQLite with Mono on Linux) is + ; not compatible with the sqlite3 library installed on Mac OSX. If you're using Mono 2.4 you can still use the old sqlite + ; library by uncommenting the SQLiteLegacy.dll storage plugin (and commenting out SQLite.dll). Unfortunately, the older library + ; will not work with Mono 2.6 on Mac OSX so you will either need to replace the OSX sqlite3 system library or use MySQL instead + ; + ; You will also need to do the same thing in config-include/StandaloneCommon.ini if you are running in standalone mode storage_plugin = "OpenSim.Data.SQLite.dll" + ;storage_plugin = "OpenSim.Data.SQLiteLegacy.dll" storage_connection_string="URI=file:OpenSim.db,version=3"; ; --- To use MySQL storage, supply your own connection string (this is only an example): diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 1679f93..40ef228 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -4,7 +4,15 @@ ; ;--- For SQLite StorageProvider = "OpenSim.Data.SQLite.dll" - ;--- For MySql + + ; Unfortunately the current SQLite database plugin is not compatible with Mac OSX. You can still use the older + ; legacy sqlite library if you are using Mono 2.4. Please see the notes in OpenSim.ini (search for sqlite) + ; for more details + ;StorageProvider = "OpenSim.Data.SQLiteLegacy.dll"; + + ; MySql + ; Uncomment these lines if you want to use mysql storage + ; Change the connection string to your db details ;StorageProvider = "OpenSim.Data.MySQL.dll" ;ConnectionString = "Data Source=localhost;Database=opensim;User ID=opensim;Password=***;" @@ -42,4 +50,4 @@ [LibraryModule] ; Set this if you want to change the name of the OpenSim Library - ;LibraryName = "My World's Library" \ No newline at end of file + ;LibraryName = "My World's Library" diff --git a/prebuild.xml b/prebuild.xml index 7c7e3c7..908855f 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2473,7 +2473,7 @@ - + ../../../bin/ @@ -2510,7 +2510,7 @@ - + ../../../bin/ -- cgit v1.1 From d8b604b550c76610187d929087bce3b08e7018c5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 30 Apr 2010 18:18:21 +0100 Subject: take out some debug logging in the sqlite db adaptor --- OpenSim/Data/SQLite/SQLiteRegionData.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs index 85368ab..fe6e919 100644 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLite/SQLiteRegionData.cs @@ -769,7 +769,7 @@ namespace OpenSim.Data.SQLite /// public void Commit() { - m_log.Debug("[SQLITE]: Starting commit"); + //m_log.Debug("[SQLITE]: Starting commit"); lock (ds) { primDa.Update(ds, "prims"); @@ -1914,7 +1914,7 @@ namespace OpenSim.Data.SQLite /// public void StorePrimInventory(UUID primID, ICollection items) { - m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); + //m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); DataTable dbItems = ds.Tables["primitems"]; @@ -1981,7 +1981,7 @@ namespace OpenSim.Data.SQLite sql += ") values (:"; sql += String.Join(", :", cols); sql += ")"; - m_log.DebugFormat("[SQLITE]: Created insert command {0}", sql); + //m_log.DebugFormat("[SQLITE]: Created insert command {0}", sql); SqliteCommand cmd = new SqliteCommand(sql); // this provides the binding for all our parameters, so -- cgit v1.1 From 0b8b302aa0f2ee25be5cbdfefe232459e6e5b778 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 30 Apr 2010 20:05:57 +0100 Subject: Fix a bunch of issues that crop up after the naive porting of the new sqlite db from master to 0.6.9 --- OpenSim/Data/SQLite/SQLiteAuthenticationData.cs | 257 --------------------- OpenSim/Data/SQLite/SQLiteEstateData.cs | 65 +----- OpenSim/Data/SQLite/SQLiteFramework.cs | 27 +-- OpenSim/Data/SQLite/SQLiteFriendsData.cs | 70 ------ OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs | 13 +- OpenSim/Data/SQLite/SQLiteInventoryStore.cs | 18 +- OpenSim/Data/SQLite/SQLiteManager.cs | 8 +- OpenSim/Data/SQLite/SQLiteUserAccountData.cs | 81 ------- OpenSim/Data/SQLite/SQLiteUserData.cs | 2 +- OpenSim/Data/SQLite/SQLiteXInventoryData.cs | 6 +- OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs | 3 +- OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs | 74 ------ OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs | 12 +- OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs | 70 ------ OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs | 11 +- OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs | 81 ------- 16 files changed, 24 insertions(+), 774 deletions(-) delete mode 100644 OpenSim/Data/SQLite/SQLiteAuthenticationData.cs delete mode 100644 OpenSim/Data/SQLite/SQLiteFriendsData.cs delete mode 100644 OpenSim/Data/SQLite/SQLiteUserAccountData.cs delete mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs delete mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs delete mode 100644 OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs diff --git a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs b/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs deleted file mode 100644 index 086ac0a..0000000 --- a/OpenSim/Data/SQLite/SQLiteAuthenticationData.cs +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.Sqlite; - -namespace OpenSim.Data.SQLite -{ - public class SQLiteAuthenticationData : SQLiteFramework, IAuthenticationData - { - private string m_Realm; - private List m_ColumnNames; - private int m_LastExpire; - private string m_connectionString; - - protected static SqliteConnection m_Connection; - private static bool m_initialized = false; - - public SQLiteAuthenticationData(string connectionString, string realm) - : base(connectionString) - { - m_Realm = realm; - m_connectionString = connectionString; - - if (!m_initialized) - { - m_Connection = new SqliteConnection(connectionString); - m_Connection.Open(); - - Migration m = new Migration(m_Connection, GetType().Assembly, "AuthStore"); - m.Update(); - - m_initialized = true; - } - } - - public AuthenticationData Get(UUID principalID) - { - AuthenticationData ret = new AuthenticationData(); - ret.Data = new Dictionary(); - - SqliteCommand cmd = new SqliteCommand("select * from `" + m_Realm + "` where UUID = :PrincipalID"); - cmd.Parameters.Add(new SqliteParameter(":PrincipalID", principalID.ToString())); - - IDataReader result = ExecuteReader(cmd, m_Connection); - - try - { - if (result.Read()) - { - ret.PrincipalID = principalID; - - if (m_ColumnNames == null) - { - m_ColumnNames = new List(); - - DataTable schemaTable = result.GetSchemaTable(); - foreach (DataRow row in schemaTable.Rows) - m_ColumnNames.Add(row["ColumnName"].ToString()); - } - - foreach (string s in m_ColumnNames) - { - if (s == "UUID") - continue; - - ret.Data[s] = result[s].ToString(); - } - - return ret; - } - else - { - return null; - } - } - catch - { - } - finally - { - //CloseCommand(cmd); - } - - return null; - } - - public bool Store(AuthenticationData data) - { - if (data.Data.ContainsKey("UUID")) - data.Data.Remove("UUID"); - - string[] fields = new List(data.Data.Keys).ToArray(); - string[] values = new string[data.Data.Count]; - int i = 0; - foreach (object o in data.Data.Values) - values[i++] = o.ToString(); - - SqliteCommand cmd = new SqliteCommand(); - - if (Get(data.PrincipalID) != null) - { - - - string update = "update `" + m_Realm + "` set "; - bool first = true; - foreach (string field in fields) - { - if (!first) - update += ", "; - update += "`" + field + "` = :" + field; - cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); - - first = false; - } - - update += " where UUID = :UUID"; - cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); - - cmd.CommandText = update; - try - { - if (ExecuteNonQuery(cmd, m_Connection) < 1) - { - //CloseCommand(cmd); - return false; - } - } - catch (Exception e) - { - Console.WriteLine(e.ToString()); - //CloseCommand(cmd); - return false; - } - } - - else - { - string insert = "insert into `" + m_Realm + "` (`UUID`, `" + - String.Join("`, `", fields) + - "`) values (:UUID, :" + String.Join(", :", fields) + ")"; - - cmd.Parameters.Add(new SqliteParameter(":UUID", data.PrincipalID.ToString())); - foreach (string field in fields) - cmd.Parameters.Add(new SqliteParameter(":" + field, data.Data[field])); - - cmd.CommandText = insert; - - try - { - if (ExecuteNonQuery(cmd, m_Connection) < 1) - { - //CloseCommand(cmd); - return false; - } - } - catch (Exception e) - { - Console.WriteLine(e.ToString()); - //CloseCommand(cmd); - return false; - } - } - - //CloseCommand(cmd); - - return true; - } - - public bool SetDataItem(UUID principalID, string item, string value) - { - SqliteCommand cmd = new SqliteCommand("update `" + m_Realm + - "` set `" + item + "` = " + value + " where UUID = '" + principalID.ToString() + "'"); - - if (ExecuteNonQuery(cmd, m_Connection) > 0) - return true; - - return false; - } - - public bool SetToken(UUID principalID, string token, int lifetime) - { - if (System.Environment.TickCount - m_LastExpire > 30000) - DoExpire(); - - SqliteCommand cmd = new SqliteCommand("insert into tokens (UUID, token, validity) values ('" + principalID.ToString() + - "', '" + token + "', datetime('now', 'localtime', '+" + lifetime.ToString() + " minutes'))"); - - if (ExecuteNonQuery(cmd, m_Connection) > 0) - { - cmd.Dispose(); - return true; - } - - cmd.Dispose(); - return false; - } - - public bool CheckToken(UUID principalID, string token, int lifetime) - { - if (System.Environment.TickCount - m_LastExpire > 30000) - DoExpire(); - - SqliteCommand cmd = new SqliteCommand("update tokens set validity = datetime('now', 'localtime', '+" + lifetime.ToString() + - " minutes') where UUID = '" + principalID.ToString() + "' and token = '" + token + "' and validity > datetime('now', 'localtime')"); - - if (ExecuteNonQuery(cmd, m_Connection) > 0) - { - cmd.Dispose(); - return true; - } - - cmd.Dispose(); - - return false; - } - - private void DoExpire() - { - SqliteCommand cmd = new SqliteCommand("delete from tokens where validity < datetime('now', 'localtime')"); - ExecuteNonQuery(cmd, m_Connection); - - cmd.Dispose(); - - m_LastExpire = System.Environment.TickCount; - } - } -} diff --git a/OpenSim/Data/SQLite/SQLiteEstateData.cs b/OpenSim/Data/SQLite/SQLiteEstateData.cs index ad4e2a2..643e55d 100644 --- a/OpenSim/Data/SQLite/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLite/SQLiteEstateData.cs @@ -180,7 +180,7 @@ namespace OpenSim.Data.SQLite // cmd.Parameters.Clear(); cmd.CommandText = "insert into estateban select "+es.EstateID.ToString()+", bannedUUID, bannedIp, bannedIpHostMask, '' from regionban where regionban.regionUUID = :UUID"; - cmd.Parameters.Add(":UUID", regionID.ToString()); + cmd.Parameters.AddWithValue(":UUID", regionID.ToString()); try { @@ -336,66 +336,5 @@ namespace OpenSim.Data.SQLite return uuids.ToArray(); } -<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteEstateData.cs -======= - - public EstateSettings LoadEstateSettings(int estateID) - { - string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID :EstateID"; - - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = sql; - cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); - - return DoLoad(cmd, UUID.Zero, false); - } - - public List GetEstates(string search) - { - List result = new List(); - - string sql = "select EstateID from estate_settings where estate_settings.EstateName :EstateName"; - - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = sql; - cmd.Parameters.AddWithValue(":EstateName", search); - - IDataReader r = cmd.ExecuteReader(); - - while (r.Read()) - { - result.Add(Convert.ToInt32(r["EstateID"])); - } - r.Close(); - - return result; - } - - public bool LinkRegion(UUID regionID, int estateID) - { - SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); - - cmd.CommandText = "insert into estate_map values (:RegionID, :EstateID)"; - cmd.Parameters.AddWithValue(":RegionID", regionID.ToString()); - cmd.Parameters.AddWithValue(":EstateID", estateID.ToString()); - - if (cmd.ExecuteNonQuery() == 0) - return false; - - return true; - } - - public List GetRegions(int estateID) - { - return new List(); - } - - public bool DeleteEstate(int estateID) - { - return false; - } ->>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteEstateData.cs } -} +} \ No newline at end of file diff --git a/OpenSim/Data/SQLite/SQLiteFramework.cs b/OpenSim/Data/SQLite/SQLiteFramework.cs index 79eaab3..9567727 100644 --- a/OpenSim/Data/SQLite/SQLiteFramework.cs +++ b/OpenSim/Data/SQLite/SQLiteFramework.cs @@ -57,19 +57,7 @@ namespace OpenSim.Data.SQLite { lock (m_Connection) { -<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteFramework.cs cmd.Connection = m_Connection; -======= -/* - SqliteConnection newConnection = - (SqliteConnection)((ICloneable)connection).Clone(); - newConnection.Open(); - - cmd.Connection = newConnection; -*/ - cmd.Connection = connection; - //Console.WriteLine("XXX " + cmd.CommandText); ->>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteFramework.cs return cmd.ExecuteNonQuery(); } @@ -77,27 +65,18 @@ namespace OpenSim.Data.SQLite protected IDataReader ExecuteReader(SqliteCommand cmd) { -<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteFramework.cs - SqliteConnection newConnection = - (SqliteConnection)((ICloneable)m_Connection).Clone(); - newConnection.Open(); - - cmd.Connection = newConnection; - return cmd.ExecuteReader(); -======= - lock (connection) + lock (m_Connection) { //SqliteConnection newConnection = // (SqliteConnection)((ICloneable)connection).Clone(); //newConnection.Open(); //cmd.Connection = newConnection; - cmd.Connection = connection; + cmd.Connection = m_Connection; //Console.WriteLine("XXX " + cmd.CommandText); return cmd.ExecuteReader(); } ->>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteFramework.cs } protected void CloseReaderCommand(SqliteCommand cmd) @@ -107,4 +86,4 @@ namespace OpenSim.Data.SQLite cmd.Dispose(); } } -} +} \ No newline at end of file diff --git a/OpenSim/Data/SQLite/SQLiteFriendsData.cs b/OpenSim/Data/SQLite/SQLiteFriendsData.cs deleted file mode 100644 index b06853c..0000000 --- a/OpenSim/Data/SQLite/SQLiteFriendsData.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.Sqlite; - -namespace OpenSim.Data.SQLite -{ - public class SQLiteFriendsData : SQLiteGenericTableHandler, IFriendsData - { - public SQLiteFriendsData(string connectionString, string realm) - : base(connectionString, realm, "FriendsStore") - { - } - - public FriendsData[] GetFriends(UUID userID) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = :PrincipalID", m_Realm); - cmd.Parameters.AddWithValue(":PrincipalID", userID.ToString()); - - return DoQuery(cmd); - - } - - public bool Delete(UUID principalID, string friend) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm); - cmd.Parameters.AddWithValue(":PrincipalID", principalID.ToString()); - cmd.Parameters.AddWithValue(":Friend", friend); - - ExecuteNonQuery(cmd, cmd.Connection); - - return true; - } - - } -} diff --git a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs index 918cb3d..86eaca1 100644 --- a/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs +++ b/OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs @@ -54,11 +54,8 @@ namespace OpenSim.Data.SQLite m_Realm = realm; if (storeName != String.Empty) { -<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs - Assembly assem = GetType().Assembly; -======= m_Connection = new SqliteConnection(connectionString); - Console.WriteLine(string.Format("OPENING CONNECTION FOR {0} USING {1}", storeName, connectionString)); + //Console.WriteLine(string.Format("OPENING CONNECTION FOR {0} USING {1}", storeName, connectionString)); m_Connection.Open(); if (storeName != String.Empty) @@ -74,10 +71,6 @@ namespace OpenSim.Data.SQLite //newConnection.Close(); //newConnection.Dispose(); } ->>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs - - Migration m = new Migration(m_Connection, assem, storeName); - m.Update(); } Type t = typeof(T); @@ -200,11 +193,7 @@ namespace OpenSim.Data.SQLite result.Add(row); } -<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs - CloseReaderCommand(cmd); -======= //CloseCommand(cmd); ->>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteGenericTableHandler.cs return result.ToArray(); } diff --git a/OpenSim/Data/SQLite/SQLiteInventoryStore.cs b/OpenSim/Data/SQLite/SQLiteInventoryStore.cs index 0149838..9ce21b1 100644 --- a/OpenSim/Data/SQLite/SQLiteInventoryStore.cs +++ b/OpenSim/Data/SQLite/SQLiteInventoryStore.cs @@ -88,30 +88,18 @@ namespace OpenSim.Data.SQLite invFoldersDa = new SqliteDataAdapter(foldersSelectCmd); ds = new DataSet(); - -<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteInventoryStore.cs + ds.Tables.Add(createInventoryFoldersTable()); invFoldersDa.Fill(ds.Tables["inventoryfolders"]); setupFoldersCommands(invFoldersDa, conn); + CreateDataSetMapping(invFoldersDa, "inventoryfolders"); m_log.Info("[INVENTORY DB]: Populated Inventory Folders Definitions"); ds.Tables.Add(createInventoryItemsTable()); invItemsDa.Fill(ds.Tables["inventoryitems"]); setupItemsCommands(invItemsDa, conn); + CreateDataSetMapping(invItemsDa, "inventoryitems"); m_log.Info("[INVENTORY DB]: Populated Inventory Items Definitions"); -======= - ds.Tables.Add(createInventoryFoldersTable()); - invFoldersDa.Fill(ds.Tables["inventoryfolders"]); - setupFoldersCommands(invFoldersDa, conn); - CreateDataSetMapping(invFoldersDa, "inventoryfolders"); - m_log.Info("[INVENTORY DB]: Populated Inventory Folders Definitions"); - - ds.Tables.Add(createInventoryItemsTable()); - invItemsDa.Fill(ds.Tables["inventoryitems"]); - setupItemsCommands(invItemsDa, conn); - CreateDataSetMapping(invItemsDa, "inventoryitems"); - m_log.Info("[INVENTORY DB]: Populated Inventory Items Definitions"); ->>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteInventoryStore.cs ds.AcceptChanges(); } diff --git a/OpenSim/Data/SQLite/SQLiteManager.cs b/OpenSim/Data/SQLite/SQLiteManager.cs index b6d4a1c..7dcd323 100644 --- a/OpenSim/Data/SQLite/SQLiteManager.cs +++ b/OpenSim/Data/SQLite/SQLiteManager.cs @@ -28,9 +28,9 @@ using System; using System.Collections.Generic; using System.Data; -using System.Data.SQLite; using System.Reflection; using log4net; +using Mono.Data.Sqlite; using OpenMetaverse; namespace OpenSim.Data.SQLite @@ -66,7 +66,7 @@ namespace OpenSim.Data.SQLite connectionString = "URI=file:GridServerSqlite.db;"; } - dbcon = new SQLiteConnection(connectionString); + dbcon = new SqliteConnection(connectionString); dbcon.Open(); } @@ -93,11 +93,11 @@ namespace OpenSim.Data.SQLite /// A SQLite DB Command public IDbCommand Query(string sql, Dictionary parameters) { - SQLiteCommand dbcommand = (SQLiteCommand) dbcon.CreateCommand(); + SqliteCommand dbcommand = (SqliteCommand) dbcon.CreateCommand(); dbcommand.CommandText = sql; foreach (KeyValuePair param in parameters) { - SQLiteParameter paramx = new SQLiteParameter(param.Key, param.Value); + SqliteParameter paramx = new SqliteParameter(param.Key, param.Value); dbcommand.Parameters.Add(paramx); } diff --git a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs b/OpenSim/Data/SQLite/SQLiteUserAccountData.cs deleted file mode 100644 index 893f105..0000000 --- a/OpenSim/Data/SQLite/SQLiteUserAccountData.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.Sqlite; - -namespace OpenSim.Data.SQLite -{ - public class SQLiteUserAccountData : SQLiteGenericTableHandler, IUserAccountData - { - public SQLiteUserAccountData(string connectionString, string realm) - : base(connectionString, realm, "UserAccount") - { - } - - public UserAccountData[] GetUsers(UUID scopeID, string query) - { - string[] words = query.Split(new char[] {' '}); - - for (int i = 0 ; i < words.Length ; i++) - { - if (words[i].Length < 3) - { - if (i != words.Length - 1) - Array.Copy(words, i + 1, words, i, words.Length - i - 1); - Array.Resize(ref words, words.Length - 1); - } - } - - if (words.Length == 0) - return new UserAccountData[0]; - - if (words.Length > 2) - return new UserAccountData[0]; - - SqliteCommand cmd = new SqliteCommand(); - - if (words.Length == 1) - { - cmd.CommandText = String.Format("select * from {0} where ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", - m_Realm, scopeID.ToString(), words[0]); - } - else - { - cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{3}%')", - m_Realm, scopeID.ToString(), words[0], words[1]); - } - - return DoQuery(cmd); - } - } -} diff --git a/OpenSim/Data/SQLite/SQLiteUserData.cs b/OpenSim/Data/SQLite/SQLiteUserData.cs index caddcf8..12db403 100644 --- a/OpenSim/Data/SQLite/SQLiteUserData.cs +++ b/OpenSim/Data/SQLite/SQLiteUserData.cs @@ -30,7 +30,7 @@ using System.Collections.Generic; using System.Data; using System.Reflection; using log4net; -using Mono.Data.SqliteClient; +using Mono.Data.Sqlite; using OpenMetaverse; using OpenSim.Framework; diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs index 0650a86..0d211b6 100644 --- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs @@ -147,12 +147,8 @@ namespace OpenSim.Data.SQLite } reader.Close(); -<<<<<<< HEAD:OpenSim/Data/SQLite/SQLiteXInventoryData.cs - CloseReaderCommand(cmd); -======= + //CloseCommand(cmd); ->>>>>>> cc67de5... rename SQLiteNG to SQLite and SQLite to SQLiteLegacy:OpenSim/Data/SQLite/SQLiteXInventoryData.cs - return perms; } } diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs index 0d63dea..23cdfd4 100644 --- a/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs @@ -234,8 +234,7 @@ namespace OpenSim.Data.SQLiteLegacy AssetBase asset = new AssetBase( new UUID((String)row["UUID"]), (String)row["Name"], - Convert.ToSByte(row["Type"]), - UUID.Zero.ToString() + Convert.ToSByte(row["Type"]) ); asset.Description = (String) row["Description"]; diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs deleted file mode 100644 index 660632c..0000000 --- a/OpenSim/Data/SQLiteLegacy/SQLiteAvatarData.cs +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Data; -using System.Reflection; -using System.Threading; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.SqliteClient; - -namespace OpenSim.Data.SQLiteLegacy -{ - /// - /// A SQLite Interface for Avatar Data - /// - public class SQLiteAvatarData : SQLiteGenericTableHandler, - IAvatarData - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public SQLiteAvatarData(string connectionString, string realm) : - base(connectionString, realm, "Avatar") - { - } - - public bool Delete(UUID principalID, string name) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("delete from {0} where `PrincipalID` = :PrincipalID and `Name` = :Name", m_Realm); - cmd.Parameters.Add(":PrincipalID", principalID.ToString()); - cmd.Parameters.Add(":Name", name); - - try - { - if (ExecuteNonQuery(cmd, m_Connection) > 0) - return true; - - return false; - } - finally - { - CloseCommand(cmd); - } - } - } -} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs index e135eaa..5a7fbd7 100644 --- a/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs @@ -80,7 +80,7 @@ namespace OpenSim.Data.SQLiteLegacy get { return new List(m_FieldMap.Keys).ToArray(); } } - public EstateSettings LoadEstateSettings(UUID regionID, bool create) + public EstateSettings LoadEstateSettings(UUID regionID) { string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_map left join estate_settings on estate_map.EstateID = estate_settings.EstateID where estate_settings.EstateID is not null and RegionID = :RegionID"; @@ -89,10 +89,10 @@ namespace OpenSim.Data.SQLiteLegacy cmd.CommandText = sql; cmd.Parameters.Add(":RegionID", regionID.ToString()); - return DoLoad(cmd, regionID, create); + return DoLoad(cmd, regionID); } - private EstateSettings DoLoad(SqliteCommand cmd, UUID regionID, bool create) + private EstateSettings DoLoad(SqliteCommand cmd, UUID regionID) { EstateSettings es = new EstateSettings(); es.OnSave += StoreEstateSettings; @@ -125,8 +125,10 @@ namespace OpenSim.Data.SQLiteLegacy } r.Close(); } - else if (create) + else { + // Migration case + // r.Close(); List names = new List(FieldList); @@ -335,7 +337,7 @@ namespace OpenSim.Data.SQLiteLegacy cmd.CommandText = sql; cmd.Parameters.Add(":EstateID", estateID.ToString()); - return DoLoad(cmd, UUID.Zero, false); + return DoLoad(cmd, UUID.Zero); } public List GetEstates(string search) diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs deleted file mode 100644 index d529d4d..0000000 --- a/OpenSim/Data/SQLiteLegacy/SQLiteFriendsData.cs +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.SqliteClient; - -namespace OpenSim.Data.SQLiteLegacy -{ - public class SQLiteFriendsData : SQLiteGenericTableHandler, IFriendsData - { - public SQLiteFriendsData(string connectionString, string realm) - : base(connectionString, realm, "FriendsStore") - { - } - - public FriendsData[] GetFriends(UUID userID) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("select a.*,case when b.Flags is null then -1 else b.Flags end as TheirFlags from {0} as a left join {0} as b on a.PrincipalID = b.Friend and a.Friend = b.PrincipalID where a.PrincipalID = :PrincipalID", m_Realm); - cmd.Parameters.Add(":PrincipalID", userID.ToString()); - - return DoQuery(cmd); - - } - - public bool Delete(UUID principalID, string friend) - { - SqliteCommand cmd = new SqliteCommand(); - - cmd.CommandText = String.Format("delete from {0} where PrincipalID = :PrincipalID and Friend = :Friend", m_Realm); - cmd.Parameters.Add(":PrincipalID", principalID.ToString()); - cmd.Parameters.Add(":Friend", friend); - - ExecuteNonQuery(cmd, cmd.Connection); - - return true; - } - - } -} diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs index eb78037..f8660c7 100644 --- a/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs @@ -272,16 +272,7 @@ namespace OpenSim.Data.SQLiteLegacy Commit(); } } - public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) - { - //This connector doesn't support the windlight module yet - //Return default LL windlight settings - return new RegionLightShareData(); - } - public void StoreRegionWindlightSettings(RegionLightShareData wl) - { - //This connector doesn't support the windlight module yet - } + public RegionSettings LoadRegionSettings(UUID regionUUID) { lock (ds) diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs deleted file mode 100644 index 27553c6..0000000 --- a/OpenSim/Data/SQLiteLegacy/SQLiteUserAccountData.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Data; -using OpenMetaverse; -using OpenSim.Framework; -using Mono.Data.SqliteClient; - -namespace OpenSim.Data.SQLiteLegacy -{ - public class SQLiteUserAccountData : SQLiteGenericTableHandler, IUserAccountData - { - public SQLiteUserAccountData(string connectionString, string realm) - : base(connectionString, realm, "UserAccount") - { - } - - public UserAccountData[] GetUsers(UUID scopeID, string query) - { - string[] words = query.Split(new char[] {' '}); - - for (int i = 0 ; i < words.Length ; i++) - { - if (words[i].Length < 3) - { - if (i != words.Length - 1) - Array.Copy(words, i + 1, words, i, words.Length - i - 1); - Array.Resize(ref words, words.Length - 1); - } - } - - if (words.Length == 0) - return new UserAccountData[0]; - - if (words.Length > 2) - return new UserAccountData[0]; - - SqliteCommand cmd = new SqliteCommand(); - - if (words.Length == 1) - { - cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{2}%')", - m_Realm, scopeID.ToString(), words[0]); - } - else - { - cmd.CommandText = String.Format("select * from {0} where (ScopeID='{1}' or ScopeID='00000000-0000-0000-0000-000000000000') and (FirstName like '{2}%' or LastName like '{3}%')", - m_Realm, scopeID.ToString(), words[0], words[1]); - } - - return DoQuery(cmd); - } - } -} -- cgit v1.1 From 3e30de7430bff6f2eede395140e45207a15c23a5 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 30 Apr 2010 22:35:07 +0200 Subject: Fix linking issue introduced in my earlier commit --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 90bce39..cfcd544 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1970,8 +1970,17 @@ namespace OpenSim.Region.Framework.Scenes List children = new List(); SceneObjectPart root = GetSceneObjectPart(parentPrimId); - if (Permissions.CanLinkObject(client.AgentId, root.ParentGroup.RootPart.UUID)) + if (root == null) + { + m_log.DebugFormat("[LINK]: Can't find linkset root prim {0{", parentPrimId); + return; + } + + if (!Permissions.CanLinkObject(client.AgentId, root.ParentGroup.RootPart.UUID)) + { + m_log.DebugFormat("[LINK]: Refusing link. No permissions on root prim"); return; + } foreach (uint localID in childPrimIds) { @@ -1990,7 +1999,16 @@ namespace OpenSim.Region.Framework.Scenes // Must be all one owner // if (owners.Count > 1) + { + m_log.DebugFormat("[LINK]: Refusing link. Too many owners"); + return; + } + + if (children.Count == 0) + { + m_log.DebugFormat("[LINK]: Refusing link. No permissions to link any of the children"); return; + } m_sceneGraph.LinkObjects(root, children); } -- cgit v1.1 From 0a9c98e7c472f93986f2eedcfaff0d05c8686cee Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 30 Apr 2010 22:35:07 +0200 Subject: Fix linking issue introduced in my earlier commit --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 8716e0a..4f2b446 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2594,8 +2594,17 @@ namespace OpenSim.Region.Framework.Scenes List children = new List(); SceneObjectPart root = GetSceneObjectPart(parentPrimId); - if (Permissions.CanLinkObject(client.AgentId, root.ParentGroup.RootPart.UUID)) + if (root == null) + { + m_log.DebugFormat("[LINK]: Can't find linkset root prim {0{", parentPrimId); + return; + } + + if (!Permissions.CanLinkObject(client.AgentId, root.ParentGroup.RootPart.UUID)) + { + m_log.DebugFormat("[LINK]: Refusing link. No permissions on root prim"); return; + } foreach (uint localID in childPrimIds) { @@ -2614,7 +2623,16 @@ namespace OpenSim.Region.Framework.Scenes // Must be all one owner // if (owners.Count > 1) + { + m_log.DebugFormat("[LINK]: Refusing link. Too many owners"); + return; + } + + if (children.Count == 0) + { + m_log.DebugFormat("[LINK]: Refusing link. No permissions to link any of the children"); return; + } m_sceneGraph.LinkObjects(root, children); } -- cgit v1.1 From 7ae55f624883b711e5a9d4d5f040ba884fc8bd5e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 30 Apr 2010 22:35:07 +0200 Subject: Fix linking issue introduced in my earlier commit --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index a430bc4..e031ebc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2603,8 +2603,17 @@ namespace OpenSim.Region.Framework.Scenes List children = new List(); SceneObjectPart root = GetSceneObjectPart(parentPrimId); - if (Permissions.CanLinkObject(client.AgentId, root.ParentGroup.RootPart.UUID)) + if (root == null) + { + m_log.DebugFormat("[LINK]: Can't find linkset root prim {0{", parentPrimId); + return; + } + + if (!Permissions.CanLinkObject(client.AgentId, root.ParentGroup.RootPart.UUID)) + { + m_log.DebugFormat("[LINK]: Refusing link. No permissions on root prim"); return; + } foreach (uint localID in childPrimIds) { @@ -2623,7 +2632,16 @@ namespace OpenSim.Region.Framework.Scenes // Must be all one owner // if (owners.Count > 1) + { + m_log.DebugFormat("[LINK]: Refusing link. Too many owners"); + return; + } + + if (children.Count == 0) + { + m_log.DebugFormat("[LINK]: Refusing link. No permissions to link any of the children"); return; + } m_sceneGraph.LinkObjects(root, children); } -- cgit v1.1 From 8966ed9c82c8199bf0da61815d04d485d67aa34a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 30 Apr 2010 21:37:31 +0100 Subject: fix an issue with user appearance where the new sqlite db adapter expects directly specification of byte[] type rather than base64 strings --- OpenSim/Data/SQLite/SQLiteUserData.cs | 37 +++++++++++++++------- .../Data/SQLiteLegacy/Resources/001_AuthStore.sql | 18 ----------- OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql | 9 ------ .../SQLiteLegacy/Resources/001_FriendsStore.sql | 10 ------ .../SQLiteLegacy/Resources/001_UserAccount.sql | 17 ---------- .../Data/SQLiteLegacy/Resources/002_AuthStore.sql | 5 --- .../SQLiteLegacy/Resources/002_FriendsStore.sql | 5 --- .../SQLiteLegacy/Resources/002_UserAccount.sql | 5 --- 8 files changed, 25 insertions(+), 81 deletions(-) delete mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_AuthStore.sql delete mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql delete mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_FriendsStore.sql delete mode 100644 OpenSim/Data/SQLiteLegacy/Resources/001_UserAccount.sql delete mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_AuthStore.sql delete mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_FriendsStore.sql delete mode 100644 OpenSim/Data/SQLiteLegacy/Resources/002_UserAccount.sql diff --git a/OpenSim/Data/SQLite/SQLiteUserData.cs b/OpenSim/Data/SQLite/SQLiteUserData.cs index 12db403..bffc0d0 100644 --- a/OpenSim/Data/SQLite/SQLiteUserData.cs +++ b/OpenSim/Data/SQLite/SQLiteUserData.cs @@ -108,22 +108,32 @@ namespace OpenSim.Data.SQLite lock (ds) { + Console.WriteLine("Here1"); ds.Tables.Add(createUsersTable()); ds.Tables.Add(createUserAgentsTable()); ds.Tables.Add(createUserFriendsTable()); ds.Tables.Add(createAvatarAppearanceTable()); + Console.WriteLine("Here2"); setupUserCommands(da, conn); da.Fill(ds.Tables["users"]); + CreateDataSetMapping(da, "users"); + Console.WriteLine("Here3"); setupAgentCommands(dua, conn); dua.Fill(ds.Tables["useragents"]); + CreateDataSetMapping(dua, "useragents"); + Console.WriteLine("Here4"); setupUserFriendsCommands(daf, conn); daf.Fill(ds.Tables["userfriends"]); + CreateDataSetMapping(daf, "userfriends"); + Console.WriteLine("Here5"); setupAvatarAppearanceCommands(daa, conn); daa.Fill(ds.Tables["avatarappearance"]); + CreateDataSetMapping(daa, "avatarappearance"); + Console.WriteLine("Here6"); } return; @@ -706,15 +716,10 @@ namespace OpenSim.Data.SQLite aa.SkirtItem = new UUID((String)row["SkirtItem"]); aa.SkirtAsset = new UUID((String)row["SkirtAsset"]); - // Ewe Loon - // Used Base64String because for some reason it wont accept using Byte[] (which works in Region date) - - String str = (String)row["Texture"]; - byte[] texture = Convert.FromBase64String(str); + byte[] texture = (byte[])row["Texture"]; aa.Texture = new Primitive.TextureEntry(texture, 0, texture.Length); - str = (String)row["VisualParams"]; - byte[] VisualParams = Convert.FromBase64String(str); + byte[] VisualParams = (byte[])row["VisualParams"]; aa.VisualParams = VisualParams; aa.Serial = Convert.ToInt32(row["Serial"]); @@ -793,6 +798,15 @@ namespace OpenSim.Data.SQLite * **********************************************************************/ + protected void CreateDataSetMapping(IDataAdapter da, string tableName) + { + ITableMapping dbMapping = da.TableMappings.Add(tableName, tableName); + foreach (DataColumn col in ds.Tables[tableName].Columns) + { + dbMapping.ColumnMappings.Add(col.ColumnName, col.ColumnName); + } + } + /// /// Create the "users" table /// @@ -924,9 +938,8 @@ namespace OpenSim.Data.SQLite SQLiteUtil.createCol(aa, "SkirtItem", typeof(String)); SQLiteUtil.createCol(aa, "SkirtAsset", typeof(String)); - // Used Base64String because for some reason it wont accept using Byte[] (which works in Region date) - SQLiteUtil.createCol(aa, "Texture", typeof (String)); - SQLiteUtil.createCol(aa, "VisualParams", typeof (String)); + SQLiteUtil.createCol(aa, "Texture", typeof (Byte[])); + SQLiteUtil.createCol(aa, "VisualParams", typeof (Byte[])); SQLiteUtil.createCol(aa, "Serial", typeof(Int32)); SQLiteUtil.createCol(aa, "AvatarHeight", typeof(Double)); @@ -1090,8 +1103,8 @@ namespace OpenSim.Data.SQLite row["SkirtAsset"] = appearance.SkirtAsset.ToString(); // Used Base64String because for some reason it wont accept using Byte[] (which works in Region date) - row["Texture"] = Convert.ToBase64String(appearance.Texture.GetBytes()); - row["VisualParams"] = Convert.ToBase64String(appearance.VisualParams); + row["Texture"] = appearance.Texture.GetBytes(); + row["VisualParams"] = appearance.VisualParams; row["Serial"] = appearance.Serial; row["AvatarHeight"] = appearance.AvatarHeight; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_AuthStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_AuthStore.sql deleted file mode 100644 index 468567d..0000000 --- a/OpenSim/Data/SQLiteLegacy/Resources/001_AuthStore.sql +++ /dev/null @@ -1,18 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE auth ( - UUID char(36) NOT NULL, - passwordHash char(32) NOT NULL default '', - passwordSalt char(32) NOT NULL default '', - webLoginKey varchar(255) NOT NULL default '', - accountType VARCHAR(32) NOT NULL DEFAULT 'UserAccount', - PRIMARY KEY (`UUID`) -); - -CREATE TABLE tokens ( - UUID char(36) NOT NULL, - token varchar(255) NOT NULL, - validity datetime NOT NULL -); - -COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql deleted file mode 100644 index 7ec906b..0000000 --- a/OpenSim/Data/SQLiteLegacy/Resources/001_Avatar.sql +++ /dev/null @@ -1,9 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE Avatars ( - PrincipalID CHAR(36) NOT NULL, - Name VARCHAR(32) NOT NULL, - Value VARCHAR(255) NOT NULL DEFAULT '', - PRIMARY KEY(PrincipalID, Name)); - -COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_FriendsStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_FriendsStore.sql deleted file mode 100644 index f1b9ab9..0000000 --- a/OpenSim/Data/SQLiteLegacy/Resources/001_FriendsStore.sql +++ /dev/null @@ -1,10 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE `Friends` ( - `PrincipalID` CHAR(36) NOT NULL, - `Friend` VARCHAR(255) NOT NULL, - `Flags` VARCHAR(16) NOT NULL DEFAULT 0, - `Offered` VARCHAR(32) NOT NULL DEFAULT 0, - PRIMARY KEY(`PrincipalID`, `Friend`)); - -COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/001_UserAccount.sql b/OpenSim/Data/SQLiteLegacy/Resources/001_UserAccount.sql deleted file mode 100644 index c38d9a7..0000000 --- a/OpenSim/Data/SQLiteLegacy/Resources/001_UserAccount.sql +++ /dev/null @@ -1,17 +0,0 @@ -BEGIN TRANSACTION; - --- useraccounts table -CREATE TABLE UserAccounts ( - PrincipalID CHAR(36) primary key, - ScopeID CHAR(36) NOT NULL, - FirstName VARCHAR(64) NOT NULL, - LastName VARCHAR(64) NOT NULL, - Email VARCHAR(64), - ServiceURLs TEXT, - Created INT(11), - UserLevel integer NOT NULL DEFAULT 0, - UserFlags integer NOT NULL DEFAULT 0, - UserTitle varchar(64) NOT NULL DEFAULT '' -); - -COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_AuthStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_AuthStore.sql deleted file mode 100644 index 3237b68..0000000 --- a/OpenSim/Data/SQLiteLegacy/Resources/002_AuthStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN TRANSACTION; - -INSERT INTO auth (UUID, passwordHash, passwordSalt, webLoginKey) SELECT `UUID` AS UUID, `passwordHash` AS passwordHash, `passwordSalt` AS passwordSalt, `webLoginKey` AS webLoginKey FROM users; - -COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_FriendsStore.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_FriendsStore.sql deleted file mode 100644 index 6733502..0000000 --- a/OpenSim/Data/SQLiteLegacy/Resources/002_FriendsStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN TRANSACTION; - -INSERT INTO `Friends` SELECT `ownerID`, `friendID`, `friendPerms`, 0 FROM `userfriends`; - -COMMIT; diff --git a/OpenSim/Data/SQLiteLegacy/Resources/002_UserAccount.sql b/OpenSim/Data/SQLiteLegacy/Resources/002_UserAccount.sql deleted file mode 100644 index c7a6293..0000000 --- a/OpenSim/Data/SQLiteLegacy/Resources/002_UserAccount.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN TRANSACTION; - -INSERT INTO UserAccounts (PrincipalID, ScopeID, FirstName, LastName, Email, ServiceURLs, Created) SELECT `UUID` AS PrincipalID, '00000000-0000-0000-0000-000000000000' AS ScopeID, username AS FirstName, surname AS LastName, '' as Email, '' AS ServiceURLs, created as Created FROM users; - -COMMIT; -- cgit v1.1 From 139f425f4cf4c720681a10e9cd5399fe0ed3b86c Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 30 Apr 2010 22:08:57 +0100 Subject: take out some more sqlite db console debug lines --- OpenSim/Data/SQLite/SQLiteUserData.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/OpenSim/Data/SQLite/SQLiteUserData.cs b/OpenSim/Data/SQLite/SQLiteUserData.cs index bffc0d0..ea755b0 100644 --- a/OpenSim/Data/SQLite/SQLiteUserData.cs +++ b/OpenSim/Data/SQLite/SQLiteUserData.cs @@ -108,32 +108,26 @@ namespace OpenSim.Data.SQLite lock (ds) { - Console.WriteLine("Here1"); ds.Tables.Add(createUsersTable()); ds.Tables.Add(createUserAgentsTable()); ds.Tables.Add(createUserFriendsTable()); ds.Tables.Add(createAvatarAppearanceTable()); - Console.WriteLine("Here2"); setupUserCommands(da, conn); da.Fill(ds.Tables["users"]); CreateDataSetMapping(da, "users"); - Console.WriteLine("Here3"); setupAgentCommands(dua, conn); dua.Fill(ds.Tables["useragents"]); CreateDataSetMapping(dua, "useragents"); - Console.WriteLine("Here4"); setupUserFriendsCommands(daf, conn); daf.Fill(ds.Tables["userfriends"]); CreateDataSetMapping(daf, "userfriends"); - Console.WriteLine("Here5"); setupAvatarAppearanceCommands(daa, conn); daa.Fill(ds.Tables["avatarappearance"]); CreateDataSetMapping(daa, "avatarappearance"); - Console.WriteLine("Here6"); } return; -- cgit v1.1 From 881fcb7def0ef1ff81c6de10137abcdca8bc7679 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 30 Apr 2010 23:32:58 +0200 Subject: Allow retrieval if admin users in scope mode --- .../Services/UserAccountService/UserAccountService.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index 7b38aa6..35e2826 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -104,6 +104,12 @@ namespace OpenSim.Services.UserAccountService d = m_Database.Get( new string[] { "ScopeID", "FirstName", "LastName" }, new string[] { scopeID.ToString(), firstName, lastName }); + if (d.Length < 1) + { + d = m_Database.Get( + new string[] { "ScopeID", "FirstName", "LastName" }, + new string[] { UUID.Zero.ToString(), firstName, lastName }); + } } else { @@ -172,6 +178,12 @@ namespace OpenSim.Services.UserAccountService d = m_Database.Get( new string[] { "ScopeID", "Email" }, new string[] { scopeID.ToString(), email }); + if (d.Length < 1) + { + d = m_Database.Get( + new string[] { "ScopeID", "Email" }, + new string[] { UUID.Zero.ToString(), email }); + } } else { @@ -195,6 +207,12 @@ namespace OpenSim.Services.UserAccountService d = m_Database.Get( new string[] { "ScopeID", "PrincipalID" }, new string[] { scopeID.ToString(), principalID.ToString() }); + if (d.Length < 1) + { + d = m_Database.Get( + new string[] { "ScopeID", "PrincipalID" }, + new string[] { UUID.Zero.ToString(), principalID.ToString() }); + } } else { -- cgit v1.1 From 8938fac4fdd5ca949da8415f681b54872f330e57 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 30 Apr 2010 22:36:26 +0100 Subject: add operation to "nant distbin" to copy StandaloneCommon.ini.example -> StandaloneCommon.ini --- .nant/local.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nant/local.include b/.nant/local.include index 1e8bedc..f71e5d8 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -7,8 +7,8 @@ + - -- cgit v1.1 From 7ad36d3d75bf50a02b4947a63fa03bedf9f196e6 Mon Sep 17 00:00:00 2001 From: sacha Date: Sun, 2 May 2010 08:15:12 -0400 Subject: Adding DebugEvent Trap Adding XMREEvent Trap trapDebug("Modulename" ,"My data here ", scene); trapXMRE(int data, string Message, Scene scene); --- OpenSim/Region/Framework/Interfaces/ISnmpModule.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs index 16a243c..e01f649 100644 --- a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -21,4 +21,7 @@ public interface ISnmpModule void LinkUp(Scene scene); void LinkDown(Scene scene); void BootInfo(string data, Scene scene); + void trapDebug(string Module,string data, Scene scene); + void trapXMRE(int data, string Message, Scene scene); + } -- cgit v1.1 From 0fa57cac3fc05988bf182920c82fbeee0be075cf Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 3 May 2010 00:54:24 +0200 Subject: Fix sensor cone for sensing avatars --- .../Shared/Api/Implementation/Plugins/SensorRepeat.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 4d7ead6..5e2e205 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -204,7 +204,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins // Is the sensor type is AGENT and not SCRIPTED then include agents if ((ts.type & AGENT) != 0 && (ts.type & SCRIPTED) == 0) { - sensedEntities.AddRange(doAgentSensor(ts)); + sensedEntities.AddRange(doAgentSensor(ts)); } // If SCRIPTED or PASSIVE or ACTIVE check objects @@ -309,6 +309,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins // in mouselook. ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); + fromRegionPos = avatar.AbsolutePosition; q = avatar.Rotation; } LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); @@ -422,6 +423,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins SceneObjectPart SensePoint = ts.host; Vector3 fromRegionPos = SensePoint.AbsolutePosition; Quaternion q = SensePoint.RotationOffset; + if (SensePoint.ParentGroup.RootPart.IsAttachment) + { + // In attachments, the sensor cone always orients with the + // avatar rotation. This may include a nonzero elevation if + // in mouselook. + + ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.RootPart.AttachedAvatar); + fromRegionPos = avatar.AbsolutePosition; + q = avatar.Rotation; + } LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); -- cgit v1.1 From 175f3f992ab487add20253329bef481a4d20f8aa Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 3 May 2010 01:50:32 +0200 Subject: Make the IUserAccountData properly unpack the god mode data, so grid gods work again --- .../Services/Connectors/UserAccounts/UserAccountServiceConnector.cs | 2 +- OpenSim/Services/Interfaces/IUserAccountService.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs index 1527db2..38c191a 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs @@ -113,7 +113,7 @@ namespace OpenSim.Services.Connectors public virtual UserAccount GetUserAccount(UUID scopeID, UUID userID) { - m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetUSerAccount {0}", userID); + m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetUserAccount {0}", userID); Dictionary sendData = new Dictionary(); //sendData["SCOPEID"] = scopeID.ToString(); sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs index befd14e..e316731 100644 --- a/OpenSim/Services/Interfaces/IUserAccountService.cs +++ b/OpenSim/Services/Interfaces/IUserAccountService.cs @@ -84,11 +84,11 @@ namespace OpenSim.Services.Interfaces if (kvp.ContainsKey("ScopeID")) UUID.TryParse(kvp["ScopeID"].ToString(), out ScopeID); if (kvp.ContainsKey("UserLevel")) - Convert.ToInt32(kvp["UserLevel"].ToString()); + UserLevel = Convert.ToInt32(kvp["UserLevel"].ToString()); if (kvp.ContainsKey("UserFlags")) - Convert.ToInt32(kvp["UserFlags"].ToString()); + UserFlags = Convert.ToInt32(kvp["UserFlags"].ToString()); if (kvp.ContainsKey("UserTitle")) - Email = kvp["UserTitle"].ToString(); + UserTitle = kvp["UserTitle"].ToString(); if (kvp.ContainsKey("Created")) Convert.ToInt32(kvp["Created"].ToString()); -- cgit v1.1 From 87664017773227d07b39382efa2aa94f22bbe6c6 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 3 May 2010 04:28:30 +0200 Subject: Adapt CM to the new CHANGED_OWNER handling --- .../CoreModules/Avatar/Attachments/AttachmentsModule.cs | 3 +++ OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 8 ++++++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 12 ++++++++++++ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 17 +++++++++++++---- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 1992bd4..4fac01f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -245,7 +245,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments objatt.HasGroupChanged = true; if (doc != null) + { objatt.LoadScriptState(doc); + objatt.ResetOwnerChangeFlag(); + } // Fire after attach, so we don't get messy perms dialogs // 3 == AttachedRez diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 1c6f2d1..ff471e0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3931,5 +3931,13 @@ namespace OpenSim.Region.Framework.Scenes return priority; } + + public void ResetOwnerChangeFlag() + { + ForEachPart(delegate(SceneObjectPart part) + { + part.ResetOwnerChangeFlag(); + }); + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 4b2641c..48e65a5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4683,5 +4683,17 @@ namespace OpenSim.Region.Framework.Scenes { return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A)); } + + public void ResetOwnerChangeFlag() + { + List inv = Inventory.GetInventoryList(); + + foreach (UUID itemID in inv) + { + TaskInventoryItem item = Inventory.GetInventoryItem(itemID); + item.OwnerChanged = false; + Inventory.UpdateInventoryItem(item); + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index ceb4395..562232c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -4011,15 +4011,24 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); { string xmlData; XmlDocument d = new XmlDocument(); + UUID asset; if (itemData.TryGetValue(itemID, out xmlData)) { d.LoadXml(xmlData); m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID); - } - // Rez from inventory - UUID asset - = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d); + // Rez from inventory + asset + = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d); + + } + else + { + // Rez from inventory (with a null doc to let + // CHANGED_OWNER happen) + asset + = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null); + } m_log.InfoFormat( "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", -- cgit v1.1 From 9c8d7d34b39c6351459989f02473b6f5200d14ee Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 3 May 2010 04:55:41 +0200 Subject: Fix a bug in owner change notification --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 64282d1..62b44bd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -1180,7 +1180,9 @@ namespace OpenSim.Region.Framework.Scenes { if (engine != null) { - engine.PostScriptEvent(item.ItemID, "changed", new Object[] { Changed.OWNER }); + if (item.OwnerChanged) + engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); + item.OwnerChanged = false; engine.ResumeScript(item.ItemID); } } -- cgit v1.1 From a69cb5e3901eb9aa7ebfa65a5787e023136a2b19 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 3 May 2010 21:34:38 +0100 Subject: Address symptom of Mantis 4588 (though not the cause) by moving the avatar dereference inside the exception catch --- OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs index 1a6cd6c..4bcfaac 100644 --- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs @@ -146,10 +146,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule } private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) - { - ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + { try { + ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) { avatar.Invulnerable = false; -- cgit v1.1 From 4df87631ede57316fe41ea6c5edcd4996deac625 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 3 May 2010 23:44:23 +0200 Subject: Store given items in correct parent folder. Fixes items given to offline avatars not getting lost. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index cfcd544..9b838ab 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -414,6 +414,25 @@ namespace OpenSim.Region.Framework.Scenes itemCopy.BasePermissions = item.BasePermissions; } + if (itemCopy.Folder == UUID.Zero) + { + InventoryFolderBase folder = InventoryService.GetFolderForType(recipient, (AssetType)itemCopy.AssetType); + + if (folder != null) + { + itemCopy.Folder = folder.ID; + } + else + { + InventoryFolderBase root = InventoryService.GetRootFolder(recipient); + + if (root != null) + itemCopy.Folder = root.ID; + else + return null; // No destination + } + } + itemCopy.GroupID = UUID.Zero; itemCopy.GroupOwned = false; itemCopy.Flags = item.Flags; -- cgit v1.1 From 8ec6e42e34c8ef72474852085c4d5531a6d5ac93 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 3 May 2010 23:45:05 +0200 Subject: Add folder version uncrementing to XInventoryService. Fixes offline give for avatar->avatar --- OpenSim/Data/MySQL/MySQLXInventoryData.cs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index 307a4c7..a3b728b 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -160,5 +160,36 @@ namespace OpenSim.Data.MySQL } } } + + public override bool Store(XInventoryItem item) + { + if (base.Store(item)) + return false; + + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = new MySqlCommand()) + { + cmd.Connection = dbcon; + + cmd.CommandText = String.Format("update inventoryfolders set version=version+1 where folderID = ?folderID"); + cmd.Parameters.AddWithValue("?folderID", item.parentFolderID.ToString()); + + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + return false; + } + cmd.Dispose(); + } + dbcon.Close(); + } + return true; + } } } -- cgit v1.1 From 80bf3934af8a5cbeb4ab29f93c7b2a83c80f1de7 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 3 May 2010 23:45:05 +0200 Subject: Add folder version incrementing to XInventoryService. Fixes offline give for avatar->avatar --- OpenSim/Data/MySQL/MySQLXInventoryData.cs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index 307a4c7..a3b728b 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -160,5 +160,36 @@ namespace OpenSim.Data.MySQL } } } + + public override bool Store(XInventoryItem item) + { + if (base.Store(item)) + return false; + + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = new MySqlCommand()) + { + cmd.Connection = dbcon; + + cmd.CommandText = String.Format("update inventoryfolders set version=version+1 where folderID = ?folderID"); + cmd.Parameters.AddWithValue("?folderID", item.parentFolderID.ToString()); + + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + return false; + } + cmd.Dispose(); + } + dbcon.Close(); + } + return true; + } } } -- cgit v1.1 From deaa79ca9e91e3c4d027561647669287a39ceacd Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 3 May 2010 23:53:49 +0200 Subject: Refix the fix --- OpenSim/Data/MySQL/MySQLXInventoryData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index a3b728b..0fe801d 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -163,7 +163,7 @@ namespace OpenSim.Data.MySQL public override bool Store(XInventoryItem item) { - if (base.Store(item)) + if (!base.Store(item)) return false; using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) -- cgit v1.1 From c86259c6710c8ce5c97a7a64bbb96dac35440aec Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 4 May 2010 00:44:05 +0200 Subject: Fix scripted give and interactive give to offline avatars. Both folder and single items are now supported. Magic Boxes, yeah! --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 16 +++++++++++ .../Shared/Api/Implementation/LSL_Api.cs | 31 ++++++++++++++++------ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 9b838ab..c105560 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -94,6 +94,22 @@ namespace OpenSim.Region.Framework.Scenes public void AddInventoryItem(UUID AgentID, InventoryItemBase item) { + InventoryFolderBase folder; + + if (item.Folder == UUID.Zero) + { + folder = InventoryService.GetFolderForType(AgentID, (AssetType)item.AssetType); + if (folder == null) + { + folder = InventoryService.GetRootFolder(AgentID); + + if (folder == null) + return; + } + + item.Folder = folder.ID; + } + if (InventoryService.AddItem(item)) { int userlevel = 0; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 228e9b8..d216eff 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4005,9 +4005,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); } - // check if destination is an avatar - if (World.GetScenePresence(destId) != null) + // check if destination is an object + if (World.GetSceneObjectPart(destId) != null) { + // destination is an object + World.MoveTaskInventoryItem(destId, m_host, objId); + } + else + { + ScenePresence presence = World.GetScenePresence(destId); + + if (presence == null) + { + UserAccount account = + World.UserAccountService.GetUserAccount( + World.RegionInfo.ScopeID, + destId); + + if (account == null) + { + llSay(0, "Can't find destination "+destId.ToString()); + return; + } + } + // destination is an avatar InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); @@ -4037,12 +4058,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //This delay should only occur when giving inventory to avatars. ScriptSleep(3000); } - else - { - // destination is an object - World.MoveTaskInventoryItem(destId, m_host, objId); - } - } [DebuggerNonUserCode] -- cgit v1.1 From dbce360566dd20d2b0f2ad649ba7a1dca9a27d36 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 4 May 2010 02:43:22 +0200 Subject: Fix full circle sensors --- .../ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 5e2e205..d354fde 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -483,6 +483,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins sensedEntities.Add(new SensedEntity(dis, presence.UUID)); } } + else + { + // If full circle is asked for, just add it + sensedEntities.Add(new SensedEntity(dis, presence.UUID)); + } } }); -- cgit v1.1 From da849aea780b83e3b954ef26772c11ca8c4c2371 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 4 May 2010 17:56:30 +0200 Subject: Allow regions to get the list of the other regions in the estate --- OpenSim/Data/MySQL/MySQLEstateData.cs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/MySQLEstateData.cs b/OpenSim/Data/MySQL/MySQLEstateData.cs index d0c02f0..08e2144 100644 --- a/OpenSim/Data/MySQL/MySQLEstateData.cs +++ b/OpenSim/Data/MySQL/MySQLEstateData.cs @@ -474,7 +474,36 @@ namespace OpenSim.Data.MySQL public List GetRegions(int estateID) { - return new List(); + List result = new List(); + + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + try + { + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "select RegionID from estate_map where EstateID = ?EstateID"; + cmd.Parameters.AddWithValue("?EstateID", estateID.ToString()); + + using (IDataReader reader = cmd.ExecuteReader()) + { + while(reader.Read()) + result.Add(new UUID(reader["RegionID"].ToString())); + reader.Close(); + } + } + } + catch (Exception e) + { + m_log.Error("[REGION DB]: Error reading estate map. " + e.ToString()); + return result; + } + dbcon.Close(); + } + + return result; } public bool DeleteEstate(int estateID) -- cgit v1.1 From 4f93d30790c8392c6f91cb1818d1c16f89169ab7 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 4 May 2010 18:10:13 +0200 Subject: Allow reloading of estate settings into a running region. Move sun update helper into Scene, since that is less evil than exposing m_storageManager to the public. --- .../World/Estate/EstateManagementModule.cs | 40 ++----------------- OpenSim/Region/Framework/Scenes/Scene.cs | 46 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 91d40ab..77068b0 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -212,7 +212,7 @@ namespace OpenSim.Region.CoreModules.World.Estate m_scene.RegionInfo.RegionSettings.FixedSun = UseFixedSun; m_scene.RegionInfo.RegionSettings.SunPosition = SunHour; - TriggerEstateToolsSunUpdate(); + m_scene.TriggerEstateSunUpdate(); //m_log.Debug("[ESTATE]: UFS: " + UseFixedSun.ToString()); //m_log.Debug("[ESTATE]: SunHour: " + SunHour.ToString()); @@ -861,7 +861,7 @@ namespace OpenSim.Region.CoreModules.World.Estate m_scene.RegionInfo.EstateSettings.Save(); - TriggerEstateToolsSunUpdate(); + m_scene.TriggerEstateSunUpdate(); sendDetailedEstateData(remoteClient, invoice); } @@ -983,7 +983,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { // Sets up the sun module based no the saved Estate and Region Settings // DO NOT REMOVE or the sun will stop working - TriggerEstateToolsSunUpdate(); + m_scene.TriggerEstateSunUpdate(); } public void Close() @@ -1004,40 +1004,6 @@ namespace OpenSim.Region.CoreModules.World.Estate #region Other Functions - private void TriggerEstateToolsSunUpdate() - { - float sun; - if (m_scene.RegionInfo.RegionSettings.UseEstateSun) - { - sun = (float)m_scene.RegionInfo.EstateSettings.SunPosition; - if (m_scene.RegionInfo.EstateSettings.UseGlobalTime) - { - sun = m_scene.EventManager.GetCurrentTimeAsSunLindenHour() - 6.0f; - } - - // - m_scene.EventManager.TriggerEstateToolsSunUpdate( - m_scene.RegionInfo.RegionHandle, - m_scene.RegionInfo.EstateSettings.FixedSun, - m_scene.RegionInfo.RegionSettings.UseEstateSun, - sun); - } - else - { - // Use the Sun Position from the Region Settings - sun = (float)m_scene.RegionInfo.RegionSettings.SunPosition - 6.0f; - - m_scene.EventManager.TriggerEstateToolsSunUpdate( - m_scene.RegionInfo.RegionHandle, - m_scene.RegionInfo.RegionSettings.FixedSun, - m_scene.RegionInfo.RegionSettings.UseEstateSun, - sun); - } - - - } - - public void changeWaterHeight(float height) { setRegionTerrainSettings(height, diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 3e78a08..f17e464 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5109,5 +5109,51 @@ namespace OpenSim.Region.Framework.Scenes { return new Vector3(x, y, GetGroundHeight(x, y)); } + + public List GetEstateRegions(int estateID) + { + if (m_storageManager.EstateDataStore == null) + return new List(); + + return m_storageManager.EstateDataStore.GetRegions(estateID); + } + + public void ReloadEstateData() + { + m_regInfo.EstateSettings = m_storageManager.EstateDataStore.LoadEstateSettings(m_regInfo.RegionID, false); + + TriggerEstateSunUpdate(); + } + + public void TriggerEstateSunUpdate() + { + float sun; + if (RegionInfo.RegionSettings.UseEstateSun) + { + sun = (float)RegionInfo.EstateSettings.SunPosition; + if (RegionInfo.EstateSettings.UseGlobalTime) + { + sun = EventManager.GetCurrentTimeAsSunLindenHour() - 6.0f; + } + + // + EventManager.TriggerEstateToolsSunUpdate( + RegionInfo.RegionHandle, + RegionInfo.EstateSettings.FixedSun, + RegionInfo.RegionSettings.UseEstateSun, + sun); + } + else + { + // Use the Sun Position from the Region Settings + sun = (float)RegionInfo.RegionSettings.SunPosition - 6.0f; + + EventManager.TriggerEstateToolsSunUpdate( + RegionInfo.RegionHandle, + RegionInfo.RegionSettings.FixedSun, + RegionInfo.RegionSettings.UseEstateSun, + sun); + } + } } } -- cgit v1.1 From ce86d39c70882a4beb04a23565121b05a4325a46 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 4 May 2010 18:31:52 +0200 Subject: Add "reload estate" command to sims --- OpenSim/Region/Framework/Scenes/Scene.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f17e464..0ca5948 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -662,6 +662,10 @@ namespace OpenSim.Region.Framework.Scenes } } + MainConsole.Instance.Commands.AddCommand("region", false, "reload estate", + "reload estate", + "Reload the estate data", HandleReloadEstate); + //Bind Storage Manager functions to some land manager functions for this scene EventManager.OnLandObjectAdded += new EventManager.LandObjectAdded(m_storageManager.DataStore.StoreLandObject); @@ -5155,5 +5159,15 @@ namespace OpenSim.Region.Framework.Scenes sun); } } + + private void HandleReloadEstate(string module, string[] cmd) + { + if (MainConsole.Instance.ConsoleScene == null || + (MainConsole.Instance.ConsoleScene is Scene && + (Scene)MainConsole.Instance.ConsoleScene == this)) + { + ReloadEstateData(); + } + } } } -- cgit v1.1 From 97bbce92a865279de3b240eb07b6b54490d02942 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 4 May 2010 20:57:31 +0200 Subject: Add events to the estate interface to let interested modules know of changes to estate settings --- .../World/Estate/EstateManagementModule.cs | 36 ++++++++++++++++++++++ .../Region/Framework/Interfaces/IEstateModule.cs | 5 +++ 2 files changed, 41 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 77068b0..92e9eed 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -48,6 +48,9 @@ namespace OpenSim.Region.CoreModules.World.Estate private EstateTerrainXferHandler TerrainUploader; + public event ChangeDelegate OnRegionInfoChange; + public event ChangeDelegate OnEstateInfoChange; + #region Packet Data Responders private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice) @@ -137,6 +140,7 @@ namespace OpenSim.Region.CoreModules.World.Estate m_scene.RegionInfo.RegionSettings.AllowLandJoinDivide = false; m_scene.RegionInfo.RegionSettings.Save(); + TriggerRegionInfoChange(); sendRegionInfoPacketToAll(); } @@ -162,6 +166,7 @@ namespace OpenSim.Region.CoreModules.World.Estate break; } m_scene.RegionInfo.RegionSettings.Save(); + TriggerRegionInfoChange(); sendRegionInfoPacketToAll(); } @@ -187,6 +192,7 @@ namespace OpenSim.Region.CoreModules.World.Estate break; } m_scene.RegionInfo.RegionSettings.Save(); + TriggerRegionInfoChange(); sendRegionInfoPacketToAll(); } @@ -219,6 +225,7 @@ namespace OpenSim.Region.CoreModules.World.Estate sendRegionInfoPacketToAll(); m_scene.RegionInfo.RegionSettings.Save(); + TriggerRegionInfoChange(); } private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds) @@ -230,6 +237,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { m_scene.RegionInfo.RegionSettings.Covenant = estateCovenantID; m_scene.RegionInfo.RegionSettings.Save(); + TriggerRegionInfoChange(); } private void handleEstateAccessDeltaRequest(IClientAPI remote_client, UUID invoice, int estateAccessType, UUID user) @@ -245,6 +253,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { m_scene.RegionInfo.EstateSettings.AddEstateUser(user); m_scene.RegionInfo.EstateSettings.Save(); + TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AccessOptions, m_scene.RegionInfo.EstateSettings.EstateAccess, m_scene.RegionInfo.EstateSettings.EstateID); } else @@ -259,6 +268,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { m_scene.RegionInfo.EstateSettings.RemoveEstateUser(user); m_scene.RegionInfo.EstateSettings.Save(); + TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AccessOptions, m_scene.RegionInfo.EstateSettings.EstateAccess, m_scene.RegionInfo.EstateSettings.EstateID); } @@ -273,6 +283,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { m_scene.RegionInfo.EstateSettings.AddEstateGroup(user); m_scene.RegionInfo.EstateSettings.Save(); + TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AllowedGroups, m_scene.RegionInfo.EstateSettings.EstateGroups, m_scene.RegionInfo.EstateSettings.EstateID); } else @@ -286,6 +297,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { m_scene.RegionInfo.EstateSettings.RemoveEstateGroup(user); m_scene.RegionInfo.EstateSettings.Save(); + TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.AllowedGroups, m_scene.RegionInfo.EstateSettings.EstateGroups, m_scene.RegionInfo.EstateSettings.EstateID); } @@ -323,6 +335,7 @@ namespace OpenSim.Region.CoreModules.World.Estate m_scene.RegionInfo.EstateSettings.AddBan(item); m_scene.RegionInfo.EstateSettings.Save(); + TriggerEstateInfoChange(); ScenePresence s = m_scene.GetScenePresence(user); if (s != null) @@ -370,6 +383,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { m_scene.RegionInfo.EstateSettings.RemoveBan(listitem.BannedUserID); m_scene.RegionInfo.EstateSettings.Save(); + TriggerEstateInfoChange(); } else { @@ -389,6 +403,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { m_scene.RegionInfo.EstateSettings.AddEstateManager(user); m_scene.RegionInfo.EstateSettings.Save(); + TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateID); } else @@ -402,6 +417,7 @@ namespace OpenSim.Region.CoreModules.World.Estate { m_scene.RegionInfo.EstateSettings.RemoveEstateManager(user); m_scene.RegionInfo.EstateSettings.Save(); + TriggerEstateInfoChange(); remote_client.SendEstateList(invoice, (int)Constants.EstateAccessCodex.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateManagers, m_scene.RegionInfo.EstateSettings.EstateID); } @@ -449,6 +465,7 @@ namespace OpenSim.Region.CoreModules.World.Estate m_scene.RegionInfo.RegionSettings.Save(); + TriggerRegionInfoChange(); m_scene.SetSceneCoreDebug(scripted, collisionEvents, physics); } @@ -860,6 +877,7 @@ namespace OpenSim.Region.CoreModules.World.Estate m_scene.RegionInfo.EstateSettings.DenyMinors = false; m_scene.RegionInfo.EstateSettings.Save(); + TriggerEstateInfoChange(); m_scene.TriggerEstateSunUpdate(); @@ -927,6 +945,7 @@ namespace OpenSim.Region.CoreModules.World.Estate break; } m_scene.RegionInfo.RegionSettings.Save(); + TriggerRegionInfoChange(); sendRegionInfoPacketToAll(); } @@ -972,6 +991,7 @@ namespace OpenSim.Region.CoreModules.World.Estate break; } m_scene.RegionInfo.RegionSettings.Save(); + TriggerRegionInfoChange(); sendRegionHandshakeToAll(); } } @@ -1141,5 +1161,21 @@ namespace OpenSim.Region.CoreModules.World.Estate return false; } + + protected void TriggerRegionInfoChange() + { + ChangeDelegate change = OnRegionInfoChange; + + if (change != null) + change(); + } + + protected void TriggerEstateInfoChange() + { + ChangeDelegate change = OnEstateInfoChange; + + if (change != null) + change(); + } } } diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 890fa31..b2135d2 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -29,8 +29,13 @@ using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces { + public delegate void ChangeDelegate(); + public interface IEstateModule : IRegionModule { + event ChangeDelegate OnRegionInfoChange; + event ChangeDelegate OnEstateInfoChange; + uint GetRegionFlags(); bool IsManager(UUID avatarID); -- cgit v1.1 From 07e0732a10928e317f3245a8a1b4e2c12f294556 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 4 May 2010 21:16:20 +0200 Subject: make the events more useful by providing the source region --- OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | 4 ++-- OpenSim/Region/Framework/Interfaces/IEstateModule.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 92e9eed..dcc66ca 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -1167,7 +1167,7 @@ namespace OpenSim.Region.CoreModules.World.Estate ChangeDelegate change = OnRegionInfoChange; if (change != null) - change(); + change(m_scene.RegionInfo.RegionID); } protected void TriggerEstateInfoChange() @@ -1175,7 +1175,7 @@ namespace OpenSim.Region.CoreModules.World.Estate ChangeDelegate change = OnEstateInfoChange; if (change != null) - change(); + change(m_scene.RegionInfo.RegionID); } } } diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index b2135d2..329c3f5 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -29,7 +29,7 @@ using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces { - public delegate void ChangeDelegate(); + public delegate void ChangeDelegate(UUID regionID); public interface IEstateModule : IRegionModule { -- cgit v1.1 From 49efec2ef17ece206f73acf1665bf973a6204b87 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 4 May 2010 23:45:59 +0200 Subject: Strip estate message sending out from the estate management module and the dialog module. Convert it to an event on the estate module interface. The old implementation did the same as message to region, a button that is right next to it on the UI. This implementation prevented people from adding a more sane one in a module. --- OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs | 8 -------- .../CoreModules/World/Estate/EstateManagementModule.cs | 14 ++++++++++---- OpenSim/Region/Framework/Interfaces/IDialogModule.cs | 13 ------------- OpenSim/Region/Framework/Interfaces/IEstateModule.cs | 2 ++ 4 files changed, 12 insertions(+), 25 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index c31266c..da38ede 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -132,14 +132,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); } - public void SendNotificationToUsersInEstate( - UUID fromAvatarID, string fromAvatarName, string message) - { - // TODO: This does not yet do what it says on the tin - it only sends the message to users in the same - // region as the sending avatar. - SendNotificationToUsersInRegion(fromAvatarID, fromAvatarName, message); - } - public void SendTextBoxToUser(UUID avatarid, string message, int chatChannel, string name, UUID objectid, UUID ownerid) { UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, ownerid); diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index dcc66ca..abd0fcb 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.World.Estate public event ChangeDelegate OnRegionInfoChange; public event ChangeDelegate OnEstateInfoChange; + public event MessageDelegate OnEstateMessage; #region Packet Data Responders @@ -440,10 +441,7 @@ namespace OpenSim.Region.CoreModules.World.Estate private void SendEstateBlueBoxMessage( IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) { - IDialogModule dm = m_scene.RequestModuleInterface(); - - if (dm != null) - dm.SendNotificationToUsersInEstate(senderID, senderName, message); + TriggerEstateMessage(senderID, senderName, message); } private void handleEstateDebugRegionRequest(IClientAPI remote_client, UUID invoice, UUID senderID, bool scripted, bool collisionEvents, bool physics) @@ -1177,5 +1175,13 @@ namespace OpenSim.Region.CoreModules.World.Estate if (change != null) change(m_scene.RegionInfo.RegionID); } + + protected void TriggerEstateMessage(UUID fromID, string fromName, string message) + { + MessageDelegate onmessage = OnEstateMessage; + + if (onmessage != null) + onmessage(m_scene.RegionInfo.RegionID, fromID, fromName, message); + } } } diff --git a/OpenSim/Region/Framework/Interfaces/IDialogModule.cs b/OpenSim/Region/Framework/Interfaces/IDialogModule.cs index 35b4b63..be9764a 100644 --- a/OpenSim/Region/Framework/Interfaces/IDialogModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IDialogModule.cs @@ -120,19 +120,6 @@ namespace OpenSim.Region.Framework.Interfaces void SendNotificationToUsersInRegion(UUID fromAvatarID, string fromAvatarName, string message); /// - /// Send a notification to all users in the estate. This notification should remain around until the - /// user explicitly dismisses it. - /// - /// - /// On the Linden Labs Second Client (as of 1.21), this is a big blue box message on the upper right of the - /// screen. - /// - /// The user sending the message - /// The name of the user doing the sending - /// The message being sent to the user - void SendNotificationToUsersInEstate(UUID fromAvatarID, string fromAvatarName, string message); - - /// /// Send a textbox entry for the client to respond to /// void SendTextBoxToUser(UUID avatarid, string message, int chatChannel, string name, UUID objectid, UUID ownerid); diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 329c3f5..c850f7f 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -30,11 +30,13 @@ using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces { public delegate void ChangeDelegate(UUID regionID); + public delegate void MessageDelegate(UUID regionID, UUID fromID, string fromName, string message); public interface IEstateModule : IRegionModule { event ChangeDelegate OnRegionInfoChange; event ChangeDelegate OnEstateInfoChange; + event MessageDelegate OnEstateMessage; uint GetRegionFlags(); bool IsManager(UUID avatarID); -- cgit v1.1 From efc32415414753adc7f3f170e2d7a339095212db Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 5 May 2010 01:32:55 +0200 Subject: Add perms check to the teleport home client command handlers. --- OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index abd0fcb..940b535 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -470,6 +470,9 @@ namespace OpenSim.Region.CoreModules.World.Estate private void handleEstateTeleportOneUserHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID, UUID prey) { + if (!m_scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) + return; + if (prey != UUID.Zero) { ScenePresence s = m_scene.GetScenePresence(prey); @@ -483,6 +486,9 @@ namespace OpenSim.Region.CoreModules.World.Estate private void handleEstateTeleportAllUsersHomeRequest(IClientAPI remover_client, UUID invoice, UUID senderID) { + if (!m_scene.Permissions.CanIssueEstateCommand(remover_client.AgentId, false)) + return; + m_scene.ForEachScenePresence(delegate(ScenePresence sp) { if (sp.UUID != senderID) -- cgit v1.1 From 608bb0dfefbbc97aded6d1357dd9d350053411fb Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 5 May 2010 14:36:24 +0100 Subject: Patch from mcortez: Update groups, add ALPHA Siman grid connector for groups Mantis #4646 Signed-off-by: Melanie --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 341 +++--- .../XmlRpcGroups/IGroupsServicesConnector.cs | 62 +- .../SimianGroupsServicesConnectorModule.cs | 1278 ++++++++++++++++++++ .../XmlRpcGroupsServicesConnectorModule.cs | 209 ++-- 4 files changed, 1570 insertions(+), 320 deletions(-) create mode 100644 OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 8d32e66..6b942cb 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -43,6 +43,8 @@ using OpenSim.Region.CoreModules.Framework.EventQueue; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + using Caps = OpenSim.Framework.Capabilities.Caps; using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; @@ -87,16 +89,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private IGroupsServicesConnector m_groupData = null; - class GroupRequestIDInfo - { - public GroupRequestID RequestID = new GroupRequestID(); - public DateTime LastUsedTMStamp = DateTime.MinValue; - } - private Dictionary m_clientRequestIDInfo = new Dictionary(); - private const int m_clientRequestIDFlushTimeOut = 300000; // Every 5 minutes - private Timer m_clientRequestIDFlushTimer; - - // Configuration settings private bool m_groupsEnabled = false; private bool m_groupNoticesEnabled = true; @@ -133,30 +125,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupNoticesEnabled = groupsConfig.GetBoolean("NoticesEnabled", true); m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); - m_clientRequestIDFlushTimer = new Timer(); - m_clientRequestIDFlushTimer.Interval = m_clientRequestIDFlushTimeOut; - m_clientRequestIDFlushTimer.Elapsed += FlushClientRequestIDInfoCache; - m_clientRequestIDFlushTimer.AutoReset = true; - m_clientRequestIDFlushTimer.Start(); - } - } - - void FlushClientRequestIDInfoCache(object sender, ElapsedEventArgs e) - { - lock (m_clientRequestIDInfo) - { - TimeSpan cacheTimeout = new TimeSpan(0,0, m_clientRequestIDFlushTimeOut / 1000); - UUID[] CurrentKeys = new UUID[m_clientRequestIDInfo.Count]; - foreach (UUID key in CurrentKeys) - { - if (m_clientRequestIDInfo.ContainsKey(key)) - { - if (DateTime.Now - m_clientRequestIDInfo[key].LastUsedTMStamp > cacheTimeout) - { - m_clientRequestIDInfo.Remove(key); - } - } - } } } @@ -234,8 +202,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; if (m_debugEnabled) m_log.Debug("[GROUPS]: Shutting down Groups module."); - - m_clientRequestIDFlushTimer.Stop(); } public Type ReplaceableInterface @@ -272,14 +238,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Used for Notices and Group Invites/Accept/Reject client.OnInstantMessage += OnInstantMessage; - lock (m_clientRequestIDInfo) - { - if (m_clientRequestIDInfo.ContainsKey(client.AgentId)) - { - // flush any old RequestID information - m_clientRequestIDInfo.Remove(client.AgentId); - } - } + // Send client thier groups information. SendAgentGroupDataUpdate(client, client.AgentId); } @@ -287,7 +246,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetClientGroupRequestID(remoteClient), avatarID).ToArray(); + //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray(); GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); } @@ -326,15 +285,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } */ - void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart) { if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", + System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); // TODO: This currently ignores pretty much all the query flags including Mature and sort order - remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetClientGroupRequestID(remoteClient), queryText).ToArray()); + remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentID(remoteClient), queryText).ToArray()); } } @@ -348,7 +309,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups string activeGroupName = string.Empty; ulong activeGroupPowers = (ulong)GroupPowers.None; - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetClientGroupRequestID(remoteClient), dataForAgentID); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient), dataForAgentID); if (membership != null) { activeGroupID = membership.GroupID; @@ -361,13 +322,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups SendScenePresenceUpdate(dataForAgentID, activeGroupTitle); } - private void HandleUUIDGroupNameRequest(UUID GroupID,IClientAPI remoteClient) + private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); string GroupName; - GroupRecord group = m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), GroupID, null); + GroupRecord group = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null); if (group != null) { GroupName = group.GroupName; @@ -388,7 +349,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) { UUID inviteID = new UUID(im.imSessionID); - GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); + GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); if (inviteInfo == null) { @@ -407,7 +368,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received an accept invite notice."); // and the sessionid is the role - m_groupData.AddAgentToGroup(GetClientGroupRequestID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); + m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; @@ -431,14 +392,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // TODO: If the inviter is still online, they need an agent dataupdate // and maybe group membership updates for the invitee - m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); + m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); } // Reject if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received a reject invite notice."); - m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); + m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); } } } @@ -452,7 +413,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } UUID GroupID = new UUID(im.toAgentID); - if (m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), GroupID, null) != null) + if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null) != null) { UUID NoticeID = UUID.Random(); string Subject = im.message.Substring(0, im.message.IndexOf('|')); @@ -496,21 +457,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - m_groupData.AddGroupNotice(GetClientGroupRequestID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); + m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); if (OnNewGroupNotice != null) { OnNewGroupNotice(GroupID, NoticeID); } // Send notice out to everyone that wants notices - foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetClientGroupRequestID(remoteClient), GroupID)) + foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID)) { if (m_debugEnabled) { - UserProfileData targetUserProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(member.AgentID); - if (targetUserProfile != null) + UserAccount targetUser = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, member.AgentID); + if (targetUser != null) { - m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUserProfile.Name, member.AcceptNotices); + m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices); } else { @@ -588,20 +549,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public GroupRecord GetGroupRecord(UUID GroupID) { - return m_groupData.GetGroupRecord(null, GroupID, null); + return m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); } + public GroupRecord GetGroupRecord(string name) + { + return m_groupData.GetGroupRecord(UUID.Zero, UUID.Zero, name); + } + public void ActivateGroup(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentActiveGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID); + m_groupData.SetAgentActiveGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); // Changing active group changes title, active powers, all kinds of things // anyone who is in any region that can see this client, should probably be // updated with new group info. At a minimum, they should get ScenePresence // updated with new title. - UpdateAllClientsWithGroupInfo(remoteClient.AgentId); + UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); } /// @@ -611,10 +577,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - List agentRoles = m_groupData.GetAgentGroupRoles(grID, remoteClient.AgentId, groupID); - GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(grID, remoteClient.AgentId, groupID); + List agentRoles = m_groupData.GetAgentGroupRoles(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); + GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); List titles = new List(); foreach (GroupRolesData role in agentRoles) @@ -636,8 +601,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public List GroupMembersRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List data = m_groupData.GetGroupMembers(GetClientGroupRequestID(remoteClient), groupID); + List data = m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), groupID); + + if (m_debugEnabled) + { + foreach (GroupMembersData member in data) + { + m_log.DebugFormat("[GROUPS]: Member({0}) - IsOwner({1})", member.AgentID, member.IsOwner); + } + } return data; @@ -647,21 +619,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List data = m_groupData.GetGroupRoles(GetClientGroupRequestID(remoteClient), groupID); + List data = m_groupData.GetGroupRoles(GetRequestingAgentID(remoteClient), groupID); return data; - } public List GroupRoleMembersRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List data = m_groupData.GetGroupRoleMembers(GetClientGroupRequestID(remoteClient), groupID); - + List data = m_groupData.GetGroupRoleMembers(GetRequestingAgentID(remoteClient), groupID); + + if (m_debugEnabled) + { + foreach (GroupRoleMembersData member in data) + { + m_log.DebugFormat("[GROUPS]: Member({0}) - Role({1})", member.MemberID, member.RoleID); + } + } return data; - - } public GroupProfileData GroupProfileRequest(IClientAPI remoteClient, UUID groupID) @@ -670,17 +646,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupProfileData profile = new GroupProfileData(); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - GroupRecord groupInfo = m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), groupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); if (groupInfo != null) { profile.AllowPublish = groupInfo.AllowPublish; profile.Charter = groupInfo.Charter; profile.FounderID = groupInfo.FounderID; profile.GroupID = groupID; - profile.GroupMembershipCount = m_groupData.GetGroupMembers(grID, groupID).Count; - profile.GroupRolesCount = m_groupData.GetGroupRoles(grID, groupID).Count; + profile.GroupMembershipCount = m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), groupID).Count; + profile.GroupRolesCount = m_groupData.GetGroupRoles(GetRequestingAgentID(remoteClient), groupID).Count; profile.InsigniaID = groupInfo.GroupPicture; profile.MaturePublish = groupInfo.MaturePublish; profile.MembershipFee = groupInfo.MembershipFee; @@ -691,7 +666,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups profile.ShowInList = groupInfo.ShowInList; } - GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(grID, remoteClient.AgentId, groupID); + GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); if (memberInfo != null) { profile.MemberTitle = memberInfo.GroupTitle; @@ -705,46 +680,46 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - return m_groupData.GetAgentGroupMemberships(null, agentID).ToArray(); + return m_groupData.GetAgentGroupMemberships(UUID.Zero, agentID).ToArray(); } public GroupMembershipData GetMembershipData(UUID groupID, UUID agentID) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS]: {0} called with groupID={1}, agentID={2}", + System.Reflection.MethodBase.GetCurrentMethod().Name, groupID, agentID); - return m_groupData.GetAgentGroupMembership(null, agentID, groupID); + return m_groupData.GetAgentGroupMembership(UUID.Zero, agentID, groupID); } public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - // TODO: Security Check? - - m_groupData.UpdateGroup(GetClientGroupRequestID(remoteClient), groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); + // Note: Permissions checking for modification rights is handled by the Groups Server/Service + m_groupData.UpdateGroup(GetRequestingAgentID(remoteClient), groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); } public void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile) { - // TODO: Security Check? + // Note: Permissions checking for modification rights is handled by the Groups Server/Service if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentGroupInfo(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, acceptNotices, listInProfile); + m_groupData.SetAgentGroupInfo(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, acceptNotices, listInProfile); } public UUID CreateGroup(IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - - if (m_groupData.GetGroupRecord(grID, UUID.Zero, name) != null) + if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), UUID.Zero, name) != null) { remoteClient.SendCreateGroupReply(UUID.Zero, false, "A group with the same name already exists."); return UUID.Zero; } // is there is a money module present ? - IMoneyModule money=remoteClient.Scene.RequestModuleInterface(); + IMoneyModule money = remoteClient.Scene.RequestModuleInterface(); if (money != null) { // do the transaction, that is if the agent has got sufficient funds @@ -752,14 +727,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got issuficient funds to create a group."); return UUID.Zero; } - money.ApplyGroupCreationCharge(remoteClient.AgentId); + money.ApplyGroupCreationCharge(GetRequestingAgentID(remoteClient)); } - UUID groupID = m_groupData.CreateGroup(grID, name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, remoteClient.AgentId); + UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); // Update the founder with new group information. - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); return groupID; } @@ -770,7 +745,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // ToDo: check if agent is a member of group and is allowed to see notices? - return m_groupData.GetGroupNotices(GetClientGroupRequestID(remoteClient), groupID).ToArray(); + return m_groupData.GetGroupNotices(GetRequestingAgentID(remoteClient), groupID).ToArray(); } /// @@ -780,7 +755,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(null, avatarID); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(UUID.Zero, avatarID); if (membership != null) { return membership.GroupTitle; @@ -795,13 +770,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentActiveGroupRole(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, titleRoleID); + m_groupData.SetAgentActiveGroupRole(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, titleRoleID); // TODO: Not sure what all is needed here, but if the active group role change is for the group // the client currently has set active, then we need to do a scene presence update too - // if (m_groupData.GetAgentActiveMembership(remoteClient.AgentId).GroupID == GroupID) + // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) - UpdateAllClientsWithGroupInfo(remoteClient.AgentId); + UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); } @@ -811,16 +786,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Security Checks are handled in the Groups Service. - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - switch ((OpenMetaverse.GroupRoleUpdate)updateType) { case OpenMetaverse.GroupRoleUpdate.Create: - m_groupData.AddGroupRole(grID, groupID, UUID.Random(), name, description, title, powers); + m_groupData.AddGroupRole(GetRequestingAgentID(remoteClient), groupID, UUID.Random(), name, description, title, powers); break; case OpenMetaverse.GroupRoleUpdate.Delete: - m_groupData.RemoveGroupRole(grID, groupID, roleID); + m_groupData.RemoveGroupRole(GetRequestingAgentID(remoteClient), groupID, roleID); break; case OpenMetaverse.GroupRoleUpdate.UpdateAll: @@ -831,7 +804,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupPowers gp = (GroupPowers)powers; m_log.DebugFormat("[GROUPS]: Role ({0}) updated with Powers ({1}) ({2})", name, powers.ToString(), gp.ToString()); } - m_groupData.UpdateGroupRole(grID, groupID, roleID, name, description, title, powers); + m_groupData.UpdateGroupRole(GetRequestingAgentID(remoteClient), groupID, roleID, name, description, title, powers); break; case OpenMetaverse.GroupRoleUpdate.NoUpdate: @@ -842,7 +815,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes) @@ -850,18 +823,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Todo: Security check - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - switch (changes) { case 0: // Add - m_groupData.AddAgentToGroupRole(grID, memberID, groupID, roleID); + m_groupData.AddAgentToGroupRole(GetRequestingAgentID(remoteClient), memberID, groupID, roleID); break; case 1: // Remove - m_groupData.RemoveAgentFromGroupRole(grID, memberID, groupID, roleID); + m_groupData.RemoveAgentFromGroupRole(GetRequestingAgentID(remoteClient), memberID, groupID, roleID); break; default: @@ -870,25 +841,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - - GroupNoticeInfo data = m_groupData.GetGroupNotice(grID, groupNoticeID); + GroupNoticeInfo data = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), groupNoticeID); if (data != null) { - GroupRecord groupInfo = m_groupData.GetGroupRecord(grID, data.GroupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; msg.fromAgentID = data.GroupID.Guid; - msg.toAgentID = remoteClient.AgentId.Guid; + msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName; msg.message = data.noticeData.Subject + "|" + data.Message; @@ -900,7 +869,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.RegionID = UUID.Zero.Guid; msg.binaryBucket = data.BinaryBucket; - OutgoingInstantMessage(msg, remoteClient.AgentId); + OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); } } @@ -920,7 +889,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.Position = Vector3.Zero; msg.RegionID = UUID.Zero.Guid; - GroupNoticeInfo info = m_groupData.GetGroupNotice(null, groupNoticeID); + GroupNoticeInfo info = m_groupData.GetGroupNotice(agentID, groupNoticeID); if (info != null) { msg.fromAgentID = info.GroupID.Guid; @@ -947,7 +916,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Send agent information about his groups - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID) @@ -955,19 +924,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Should check to see if OpenEnrollment, or if there's an outstanding invitation - m_groupData.AddAgentToGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, UUID.Zero); + m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, UUID.Zero); remoteClient.SendJoinGroupReply(groupID, true); // Should this send updates to everyone in the group? - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.RemoveAgentFromGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID); + m_groupData.RemoveAgentFromGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); remoteClient.SendLeaveGroupReply(groupID, true); @@ -975,34 +944,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // SL sends out notifcations to the group messaging session that the person has left // Should this also update everyone who is in the group? - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); // Todo: Security check? - m_groupData.RemoveAgentFromGroup(grID, ejecteeID, groupID); + m_groupData.RemoveAgentFromGroup(GetRequestingAgentID(remoteClient), ejecteeID, groupID); - remoteClient.SendEjectGroupMemberReply(remoteClient.AgentId, groupID, true); + remoteClient.SendEjectGroupMemberReply(GetRequestingAgentID(remoteClient), groupID, true); - GroupRecord groupInfo = m_groupData.GetGroupRecord(grID, groupID, null); - UserProfileData userProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(ejecteeID); + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); - if ((groupInfo == null) || (userProfile == null)) + UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, ejecteeID); + if ((groupInfo == null) || (account == null)) { return; - } - + } // Send Message to Ejectee GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; - msg.fromAgentID = remoteClient.AgentId.Guid; + msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; // msg.fromAgentID = info.GroupID; msg.toAgentID = ejecteeID.Guid; //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); @@ -1028,13 +995,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; - msg.fromAgentID = remoteClient.AgentId.Guid; - msg.toAgentID = remoteClient.AgentId.Guid; + msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; + msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; msg.timestamp = 0; msg.fromAgentName = remoteClient.Name; - if (userProfile != null) + if (account != null) { - msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", remoteClient.Name, groupInfo.GroupName, userProfile.Name); + msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", remoteClient.Name, groupInfo.GroupName, account.FirstName + " " + account.LastName); } else { @@ -1047,7 +1014,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.Position = Vector3.Zero; msg.RegionID = remoteClient.Scene.RegionInfo.RegionID.Guid; msg.binaryBucket = new byte[0]; - OutgoingInstantMessage(msg, remoteClient.AgentId); + OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); // SL sends out messages to everyone in the group @@ -1061,13 +1028,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Todo: Security check, probably also want to send some kind of notification UUID InviteID = UUID.Random(); - GroupRequestID grid = GetClientGroupRequestID(remoteClient); - m_groupData.AddAgentToGroupInvite(grid, InviteID, groupID, roleID, invitedAgentID); + m_groupData.AddAgentToGroupInvite(GetRequestingAgentID(remoteClient), InviteID, groupID, roleID, invitedAgentID); // Check to see if the invite went through, if it did not then it's possible // the remoteClient did not validate or did not have permission to invite. - GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(grid, InviteID); + GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), InviteID); if (inviteInfo != null) { @@ -1079,7 +1045,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.imSessionID = inviteUUID; - // msg.fromAgentID = remoteClient.AgentId.Guid; + // msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; msg.fromAgentID = groupID.Guid; msg.toAgentID = invitedAgentID.Guid; //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); @@ -1132,57 +1098,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return child; } - private GroupRequestID GetClientGroupRequestID(IClientAPI client) - { - if (client == null) - { - return new GroupRequestID(); - } - - lock (m_clientRequestIDInfo) - { - if (!m_clientRequestIDInfo.ContainsKey(client.AgentId)) - { - GroupRequestIDInfo info = new GroupRequestIDInfo(); - info.RequestID.AgentID = client.AgentId; - info.RequestID.SessionID = client.SessionId; - - UserProfileData userProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(client.AgentId); - if (userProfile == null) - { - // This should be impossible. If I've been passed a reference to a client - // that client should be registered with the UserService. So something - // is horribly wrong somewhere. - - m_log.WarnFormat("[GROUPS]: Could not find a user profile for {0} / {1}", client.Name, client.AgentId); - - // Default to local user service and hope for the best? - info.RequestID.UserServiceURL = m_sceneList[0].CommsManager.NetworkServersInfo.UserURL; - - } - else if (userProfile is ForeignUserProfileData) - { - // They aren't from around here - ForeignUserProfileData fupd = (ForeignUserProfileData)userProfile; - info.RequestID.UserServiceURL = fupd.UserServerURI; - } - else - { - // They're a local user, use this: - info.RequestID.UserServiceURL = m_sceneList[0].CommsManager.NetworkServersInfo.UserURL; - } - - m_clientRequestIDInfo.Add(client.AgentId, info); - } - - m_clientRequestIDInfo[client.AgentId].LastUsedTMStamp = DateTime.Now; - - return m_clientRequestIDInfo[client.AgentId].RequestID; - } -// Unreachable code! -// return new GroupRequestID(); - } - /// /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'. /// @@ -1201,7 +1116,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups foreach (GroupMembershipData membership in data) { - if (remoteClient.AgentId != dataForAgentID) + if (GetRequestingAgentID(remoteClient) != dataForAgentID) { if (!membership.ListInProfile) { @@ -1229,13 +1144,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups OSDMap llDataStruct = new OSDMap(3); llDataStruct.Add("AgentData", AgentData); llDataStruct.Add("GroupData", GroupData); - llDataStruct.Add("NewGroupData", NewGroupData); + llDataStruct.Add("NewGroupData", NewGroupData); + + if (m_debugEnabled) + { + m_log.InfoFormat("[GROUPS]: {0}", OSDParser.SerializeJsonString(llDataStruct)); + } IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); if (queue != null) { - queue.Enqueue(EventQueueHelper.buildEvent("AgentGroupDataUpdate", llDataStruct), remoteClient.AgentId); + queue.Enqueue(EventQueueHelper.buildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient)); } } @@ -1308,7 +1228,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private GroupMembershipData[] GetProfileListedGroupMemberships(IClientAPI requestingClient, UUID dataForAgentID) { - List membershipData = m_groupData.GetAgentGroupMemberships(GetClientGroupRequestID(requestingClient), dataForAgentID); + List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; if (requestingClient.AgentId != dataForAgentID) @@ -1330,7 +1250,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); foreach (GroupMembershipData membership in membershipArray) { - m_log.InfoFormat("[GROUPS]: {0} :: {1} - {2}", dataForAgentID, membership.GroupName, membership.GroupTitle); + m_log.InfoFormat("[GROUPS]: {0} :: {1} - {2} - {3}", dataForAgentID, membership.GroupName, membership.GroupTitle, membership.GroupPowers); } } @@ -1342,12 +1262,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff - UserProfileData userProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(dataForAgentID); + UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, dataForAgentID); string firstname, lastname; - if (userProfile != null) + if (account != null) { - firstname = userProfile.FirstName; - lastname = userProfile.SurName; + firstname = account.FirstName; + lastname = account.LastName; } else { @@ -1388,7 +1308,24 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // } - #endregion + #endregion + + private UUID GetRequestingAgentID(IClientAPI client) + { + UUID requestingAgentID = UUID.Zero; + if (client != null) + { + requestingAgentID = client.AgentId; + } + return requestingAgentID; + } } + public class GroupNoticeInfo + { + public GroupNoticeData noticeData = new GroupNoticeData(); + public UUID GroupID = UUID.Zero; + public string Message = string.Empty; + public byte[] BinaryBucket = new byte[0]; + } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs index 9e0fa2d..6487967 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs @@ -36,42 +36,41 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { interface IGroupsServicesConnector { - UUID CreateGroup(GroupRequestID requestID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); - void UpdateGroup(GroupRequestID requestID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); - GroupRecord GetGroupRecord(GroupRequestID requestID, UUID GroupID, string GroupName); - List FindGroups(GroupRequestID requestID, string search); - List GetGroupMembers(GroupRequestID requestID, UUID GroupID); + UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); + void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); + GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName); + List FindGroups(UUID RequestingAgentID, string search); + List GetGroupMembers(UUID RequestingAgentID, UUID GroupID); - void AddGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); - void UpdateGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); - void RemoveGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID); - List GetGroupRoles(GroupRequestID requestID, UUID GroupID); - List GetGroupRoleMembers(GroupRequestID requestID, UUID GroupID); + void AddGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); + void UpdateGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); + void RemoveGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID); + List GetGroupRoles(UUID RequestingAgentID, UUID GroupID); + List GetGroupRoleMembers(UUID RequestingAgentID, UUID GroupID); - void AddAgentToGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - void RemoveAgentFromGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID); + void AddAgentToGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + void RemoveAgentFromGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - void AddAgentToGroupInvite(GroupRequestID requestID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID); - GroupInviteInfo GetAgentToGroupInvite(GroupRequestID requestID, UUID inviteID); - void RemoveAgentToGroupInvite(GroupRequestID requestID, UUID inviteID); + void AddAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID); + GroupInviteInfo GetAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID); + void RemoveAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID); + void AddAgentToGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + void RemoveAgentFromGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + List GetAgentGroupRoles(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - void AddAgentToGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - void RemoveAgentFromGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - List GetAgentGroupRoles(GroupRequestID requestID, UUID AgentID, UUID GroupID); + void SetAgentActiveGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID); + GroupMembershipData GetAgentActiveMembership(UUID RequestingAgentID, UUID AgentID); - void SetAgentActiveGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID); - GroupMembershipData GetAgentActiveMembership(GroupRequestID requestID, UUID AgentID); + void SetAgentActiveGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + void SetAgentGroupInfo(UUID RequestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile); - void SetAgentActiveGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - void SetAgentGroupInfo(GroupRequestID requestID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile); + GroupMembershipData GetAgentGroupMembership(UUID RequestingAgentID, UUID AgentID, UUID GroupID); + List GetAgentGroupMemberships(UUID RequestingAgentID, UUID AgentID); - GroupMembershipData GetAgentGroupMembership(GroupRequestID requestID, UUID AgentID, UUID GroupID); - List GetAgentGroupMemberships(GroupRequestID requestID, UUID AgentID); - - void AddGroupNotice(GroupRequestID requestID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); - GroupNoticeInfo GetGroupNotice(GroupRequestID requestID, UUID noticeID); - List GetGroupNotices(GroupRequestID requestID, UUID GroupID); + void AddGroupNotice(UUID RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); + GroupNoticeInfo GetGroupNotice(UUID RequestingAgentID, UUID noticeID); + List GetGroupNotices(UUID RequestingAgentID, UUID GroupID); } public class GroupInviteInfo @@ -81,11 +80,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public UUID AgentID = UUID.Zero; public UUID InviteID = UUID.Zero; } - - public class GroupRequestID - { - public UUID AgentID = UUID.Zero; - public string UserServiceURL = string.Empty; - public UUID SessionID = UUID.Zero; - } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs new file mode 100644 index 0000000..590753e --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -0,0 +1,1278 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Reflection; + +using Nwc.XmlRpc; + +using log4net; +using Mono.Addins; +using Nini.Config; + +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; + +/*************************************************************************** + * Simian Data Map + * =============== + * + * OwnerID -> Type -> Key + * ----------------------- + * + * UserID -> Group -> ActiveGroup + * + GroupID + * + * UserID -> GroupMember -> GroupID + * + SelectedRoleID [UUID] + * + AcceptNotices [bool] + * + ListInProfile [bool] + * + Contribution [int] + * + * UserID -> GroupRole[GroupID] -> RoleID + * + * GroupID -> Group -> GroupName + * + Charter + * + ShowInList + * + InsigniaID + * + MembershipFee + * + OpenEnrollment + * + AllowPublish + * + MaturePublish + * + FounderID + * + EveryonePowers + * + OwnerRoleID + * + OwnersPowers + * + * GroupID -> GroupRole -> RoleID + * + Name + * + Description + * + Title + * + Powers + * + * GroupID -> GroupMemberInvite -> InviteID + * + AgentID + * + RoleID + * + * GroupID -> GroupNotice -> NoticeID + * + TimeStamp [uint] + * + FromName [string] + * + Subject [string] + * + Message [string] + * + BinaryBucket [byte[]] + * + * */ + +namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | + GroupPowers.Accountable | + GroupPowers.JoinChat | + GroupPowers.AllowVoiceChat | + GroupPowers.ReceiveNotices | + GroupPowers.StartProposal | + GroupPowers.VoteOnProposal; + + // Would this be cleaner as (GroupPowers)ulong.MaxValue; + public const GroupPowers m_DefaultOwnerPowers = GroupPowers.Accountable + | GroupPowers.AllowEditLand + | GroupPowers.AllowFly + | GroupPowers.AllowLandmark + | GroupPowers.AllowRez + | GroupPowers.AllowSetHome + | GroupPowers.AllowVoiceChat + | GroupPowers.AssignMember + | GroupPowers.AssignMemberLimited + | GroupPowers.ChangeActions + | GroupPowers.ChangeIdentity + | GroupPowers.ChangeMedia + | GroupPowers.ChangeOptions + | GroupPowers.CreateRole + | GroupPowers.DeedObject + | GroupPowers.DeleteRole + | GroupPowers.Eject + | GroupPowers.FindPlaces + | GroupPowers.Invite + | GroupPowers.JoinChat + | GroupPowers.LandChangeIdentity + | GroupPowers.LandDeed + | GroupPowers.LandDivideJoin + | GroupPowers.LandEdit + | GroupPowers.LandEjectAndFreeze + | GroupPowers.LandGardening + | GroupPowers.LandManageAllowed + | GroupPowers.LandManageBanned + | GroupPowers.LandManagePasses + | GroupPowers.LandOptions + | GroupPowers.LandRelease + | GroupPowers.LandSetSale + | GroupPowers.ModerateChat + | GroupPowers.ObjectManipulate + | GroupPowers.ObjectSetForSale + | GroupPowers.ReceiveNotices + | GroupPowers.RemoveMember + | GroupPowers.ReturnGroupOwned + | GroupPowers.ReturnGroupSet + | GroupPowers.ReturnNonGroup + | GroupPowers.RoleProperties + | GroupPowers.SendNotices + | GroupPowers.SetLandingPoint + | GroupPowers.StartProposal + | GroupPowers.VoteOnProposal; + + private bool m_connectorEnabled = false; + + private string m_serviceURL = string.Empty; + + private bool m_debugEnabled = false; + + // private IUserAccountService m_accountService = null; + + + #region IRegionModuleBase Members + + public string Name + { + get { return "SimianGroupsServicesConnector"; } + } + + // this module is not intended to be replaced, but there should only be 1 of them. + public Type ReplaceableInterface + { + get { return null; } + } + + public void Initialise(IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + + if (groupsConfig == null) + { + // Do not run this module by default. + return; + } + else + { + // if groups aren't enabled, we're not needed. + // if we're not specified as the connector to use, then we're not wanted + if ((groupsConfig.GetBoolean("Enabled", false) == false) + || (groupsConfig.GetString("ServicesConnectorModule", "Default") != Name)) + { + m_connectorEnabled = false; + return; + } + + m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); + + m_serviceURL = groupsConfig.GetString("XmlRpcServiceURL", string.Empty); + if ((m_serviceURL == null) || + (m_serviceURL == string.Empty)) + { + m_log.ErrorFormat("Please specify a valid Simian Server URL for XmlRpcServiceURL in OpenSim.ini, [Groups]"); + m_connectorEnabled = false; + return; + } + + // If we got all the config options we need, lets start'er'up + m_connectorEnabled = true; + + m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); + + } + } + + public void Close() + { + m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); + } + + public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) + { + if (m_connectorEnabled) + { + scene.RegisterModuleInterface(this); + } + } + + public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene) + { + if (scene.RequestModuleInterface() == this) + { + scene.UnregisterModuleInterface(this); + } + } + + public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene) + { + // TODO: May want to consider listenning for Agent Connections so we can pre-cache group info + // scene.EventManager.OnNewClient += OnNewClient; + } + + #endregion + + #region ISharedRegionModule Members + + public void PostInitialise() + { + // NoOp + } + + #endregion + + + + + #region IGroupsServicesConnector Members + + /// + /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. + /// + public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, + int membershipFee, bool openEnrollment, bool allowPublish, + bool maturePublish, UUID founderID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + UUID GroupID = UUID.Random(); + UUID OwnerRoleID = UUID.Random(); + + OSDMap GroupInfoMap = new OSDMap(); + GroupInfoMap["Charter"] = OSD.FromString(charter); + GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); + GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); + GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); + GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); + GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); + GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); + GroupInfoMap["FounderID"] = OSD.FromUUID(founderID); + GroupInfoMap["EveryonePowers"] = OSD.FromULong((ulong)m_DefaultEveryonePowers); + GroupInfoMap["OwnerRoleID"] = OSD.FromUUID(OwnerRoleID); + GroupInfoMap["OwnersPowers"] = OSD.FromULong((ulong)m_DefaultOwnerPowers); + + if(SimianAddGeneric(GroupID, "Group", name, GroupInfoMap)) + { + AddGroupRole(requestingAgentID, GroupID, UUID.Zero, "Everyone", "Members of " + name, "Member of " + name, (ulong)m_DefaultEveryonePowers); + AddGroupRole(requestingAgentID, GroupID, OwnerRoleID, "Owners", "Owners of " + name, "Owner of " + name, (ulong)m_DefaultOwnerPowers); + + AddAgentToGroup(requestingAgentID, requestingAgentID, GroupID, OwnerRoleID); + + return GroupID; + } + else + { + return UUID.Zero; + } + } + + + public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, + UUID insigniaID, int membershipFee, bool openEnrollment, + bool allowPublish, bool maturePublish) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + // TODO: Check to make sure requestingAgentID has permission to update group + + string GroupName; + OSDMap GroupInfoMap; + if( SimianGetFirstGenericEntry(groupID, "GroupInfo", out GroupName, out GroupInfoMap) ) + { + GroupInfoMap["Charter"] = OSD.FromString(charter); + GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); + GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); + GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); + GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); + GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); + GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); + + SimianAddGeneric(groupID, "Group", GroupName, GroupInfoMap); + } + + } + + + public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + string title, ulong powers) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupRoleInfo = new OSDMap(); + GroupRoleInfo["Name"] = OSD.FromString(name); + GroupRoleInfo["Description"] = OSD.FromString(description); + GroupRoleInfo["Title"] = OSD.FromString(title); + GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); + + // TODO: Add security, make sure that requestingAgentID has permision to add roles + SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); + } + + public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // TODO: Add security + + // Can't delete the Everyone Role + if (roleID != UUID.Zero) + { + // Remove all GroupRole Members from Role + Dictionary GroupRoleMembers; + string GroupRoleMemberType = "GroupRole" + groupID.ToString(); + if (SimianGetGenericEntries(GroupRoleMemberType, roleID.ToString(), out GroupRoleMembers)) + { + foreach(UUID UserID in GroupRoleMembers.Keys) + { + EnsureRoleNotSelectedByMember(groupID, roleID, UserID); + + SimianRemoveGenericEntry(UserID, GroupRoleMemberType, roleID.ToString()); + } + } + + // Remove role + SimianRemoveGenericEntry(groupID, "GroupRole", roleID.ToString()); + } + } + + + public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + string title, ulong powers) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // TODO: Security, check that requestingAgentID is allowed to update group roles + + OSDMap GroupRoleInfo; + if (SimianGetGenericEntry(groupID, "GroupRole", roleID.ToString(), out GroupRoleInfo)) + { + if (name != null) + { + GroupRoleInfo["Name"] = OSD.FromString(name); + } + if (description != null) + { + GroupRoleInfo["Description"] = OSD.FromString(description); + } + if (title != null) + { + GroupRoleInfo["Title"] = OSD.FromString(title); + } + GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); + + } + + + SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); + } + + public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupInfoMap = null; + if (groupID != UUID.Zero) + { + if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out GroupInfoMap)) + { + return null; + } + } + else if ((groupName != null) && (groupName != string.Empty)) + { + if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) + { + return null; + } + } + + GroupRecord GroupInfo = new GroupRecord(); + + GroupInfo.GroupID = groupID; + GroupInfo.GroupName = groupName; + GroupInfo.Charter = GroupInfoMap["Charter"].AsString(); + GroupInfo.ShowInList = GroupInfoMap["ShowInList"].AsBoolean(); + GroupInfo.GroupPicture = GroupInfoMap["InsigniaID"].AsUUID(); + GroupInfo.MembershipFee = GroupInfoMap["MembershipFee"].AsInteger(); + GroupInfo.OpenEnrollment = GroupInfoMap["OpenEnrollment"].AsBoolean(); + GroupInfo.AllowPublish = GroupInfoMap["AllowPublish"].AsBoolean(); + GroupInfo.MaturePublish = GroupInfoMap["MaturePublish"].AsBoolean(); + GroupInfo.FounderID = GroupInfoMap["FounderID"].AsUUID(); + GroupInfo.OwnerRoleID = GroupInfoMap["OwnerRoleID"].AsUUID(); + + return GroupInfo; + + } + + public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID groupID, UUID memberID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap groupProfile; + string groupName; + if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out groupProfile)) + { + // GroupProfileData is not nullable + return new GroupProfileData(); + } + + GroupProfileData MemberGroupProfile = new GroupProfileData(); + MemberGroupProfile.GroupID = groupID; + MemberGroupProfile.Name = groupName; + + if (groupProfile["Charter"] != null) + { + MemberGroupProfile.Charter = groupProfile["Charter"].AsString(); + } + + MemberGroupProfile.ShowInList = groupProfile["ShowInList"].AsString() == "1"; + MemberGroupProfile.InsigniaID = groupProfile["InsigniaID"].AsUUID(); + MemberGroupProfile.MembershipFee = groupProfile["MembershipFee"].AsInteger(); + MemberGroupProfile.OpenEnrollment = groupProfile["OpenEnrollment"].AsBoolean(); + MemberGroupProfile.AllowPublish = groupProfile["AllowPublish"].AsBoolean(); + MemberGroupProfile.MaturePublish = groupProfile["MaturePublish"].AsBoolean(); + MemberGroupProfile.FounderID = groupProfile["FounderID"].AsUUID();; + MemberGroupProfile.OwnerRole = groupProfile["OwnerRoleID"].AsUUID(); + + Dictionary Members; + if (SimianGetGenericEntries("GroupMember",groupID.ToString(), out Members)) + { + MemberGroupProfile.GroupMembershipCount = Members.Count; + } + + Dictionary Roles; + if (SimianGetGenericEntries(groupID, "GroupRole", out Roles)) + { + MemberGroupProfile.GroupRolesCount = Roles.Count; + } + + // TODO: Get Group Money balance from somewhere + // group.Money = 0; + + GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, memberID, groupID); + + MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; + MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; + + return MemberGroupProfile; + } + + public void SetAgentActiveGroup(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap ActiveGroup = new OSDMap(); + ActiveGroup.Add("GroupID", OSD.FromUUID(groupID)); + SimianAddGeneric(agentID, "Group", "ActiveGroup", ActiveGroup); + } + + public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupMemberInfo; + if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) + { + GroupMemberInfo = new OSDMap(); + } + + GroupMemberInfo["SelectedRoleID"] = OSD.FromUUID(roleID); + SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); + } + + public void SetAgentGroupInfo(UUID requestingAgentID, UUID agentID, UUID groupID, bool acceptNotices, bool listInProfile) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupMemberInfo; + if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) + { + GroupMemberInfo = new OSDMap(); + } + + GroupMemberInfo["AcceptNotices"] = OSD.FromBoolean(acceptNotices); + GroupMemberInfo["ListInProfile"] = OSD.FromBoolean(listInProfile); + GroupMemberInfo["Contribution"] = OSD.FromInteger(0); + GroupMemberInfo["SelectedRole"] = OSD.FromUUID(UUID.Zero); + SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); + } + + public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap Invite = new OSDMap(); + Invite["AgentID"] = OSD.FromUUID(agentID); + Invite["RoleID"] = OSD.FromUUID(roleID); + + SimianAddGeneric(groupID, "GroupMemberInvite", inviteID.ToString(), Invite); + } + + public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupMemberInvite; + UUID GroupID; + if (!SimianGetFirstGenericEntry("GroupMemberInvite", inviteID.ToString(), out GroupID, out GroupMemberInvite)) + { + return null; + } + + GroupInviteInfo inviteInfo = new GroupInviteInfo(); + inviteInfo.InviteID = inviteID; + inviteInfo.GroupID = GroupID; + inviteInfo.AgentID = GroupMemberInvite["AgentID"].AsUUID(); + inviteInfo.RoleID = GroupMemberInvite["RoleID"].AsUUID(); + + return inviteInfo; + } + + public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupInviteInfo invite = GetAgentToGroupInvite(requestingAgentID, inviteID); + SimianRemoveGenericEntry(invite.GroupID, "GroupMemberInvite", inviteID.ToString()); + } + + public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Setup Agent/Group information + SetAgentGroupInfo(requestingAgentID, AgentID, GroupID, true, true); + + // Add agent to Everyone Group + AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, UUID.Zero); + + // Add agent to Specified Role + AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, RoleID); + + // Set selected role in this group to specified role + SetAgentActiveGroupRole(requestingAgentID, AgentID, GroupID, RoleID); + } + + public void RemoveAgentFromGroup(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // If current active group is the group the agent is being removed from, change their group to UUID.Zero + GroupMembershipData memberActiveMembership = GetAgentActiveMembership(requestingAgentID, agentID); + if (memberActiveMembership.GroupID == groupID) + { + SetAgentActiveGroup(agentID, agentID, UUID.Zero); + } + + // Remove Group Member information for this group + SimianRemoveGenericEntry(agentID, "GroupMember", groupID.ToString()); + + // By using a Simian Generics Type consisting of a prefix and a groupID, + // combined with RoleID as key allows us to get a list of roles a particular member + // of a group is assigned to. + string GroupRoleMemberType = "GroupRole" + groupID.ToString(); + + // Take Agent out of all other group roles + Dictionary GroupRoles; + if (SimianGetGenericEntries(agentID, GroupRoleMemberType, out GroupRoles)) + { + foreach (string roleID in GroupRoles.Keys) + { + SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID); + } + } + } + + public void AddAgentToGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + SimianAddGeneric(agentID, "GroupRole" + groupID.ToString(), roleID.ToString(), new OSDMap()); + } + + public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Cannot remove members from the Everyone Role + if (roleID != UUID.Zero) + { + EnsureRoleNotSelectedByMember(groupID, roleID, agentID); + + string GroupRoleMemberType = "GroupRole" + groupID.ToString(); + SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID.ToString()); + } + } + + public List FindGroups(UUID requestingAgentID, string search) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List findings = new List(); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Type", "Group" }, + { "Key", search }, + { "Fuzzy", "1" } + }; + + + OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)response["Entries"]; + foreach (OSDMap entryMap in entryArray) + { + DirGroupsReplyData data = new DirGroupsReplyData(); + data.groupID = entryMap["OwnerID"].AsUUID(); + data.groupName = entryMap["Key"].AsString(); + + // TODO: is there a better way to do this? + Dictionary Members; + if (SimianGetGenericEntries("GroupMember", data.groupID.ToString(), out Members)) + { + data.members = Members.Count; + } + else + { + data.members = 0; + } + + // TODO: sort results? + // data.searchOrder = order; + + findings.Add(data); + } + } + + + return findings; + } + + public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupMembershipData data = new GroupMembershipData(); + + /////////////////////////////// + // Agent Specific Information: + // + OSDMap UserActiveGroup; + if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) + { + data.Active = UserActiveGroup["GroupID"].AsUUID().Equals(groupID); + } + + OSDMap UserGroupMemberInfo; + if( SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out UserGroupMemberInfo) ) + { + data.AcceptNotices = UserGroupMemberInfo["AcceptNotices"].AsBoolean(); + data.Contribution = UserGroupMemberInfo["Contribution"].AsInteger(); + data.ListInProfile = UserGroupMemberInfo["ListInProfile"].AsBoolean(); + data.ActiveRole = UserGroupMemberInfo["SelectedRoleID"].AsUUID(); + + /////////////////////////////// + // Role Specific Information: + // + + OSDMap GroupRoleInfo; + if( SimianGetGenericEntry(groupID, "GroupRole", data.ActiveRole.ToString(), out GroupRoleInfo) ) + { + data.GroupTitle = GroupRoleInfo["Title"].AsString(); + data.GroupPowers = GroupRoleInfo["Powers"].AsULong(); + } + } + + /////////////////////////////// + // Group Specific Information: + // + OSDMap GroupInfo; + string GroupName; + if( SimianGetFirstGenericEntry(groupID, "Group", out GroupName, out GroupInfo) ) + { + data.GroupID = groupID; + data.AllowPublish = GroupInfo["AllowPublish"].AsBoolean(); + data.Charter = GroupInfo["Charter"].AsString(); + data.FounderID = GroupInfo["FounderID"].AsUUID(); + data.GroupName = GroupName; + data.GroupPicture = GroupInfo["InsigniaID"].AsUUID(); + data.MaturePublish = GroupInfo["MaturePublish"].AsBoolean(); + data.MembershipFee = GroupInfo["MembershipFee"].AsInteger(); + data.OpenEnrollment = GroupInfo["OpenEnrollment"].AsBoolean(); + data.ShowInList = GroupInfo["ShowInList"].AsBoolean(); + } + + return data; + } + + public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID agentID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + UUID GroupID = UUID.Zero; + OSDMap UserActiveGroup; + if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) + { + GroupID = UserActiveGroup["GroupID"].AsUUID(); + } + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Active GroupID : {0}", GroupID.ToString()); + return GetAgentGroupMembership(requestingAgentID, agentID, GroupID); + } + + public List GetAgentGroupMemberships(UUID requestingAgentID, UUID agentID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List memberships = new List(); + + Dictionary GroupMemberShips; + if (SimianGetGenericEntries(agentID, "GroupMember", out GroupMemberShips)) + { + foreach (string key in GroupMemberShips.Keys) + { + memberships.Add(GetAgentGroupMembership(requestingAgentID, agentID, UUID.Parse(key))); + } + } + + return memberships; + } + + public List GetAgentGroupRoles(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List Roles = new List(); + + Dictionary GroupRoles; + if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) + { + Dictionary MemberRoles; + if (SimianGetGenericEntries(agentID, "GroupRole" + groupID.ToString(), out MemberRoles)) + { + foreach (KeyValuePair kvp in MemberRoles) + { + GroupRolesData data = new GroupRolesData(); + data.RoleID = UUID.Parse(kvp.Key); + data.Name = GroupRoles[kvp.Key]["Name"].AsString(); + data.Description = GroupRoles[kvp.Key]["Description"].AsString(); + data.Title = GroupRoles[kvp.Key]["Title"].AsString(); + data.Powers = GroupRoles[kvp.Key]["Powers"].AsULong(); + + Roles.Add(data); + } + } + } + return Roles; + } + + public List GetGroupRoles(UUID requestingAgentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List Roles = new List(); + + Dictionary GroupRoles; + if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) + { + foreach (KeyValuePair role in GroupRoles) + { + GroupRolesData data = new GroupRolesData(); + + data.RoleID = UUID.Parse(role.Key); + + data.Name = role.Value["Name"].AsString(); + data.Description = role.Value["Description"].AsString(); + data.Title = role.Value["Title"].AsString(); + data.Powers = role.Value["Powers"].AsULong(); + + Dictionary GroupRoleMembers; + if (SimianGetGenericEntries("GroupRole" + groupID.ToString(), role.Key, out GroupRoleMembers)) + { + data.Members = GroupRoleMembers.Count; + } + else + { + data.Members = 0; + } + + Roles.Add(data); + } + } + + return Roles; + + } + + + + public List GetGroupMembers(UUID requestingAgentID, UUID GroupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List members = new List(); + + OSDMap GroupInfo; + string GroupName; + UUID GroupOwnerRoleID = UUID.Zero; + if (!SimianGetFirstGenericEntry(GroupID, "Group", out GroupName, out GroupInfo)) + { + return members; + } + GroupOwnerRoleID = GroupInfo["OwnerRoleID"].AsUUID(); + + // Locally cache group roles, since we'll be needing this data for each member + Dictionary GroupRoles; + SimianGetGenericEntries(GroupID, "GroupRole", out GroupRoles); + + // Locally cache list of group owners + Dictionary GroupOwners; + SimianGetGenericEntries("GroupRole" + GroupID.ToString(), GroupOwnerRoleID.ToString(), out GroupOwners); + + + Dictionary GroupMembers; + if (SimianGetGenericEntries("GroupMember", GroupID.ToString(), out GroupMembers)) + { + foreach (KeyValuePair member in GroupMembers) + { + GroupMembersData data = new GroupMembersData(); + + data.AgentID = member.Key; + + UUID SelectedRoleID = member.Value["SelectedRoleID"].AsUUID(); + + data.AcceptNotices = member.Value["AcceptNotices"].AsBoolean(); + data.ListInProfile = member.Value["ListInProfile"].AsBoolean(); + data.Contribution = member.Value["Contribution"].AsInteger(); + + data.IsOwner = GroupOwners.ContainsKey(member.Key); + + OSDMap GroupRoleInfo = GroupRoles[SelectedRoleID.ToString()]; + data.Title = GroupRoleInfo["Title"].AsString(); + data.AgentPowers = GroupRoleInfo["Powers"].AsULong(); + + members.Add(data); + } + } + + return members; + + } + + public List GetGroupRoleMembers(UUID requestingAgentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List members = new List(); + + Dictionary GroupRoles; + if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) + { + foreach( KeyValuePair Role in GroupRoles ) + { + Dictionary GroupRoleMembers; + if( SimianGetGenericEntries("GroupRole"+groupID.ToString(), Role.Key, out GroupRoleMembers) ) + { + foreach( KeyValuePair GroupRoleMember in GroupRoleMembers ) + { + GroupRoleMembersData data = new GroupRoleMembersData(); + + data.MemberID = GroupRoleMember.Key; + data.RoleID = UUID.Parse(Role.Key); + + members.Add(data); + } + } + } + } + + return members; + } + + public List GetGroupNotices(UUID requestingAgentID, UUID GroupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List values = new List(); + + Dictionary Notices; + if (SimianGetGenericEntries(GroupID, "GroupNotice", out Notices)) + { + foreach (KeyValuePair Notice in Notices) + { + GroupNoticeData data = new GroupNoticeData(); + data.NoticeID = UUID.Parse(Notice.Key); + data.Timestamp = Notice.Value["TimeStamp"].AsUInteger(); + data.FromName = Notice.Value["FromName"].AsString(); + data.Subject = Notice.Value["Subject"].AsString(); + data.HasAttachment = Notice.Value["BinaryBucket"].AsBinary().Length > 0; + + //TODO: Figure out how to get this + data.AssetType = 0; + + values.Add(data); + } + } + + return values; + + } + public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupNotice; + UUID GroupID; + if (SimianGetFirstGenericEntry("GroupNotice", noticeID.ToString(), out GroupID, out GroupNotice)) + { + GroupNoticeInfo data = new GroupNoticeInfo(); + data.GroupID = GroupID; + data.Message = GroupNotice["Message"].AsString(); + data.BinaryBucket = GroupNotice["BinaryBucket"].AsBinary(); + data.noticeData.NoticeID = noticeID; + data.noticeData.Timestamp = GroupNotice["TimeStamp"].AsUInteger(); + data.noticeData.FromName = GroupNotice["FromName"].AsString(); + data.noticeData.Subject = GroupNotice["Subject"].AsString(); + data.noticeData.HasAttachment = data.BinaryBucket.Length > 0; + data.noticeData.AssetType = 0; + + if (data.Message == null) + { + data.Message = string.Empty; + } + + return data; + } + return null; + } + public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap Notice = new OSDMap(); + Notice["TimeStamp"] = OSD.FromUInteger((uint)Util.UnixTimeSinceEpoch()); + Notice["FromName"] = OSD.FromString(fromName); + Notice["Subject"] = OSD.FromString(subject); + Notice["Message"] = OSD.FromString(message); + Notice["BinaryBucket"] = OSD.FromBinary(binaryBucket); + + SimianAddGeneric(groupID, "GroupNotice", noticeID.ToString(), Notice); + + } + #endregion + + + private void EnsureRoleNotSelectedByMember(UUID groupID, UUID roleID, UUID userID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // If member's SelectedRole is roleID, change their selected role to Everyone + // before removing them from the role + OSDMap UserGroupInfo; + if (SimianGetGenericEntry(userID, "GroupMember", groupID.ToString(), out UserGroupInfo)) + { + if (UserGroupInfo["SelectedRoleID"].AsUUID() == roleID) + { + UserGroupInfo["SelectedRoleID"] = OSD.FromUUID(UUID.Zero); + } + SimianAddGeneric(userID, "GroupMember", groupID.ToString(), UserGroupInfo); + } + } + + + #region Simian Util Methods + private bool SimianAddGeneric(UUID ownerID, string type, string key, OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); + + string value = OSDParser.SerializeJsonString(map); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] value: {0}", value); + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "AddGeneric" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type }, + { "Key", key }, + { "Value", value} + }; + + + OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); + if (Response["Success"].AsBoolean()) + { + return true; + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, Response["Message"]); + return false; + } + } + + /// + /// Returns the first of possibly many entries for Owner/Type pair + /// + private bool SimianGetFirstGenericEntry(UUID ownerID, string type, out string key, out OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type); + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type } + }; + + + OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); + if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)Response["Entries"]; + if (entryArray.Count >= 1) + { + OSDMap entryMap = entryArray[0] as OSDMap; + key = entryMap["Key"].AsString(); + map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + + return true; + } + else + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); + } + key = null; + map = null; + return false; + } + private bool SimianGetFirstGenericEntry(string type, string key, out UUID ownerID, out OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); + + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Type", type }, + { "Key", key} + }; + + + OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); + if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)Response["Entries"]; + if (entryArray.Count >= 1) + { + OSDMap entryMap = entryArray[0] as OSDMap; + ownerID = entryMap["OwnerID"].AsUUID(); + map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + + return true; + } + else + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); + } + ownerID = UUID.Zero; + map = null; + return false; + } + + private bool SimianGetGenericEntry(UUID ownerID, string type, string key, out OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type }, + { "Key", key} + }; + + + OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); + if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)Response["Entries"]; + if (entryArray.Count == 1) + { + OSDMap entryMap = entryArray[0] as OSDMap; + key = entryMap["Key"].AsString(); + map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + + return true; + } + else + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); + } + map = null; + return false; + } + + private bool SimianGetGenericEntries(UUID ownerID, string type, out Dictionary maps) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name,ownerID, type); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type } + }; + + + + OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + maps = new Dictionary(); + + OSDArray entryArray = (OSDArray)response["Entries"]; + foreach (OSDMap entryMap in entryArray) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + maps.Add(entryMap["Key"].AsString(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); + } + if(maps.Count == 0) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + + return true; + } + else + { + maps = null; + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", response["Message"]); + } + return false; + } + private bool SimianGetGenericEntries(string type, string key, out Dictionary maps) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Type", type }, + { "Key", key } + }; + + + + OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + maps = new Dictionary(); + + OSDArray entryArray = (OSDArray)response["Entries"]; + foreach (OSDMap entryMap in entryArray) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + maps.Add(entryMap["OwnerID"].AsUUID(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); + } + if (maps.Count == 0) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + return true; + } + else + { + maps = null; + m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR]: Error retrieving group info ({0})", response["Message"]); + } + return false; + } + + private bool SimianRemoveGenericEntry(UUID ownerID, string type, string key) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "RemoveGeneric" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type }, + { "Key", key } + }; + + + OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); + if (response["Success"].AsBoolean()) + { + return true; + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, response["Message"]); + return false; + } + } + #endregion + } + +} + diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 964d0bb..ab343c8 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -40,16 +40,16 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; +using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class XmlRpcGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | GroupPowers.Accountable | @@ -68,6 +68,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private string m_groupReadKey = string.Empty; private string m_groupWriteKey = string.Empty; + private IUserAccountService m_accountService = null; + #region IRegionModuleBase Members @@ -118,6 +120,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty); m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty); + + + // If we got all the config options we need, lets start'er'up m_connectorEnabled = true; } @@ -131,13 +136,24 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) { if (m_connectorEnabled) + { + + if (m_accountService == null) + { + m_accountService = scene.UserAccountService; + } + + scene.RegisterModuleInterface(this); + } } public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene) { if (scene.RequestModuleInterface() == this) + { scene.UnregisterModuleInterface(this); + } } public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene) @@ -157,14 +173,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion - - #region IGroupsServicesConnector Members /// /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. /// - public UUID CreateGroup(GroupRequestID requestID, string name, string charter, bool showInList, UUID insigniaID, + public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID) { @@ -236,7 +250,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - Hashtable respData = XmlRpcCall(requestID, "groups.createGroup", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param); if (respData.Contains("error")) { @@ -248,7 +262,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return UUID.Parse((string)respData["GroupID"]); } - public void UpdateGroup(GroupRequestID requestID, UUID groupID, string charter, bool showInList, + public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { @@ -262,10 +276,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["AllowPublish"] = allowPublish == true ? 1 : 0; param["MaturePublish"] = maturePublish == true ? 1 : 0; - XmlRpcCall(requestID, "groups.updateGroup", param); + XmlRpcCall(requestingAgentID, "groups.updateGroup", param); } - public void AddGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, + public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -276,19 +290,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["Title"] = title; param["Powers"] = powers.ToString(); - XmlRpcCall(requestID, "groups.addRoleToGroup", param); + XmlRpcCall(requestingAgentID, "groups.addRoleToGroup", param); } - public void RemoveGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID) + public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) { Hashtable param = new Hashtable(); param["GroupID"] = groupID.ToString(); param["RoleID"] = roleID.ToString(); - XmlRpcCall(requestID, "groups.removeRoleFromGroup", param); + XmlRpcCall(requestingAgentID, "groups.removeRoleFromGroup", param); } - public void UpdateGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, + public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -308,10 +322,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } param["Powers"] = powers.ToString(); - XmlRpcCall(requestID, "groups.updateGroupRole", param); + XmlRpcCall(requestingAgentID, "groups.updateGroupRole", param); } - public GroupRecord GetGroupRecord(GroupRequestID requestID, UUID GroupID, string GroupName) + public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID GroupID, string GroupName) { Hashtable param = new Hashtable(); if (GroupID != UUID.Zero) @@ -323,7 +337,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["Name"] = GroupName.ToString(); } - Hashtable respData = XmlRpcCall(requestID, "groups.getGroup", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param); if (respData.Contains("error")) { @@ -334,12 +348,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public GroupProfileData GetMemberGroupProfile(GroupRequestID requestID, UUID GroupID, UUID AgentID) + public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroup", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param); if (respData.Contains("error")) { @@ -347,38 +361,35 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return new GroupProfileData(); } - GroupMembershipData MemberInfo = GetAgentGroupMembership(requestID, AgentID, GroupID); + GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, AgentID, GroupID); GroupProfileData MemberGroupProfile = GroupProfileHashtableToGroupProfileData(respData); MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; return MemberGroupProfile; - } - - - public void SetAgentActiveGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public void SetAgentActiveGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - XmlRpcCall(requestID, "groups.setAgentActiveGroup", param); + XmlRpcCall(requestingAgentID, "groups.setAgentActiveGroup", param); } - public void SetAgentActiveGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["SelectedRoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.setAgentGroupInfo", param); + XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param); } - public void SetAgentGroupInfo(GroupRequestID requestID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) + public void SetAgentGroupInfo(UUID requestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); @@ -386,11 +397,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["AcceptNotices"] = AcceptNotices ? "1" : "0"; param["ListInProfile"] = ListInProfile ? "1" : "0"; - XmlRpcCall(requestID, "groups.setAgentGroupInfo", param); + XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param); } - public void AddAgentToGroupInvite(GroupRequestID requestID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) + public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); @@ -398,16 +409,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["RoleID"] = roleID.ToString(); param["GroupID"] = groupID.ToString(); - XmlRpcCall(requestID, "groups.addAgentToGroupInvite", param); + XmlRpcCall(requestingAgentID, "groups.addAgentToGroupInvite", param); } - public GroupInviteInfo GetAgentToGroupInvite(GroupRequestID requestID, UUID inviteID) + public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentToGroupInvite", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentToGroupInvite", param); if (respData.Contains("error")) { @@ -423,60 +434,59 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return inviteInfo; } - public void RemoveAgentToGroupInvite(GroupRequestID requestID, UUID inviteID) + public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); - XmlRpcCall(requestID, "groups.removeAgentToGroupInvite", param); + XmlRpcCall(requestingAgentID, "groups.removeAgentToGroupInvite", param); } - public void AddAgentToGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.addAgentToGroup", param); + XmlRpcCall(requestingAgentID, "groups.addAgentToGroup", param); } - public void RemoveAgentFromGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public void RemoveAgentFromGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - XmlRpcCall(requestID, "groups.removeAgentFromGroup", param); + XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroup", param); } - public void AddAgentToGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void AddAgentToGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.addAgentToGroupRole", param); + XmlRpcCall(requestingAgentID, "groups.addAgentToGroupRole", param); } - public void RemoveAgentFromGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.removeAgentFromGroupRole", param); + XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroupRole", param); } - - public List FindGroups(GroupRequestID requestID, string search) + public List FindGroups(UUID requestingAgentID, string search) { Hashtable param = new Hashtable(); param["Search"] = search; - Hashtable respData = XmlRpcCall(requestID, "groups.findGroups", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.findGroups", param); List findings = new List(); @@ -498,13 +508,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return findings; } - public GroupMembershipData GetAgentGroupMembership(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentGroupMembership", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMembership", param); if (respData.Contains("error")) { @@ -516,12 +526,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return data; } - public GroupMembershipData GetAgentActiveMembership(GroupRequestID requestID, UUID AgentID) + public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID AgentID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentActiveMembership", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentActiveMembership", param); if (respData.Contains("error")) { @@ -531,13 +541,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return HashTableToGroupMembershipData(respData); } - - public List GetAgentGroupMemberships(GroupRequestID requestID, UUID AgentID) + public List GetAgentGroupMemberships(UUID requestingAgentID, UUID AgentID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentGroupMemberships", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMemberships", param); List memberships = new List(); @@ -552,13 +561,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return memberships; } - public List GetAgentGroupRoles(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public List GetAgentGroupRoles(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentRoles", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentRoles", param); List Roles = new List(); @@ -584,12 +593,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public List GetGroupRoles(GroupRequestID requestID, UUID GroupID) + public List GetGroupRoles(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupRoles", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoles", param); List Roles = new List(); @@ -617,12 +626,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - public List GetGroupMembers(GroupRequestID requestID, UUID GroupID) + public List GetGroupMembers(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupMembers", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupMembers", param); List members = new List(); @@ -650,12 +659,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public List GetGroupRoleMembers(GroupRequestID requestID, UUID GroupID) + public List GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupRoleMembers", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoleMembers", param); List members = new List(); @@ -674,12 +683,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return members; } - public List GetGroupNotices(GroupRequestID requestID, UUID GroupID) + public List GetGroupNotices(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupNotices", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotices", param); List values = new List(); @@ -701,12 +710,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return values; } - public GroupNoticeInfo GetGroupNotice(GroupRequestID requestID, UUID noticeID) + public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) { Hashtable param = new Hashtable(); param["NoticeID"] = noticeID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupNotice", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param); if (respData.Contains("error")) @@ -732,7 +741,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return data; } - public void AddGroupNotice(GroupRequestID requestID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) + public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) { string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, ""); @@ -745,7 +754,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["BinaryBucket"] = binBucket; param["TimeStamp"] = ((uint)Util.UnixTimeSinceEpoch()).ToString(); - XmlRpcCall(requestID, "groups.addGroupNotice", param); + XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param); } #endregion @@ -778,7 +787,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private GroupRecord GroupProfileHashtableToGroupRecord(Hashtable groupProfile) { - GroupRecord group = new GroupRecord(); group.GroupID = UUID.Parse((string)groupProfile["GroupID"]); group.GroupName = groupProfile["Name"].ToString(); @@ -797,6 +805,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return group; } + private static GroupMembershipData HashTableToGroupMembershipData(Hashtable respData) { GroupMembershipData data = new GroupMembershipData(); @@ -829,6 +838,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups data.MembershipFee = int.Parse((string)respData["MembershipFee"]); data.OpenEnrollment = ((string)respData["OpenEnrollment"] == "1"); data.ShowInList = ((string)respData["ShowInList"] == "1"); + return data; } @@ -837,15 +847,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Encapsulate the XmlRpc call to standardize security and error handling. /// - private Hashtable XmlRpcCall(GroupRequestID requestID, string function, Hashtable param) + private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param) { - if (requestID == null) - { - requestID = new GroupRequestID(); - } - param.Add("RequestingAgentID", requestID.AgentID.ToString()); - param.Add("RequestingAgentUserService", requestID.UserServiceURL); - param.Add("RequestingSessionID", requestID.SessionID.ToString()); + string UserService; + UUID SessionID; + GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); + param.Add("requestingAgentID", requestingAgentID.ToString()); + param.Add("RequestingAgentUserService", UserService); + param.Add("RequestingSessionID", SessionID.ToString()); param.Add("ReadKey", m_groupReadKey); @@ -936,15 +945,49 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } + + /// + /// Group Request Tokens are an attempt to allow the groups service to authenticate + /// requests. Currently uses UserService, AgentID, and SessionID + /// TODO: Find a better way to do this. + /// + /// + /// + private void GetClientGroupRequestID(UUID AgentID, out string UserServiceURL, out UUID SessionID) + { + UserServiceURL = ""; + SessionID = UUID.Zero; - } - public class GroupNoticeInfo - { - public GroupNoticeData noticeData = new GroupNoticeData(); - public UUID GroupID = UUID.Zero; - public string Message = string.Empty; - public byte[] BinaryBucket = new byte[0]; + // Need to rework this based on changes to User Services + /* + UserAccount userAccount = m_accountService.GetUserAccount(UUID.Zero,AgentID); + if (userAccount == null) + { + // This should be impossible. If I've been passed a reference to a client + // that client should be registered with the UserService. So something + // is horribly wrong somewhere. + + m_log.WarnFormat("[GROUPS]: Could not find a UserServiceURL for {0}", AgentID); + + } + else if (userProfile is ForeignUserProfileData) + { + // They aren't from around here + ForeignUserProfileData fupd = (ForeignUserProfileData)userProfile; + UserServiceURL = fupd.UserServerURI; + SessionID = fupd.CurrentAgent.SessionID; + + } + else + { + // They're a local user, use this: + UserServiceURL = m_commManager.NetworkServersInfo.UserURL; + SessionID = userProfile.CurrentAgent.SessionID; + } + */ + } + } } -- cgit v1.1 From 6fdd5bfe2d0ac1313d94466b5c8a87ef07768f29 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 5 May 2010 16:03:20 +0100 Subject: Revert "Patch from mcortez: Update groups, add ALPHA Siman grid connector for groups" The patch was for 0.7 This reverts commit 608bb0dfefbbc97aded6d1357dd9d350053411fb. --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 341 +++--- .../XmlRpcGroups/IGroupsServicesConnector.cs | 62 +- .../SimianGroupsServicesConnectorModule.cs | 1278 -------------------- .../XmlRpcGroupsServicesConnectorModule.cs | 209 ++-- 4 files changed, 320 insertions(+), 1570 deletions(-) delete mode 100644 OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 6b942cb..8d32e66 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -43,8 +43,6 @@ using OpenSim.Region.CoreModules.Framework.EventQueue; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; - using Caps = OpenSim.Framework.Capabilities.Caps; using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; @@ -89,6 +87,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private IGroupsServicesConnector m_groupData = null; + class GroupRequestIDInfo + { + public GroupRequestID RequestID = new GroupRequestID(); + public DateTime LastUsedTMStamp = DateTime.MinValue; + } + private Dictionary m_clientRequestIDInfo = new Dictionary(); + private const int m_clientRequestIDFlushTimeOut = 300000; // Every 5 minutes + private Timer m_clientRequestIDFlushTimer; + + // Configuration settings private bool m_groupsEnabled = false; private bool m_groupNoticesEnabled = true; @@ -125,6 +133,30 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupNoticesEnabled = groupsConfig.GetBoolean("NoticesEnabled", true); m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); + m_clientRequestIDFlushTimer = new Timer(); + m_clientRequestIDFlushTimer.Interval = m_clientRequestIDFlushTimeOut; + m_clientRequestIDFlushTimer.Elapsed += FlushClientRequestIDInfoCache; + m_clientRequestIDFlushTimer.AutoReset = true; + m_clientRequestIDFlushTimer.Start(); + } + } + + void FlushClientRequestIDInfoCache(object sender, ElapsedEventArgs e) + { + lock (m_clientRequestIDInfo) + { + TimeSpan cacheTimeout = new TimeSpan(0,0, m_clientRequestIDFlushTimeOut / 1000); + UUID[] CurrentKeys = new UUID[m_clientRequestIDInfo.Count]; + foreach (UUID key in CurrentKeys) + { + if (m_clientRequestIDInfo.ContainsKey(key)) + { + if (DateTime.Now - m_clientRequestIDInfo[key].LastUsedTMStamp > cacheTimeout) + { + m_clientRequestIDInfo.Remove(key); + } + } + } } } @@ -202,6 +234,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; if (m_debugEnabled) m_log.Debug("[GROUPS]: Shutting down Groups module."); + + m_clientRequestIDFlushTimer.Stop(); } public Type ReplaceableInterface @@ -238,7 +272,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Used for Notices and Group Invites/Accept/Reject client.OnInstantMessage += OnInstantMessage; - // Send client thier groups information. + lock (m_clientRequestIDInfo) + { + if (m_clientRequestIDInfo.ContainsKey(client.AgentId)) + { + // flush any old RequestID information + m_clientRequestIDInfo.Remove(client.AgentId); + } + } SendAgentGroupDataUpdate(client, client.AgentId); } @@ -246,7 +287,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray(); + //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetClientGroupRequestID(remoteClient), avatarID).ToArray(); GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); } @@ -285,17 +326,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } */ + void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart) { if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups) { - if (m_debugEnabled) - m_log.DebugFormat( - "[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", - System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); + if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); // TODO: This currently ignores pretty much all the query flags including Mature and sort order - remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentID(remoteClient), queryText).ToArray()); + remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetClientGroupRequestID(remoteClient), queryText).ToArray()); } } @@ -309,7 +348,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups string activeGroupName = string.Empty; ulong activeGroupPowers = (ulong)GroupPowers.None; - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient), dataForAgentID); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetClientGroupRequestID(remoteClient), dataForAgentID); if (membership != null) { activeGroupID = membership.GroupID; @@ -322,13 +361,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups SendScenePresenceUpdate(dataForAgentID, activeGroupTitle); } - private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient) + private void HandleUUIDGroupNameRequest(UUID GroupID,IClientAPI remoteClient) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); string GroupName; - GroupRecord group = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null); + GroupRecord group = m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), GroupID, null); if (group != null) { GroupName = group.GroupName; @@ -349,7 +388,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) { UUID inviteID = new UUID(im.imSessionID); - GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); + GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); if (inviteInfo == null) { @@ -368,7 +407,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received an accept invite notice."); // and the sessionid is the role - m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); + m_groupData.AddAgentToGroup(GetClientGroupRequestID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; @@ -392,14 +431,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // TODO: If the inviter is still online, they need an agent dataupdate // and maybe group membership updates for the invitee - m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); + m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); } // Reject if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received a reject invite notice."); - m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); + m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); } } } @@ -413,7 +452,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } UUID GroupID = new UUID(im.toAgentID); - if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null) != null) + if (m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), GroupID, null) != null) { UUID NoticeID = UUID.Random(); string Subject = im.message.Substring(0, im.message.IndexOf('|')); @@ -457,21 +496,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); + m_groupData.AddGroupNotice(GetClientGroupRequestID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); if (OnNewGroupNotice != null) { OnNewGroupNotice(GroupID, NoticeID); } // Send notice out to everyone that wants notices - foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID)) + foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetClientGroupRequestID(remoteClient), GroupID)) { if (m_debugEnabled) { - UserAccount targetUser = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, member.AgentID); - if (targetUser != null) + UserProfileData targetUserProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(member.AgentID); + if (targetUserProfile != null) { - m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUser.FirstName + " " + targetUser.LastName, member.AcceptNotices); + m_log.DebugFormat("[GROUPS]: Prepping group notice {0} for agent: {1} who Accepts Notices ({2})", NoticeID, targetUserProfile.Name, member.AcceptNotices); } else { @@ -549,25 +588,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public GroupRecord GetGroupRecord(UUID GroupID) { - return m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); + return m_groupData.GetGroupRecord(null, GroupID, null); } - public GroupRecord GetGroupRecord(string name) - { - return m_groupData.GetGroupRecord(UUID.Zero, UUID.Zero, name); - } - public void ActivateGroup(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentActiveGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); + m_groupData.SetAgentActiveGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID); // Changing active group changes title, active powers, all kinds of things // anyone who is in any region that can see this client, should probably be // updated with new group info. At a minimum, they should get ScenePresence // updated with new title. - UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); + UpdateAllClientsWithGroupInfo(remoteClient.AgentId); } /// @@ -577,9 +611,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + GroupRequestID grID = GetClientGroupRequestID(remoteClient); - List agentRoles = m_groupData.GetAgentGroupRoles(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); - GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); + List agentRoles = m_groupData.GetAgentGroupRoles(grID, remoteClient.AgentId, groupID); + GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(grID, remoteClient.AgentId, groupID); List titles = new List(); foreach (GroupRolesData role in agentRoles) @@ -601,15 +636,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public List GroupMembersRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List data = m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), groupID); - - if (m_debugEnabled) - { - foreach (GroupMembersData member in data) - { - m_log.DebugFormat("[GROUPS]: Member({0}) - IsOwner({1})", member.AgentID, member.IsOwner); - } - } + + List data = m_groupData.GetGroupMembers(GetClientGroupRequestID(remoteClient), groupID); return data; @@ -619,25 +647,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List data = m_groupData.GetGroupRoles(GetRequestingAgentID(remoteClient), groupID); + List data = m_groupData.GetGroupRoles(GetClientGroupRequestID(remoteClient), groupID); return data; + } public List GroupRoleMembersRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List data = m_groupData.GetGroupRoleMembers(GetRequestingAgentID(remoteClient), groupID); - - if (m_debugEnabled) - { - foreach (GroupRoleMembersData member in data) - { - m_log.DebugFormat("[GROUPS]: Member({0}) - Role({1})", member.MemberID, member.RoleID); - } - } + List data = m_groupData.GetGroupRoleMembers(GetClientGroupRequestID(remoteClient), groupID); + return data; + + } public GroupProfileData GroupProfileRequest(IClientAPI remoteClient, UUID groupID) @@ -646,16 +670,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupProfileData profile = new GroupProfileData(); + GroupRequestID grID = GetClientGroupRequestID(remoteClient); - GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), groupID, null); if (groupInfo != null) { profile.AllowPublish = groupInfo.AllowPublish; profile.Charter = groupInfo.Charter; profile.FounderID = groupInfo.FounderID; profile.GroupID = groupID; - profile.GroupMembershipCount = m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), groupID).Count; - profile.GroupRolesCount = m_groupData.GetGroupRoles(GetRequestingAgentID(remoteClient), groupID).Count; + profile.GroupMembershipCount = m_groupData.GetGroupMembers(grID, groupID).Count; + profile.GroupRolesCount = m_groupData.GetGroupRoles(grID, groupID).Count; profile.InsigniaID = groupInfo.GroupPicture; profile.MaturePublish = groupInfo.MaturePublish; profile.MembershipFee = groupInfo.MembershipFee; @@ -666,7 +691,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups profile.ShowInList = groupInfo.ShowInList; } - GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); + GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(grID, remoteClient.AgentId, groupID); if (memberInfo != null) { profile.MemberTitle = memberInfo.GroupTitle; @@ -680,46 +705,46 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - return m_groupData.GetAgentGroupMemberships(UUID.Zero, agentID).ToArray(); + return m_groupData.GetAgentGroupMemberships(null, agentID).ToArray(); } public GroupMembershipData GetMembershipData(UUID groupID, UUID agentID) { - if (m_debugEnabled) - m_log.DebugFormat( - "[GROUPS]: {0} called with groupID={1}, agentID={2}", - System.Reflection.MethodBase.GetCurrentMethod().Name, groupID, agentID); + if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - return m_groupData.GetAgentGroupMembership(UUID.Zero, agentID, groupID); + return m_groupData.GetAgentGroupMembership(null, agentID, groupID); } public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - // Note: Permissions checking for modification rights is handled by the Groups Server/Service - m_groupData.UpdateGroup(GetRequestingAgentID(remoteClient), groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); + // TODO: Security Check? + + m_groupData.UpdateGroup(GetClientGroupRequestID(remoteClient), groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); } public void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile) { - // Note: Permissions checking for modification rights is handled by the Groups Server/Service + // TODO: Security Check? if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentGroupInfo(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, acceptNotices, listInProfile); + m_groupData.SetAgentGroupInfo(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, acceptNotices, listInProfile); } public UUID CreateGroup(IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), UUID.Zero, name) != null) + GroupRequestID grID = GetClientGroupRequestID(remoteClient); + + if (m_groupData.GetGroupRecord(grID, UUID.Zero, name) != null) { remoteClient.SendCreateGroupReply(UUID.Zero, false, "A group with the same name already exists."); return UUID.Zero; } // is there is a money module present ? - IMoneyModule money = remoteClient.Scene.RequestModuleInterface(); + IMoneyModule money=remoteClient.Scene.RequestModuleInterface(); if (money != null) { // do the transaction, that is if the agent has got sufficient funds @@ -727,14 +752,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got issuficient funds to create a group."); return UUID.Zero; } - money.ApplyGroupCreationCharge(GetRequestingAgentID(remoteClient)); + money.ApplyGroupCreationCharge(remoteClient.AgentId); } - UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); + UUID groupID = m_groupData.CreateGroup(grID, name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, remoteClient.AgentId); remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); // Update the founder with new group information. - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); return groupID; } @@ -745,7 +770,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // ToDo: check if agent is a member of group and is allowed to see notices? - return m_groupData.GetGroupNotices(GetRequestingAgentID(remoteClient), groupID).ToArray(); + return m_groupData.GetGroupNotices(GetClientGroupRequestID(remoteClient), groupID).ToArray(); } /// @@ -755,7 +780,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(UUID.Zero, avatarID); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(null, avatarID); if (membership != null) { return membership.GroupTitle; @@ -770,13 +795,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentActiveGroupRole(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, titleRoleID); + m_groupData.SetAgentActiveGroupRole(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, titleRoleID); // TODO: Not sure what all is needed here, but if the active group role change is for the group // the client currently has set active, then we need to do a scene presence update too - // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) + // if (m_groupData.GetAgentActiveMembership(remoteClient.AgentId).GroupID == GroupID) - UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); + UpdateAllClientsWithGroupInfo(remoteClient.AgentId); } @@ -786,14 +811,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Security Checks are handled in the Groups Service. + GroupRequestID grID = GetClientGroupRequestID(remoteClient); + switch ((OpenMetaverse.GroupRoleUpdate)updateType) { case OpenMetaverse.GroupRoleUpdate.Create: - m_groupData.AddGroupRole(GetRequestingAgentID(remoteClient), groupID, UUID.Random(), name, description, title, powers); + m_groupData.AddGroupRole(grID, groupID, UUID.Random(), name, description, title, powers); break; case OpenMetaverse.GroupRoleUpdate.Delete: - m_groupData.RemoveGroupRole(GetRequestingAgentID(remoteClient), groupID, roleID); + m_groupData.RemoveGroupRole(grID, groupID, roleID); break; case OpenMetaverse.GroupRoleUpdate.UpdateAll: @@ -804,7 +831,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupPowers gp = (GroupPowers)powers; m_log.DebugFormat("[GROUPS]: Role ({0}) updated with Powers ({1}) ({2})", name, powers.ToString(), gp.ToString()); } - m_groupData.UpdateGroupRole(GetRequestingAgentID(remoteClient), groupID, roleID, name, description, title, powers); + m_groupData.UpdateGroupRole(grID, groupID, roleID, name, description, title, powers); break; case OpenMetaverse.GroupRoleUpdate.NoUpdate: @@ -815,7 +842,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); } public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes) @@ -823,16 +850,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Todo: Security check + GroupRequestID grID = GetClientGroupRequestID(remoteClient); + switch (changes) { case 0: // Add - m_groupData.AddAgentToGroupRole(GetRequestingAgentID(remoteClient), memberID, groupID, roleID); + m_groupData.AddAgentToGroupRole(grID, memberID, groupID, roleID); break; case 1: // Remove - m_groupData.RemoveAgentFromGroupRole(GetRequestingAgentID(remoteClient), memberID, groupID, roleID); + m_groupData.RemoveAgentFromGroupRole(grID, memberID, groupID, roleID); break; default: @@ -841,23 +870,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); } public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupNoticeInfo data = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), groupNoticeID); + GroupRequestID grID = GetClientGroupRequestID(remoteClient); + + GroupNoticeInfo data = m_groupData.GetGroupNotice(grID, groupNoticeID); if (data != null) { - GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(grID, data.GroupID, null); GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; msg.fromAgentID = data.GroupID.Guid; - msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; + msg.toAgentID = remoteClient.AgentId.Guid; msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName; msg.message = data.noticeData.Subject + "|" + data.Message; @@ -869,7 +900,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.RegionID = UUID.Zero.Guid; msg.binaryBucket = data.BinaryBucket; - OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); + OutgoingInstantMessage(msg, remoteClient.AgentId); } } @@ -889,7 +920,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.Position = Vector3.Zero; msg.RegionID = UUID.Zero.Guid; - GroupNoticeInfo info = m_groupData.GetGroupNotice(agentID, groupNoticeID); + GroupNoticeInfo info = m_groupData.GetGroupNotice(null, groupNoticeID); if (info != null) { msg.fromAgentID = info.GroupID.Guid; @@ -916,7 +947,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Send agent information about his groups - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); } public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID) @@ -924,19 +955,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Should check to see if OpenEnrollment, or if there's an outstanding invitation - m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, UUID.Zero); + m_groupData.AddAgentToGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, UUID.Zero); remoteClient.SendJoinGroupReply(groupID, true); // Should this send updates to everyone in the group? - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); } public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.RemoveAgentFromGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); + m_groupData.RemoveAgentFromGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID); remoteClient.SendLeaveGroupReply(groupID, true); @@ -944,32 +975,34 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // SL sends out notifcations to the group messaging session that the person has left // Should this also update everyone who is in the group? - SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); + SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); } public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + GroupRequestID grID = GetClientGroupRequestID(remoteClient); // Todo: Security check? - m_groupData.RemoveAgentFromGroup(GetRequestingAgentID(remoteClient), ejecteeID, groupID); + m_groupData.RemoveAgentFromGroup(grID, ejecteeID, groupID); - remoteClient.SendEjectGroupMemberReply(GetRequestingAgentID(remoteClient), groupID, true); + remoteClient.SendEjectGroupMemberReply(remoteClient.AgentId, groupID, true); - GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(grID, groupID, null); + UserProfileData userProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(ejecteeID); - UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, ejecteeID); - if ((groupInfo == null) || (account == null)) + if ((groupInfo == null) || (userProfile == null)) { return; - } + } + // Send Message to Ejectee GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; - msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; + msg.fromAgentID = remoteClient.AgentId.Guid; // msg.fromAgentID = info.GroupID; msg.toAgentID = ejecteeID.Guid; //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); @@ -995,13 +1028,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; - msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; - msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; + msg.fromAgentID = remoteClient.AgentId.Guid; + msg.toAgentID = remoteClient.AgentId.Guid; msg.timestamp = 0; msg.fromAgentName = remoteClient.Name; - if (account != null) + if (userProfile != null) { - msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", remoteClient.Name, groupInfo.GroupName, account.FirstName + " " + account.LastName); + msg.message = string.Format("{2} has been ejected from '{1}' by {0}.", remoteClient.Name, groupInfo.GroupName, userProfile.Name); } else { @@ -1014,7 +1047,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.Position = Vector3.Zero; msg.RegionID = remoteClient.Scene.RegionInfo.RegionID.Guid; msg.binaryBucket = new byte[0]; - OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); + OutgoingInstantMessage(msg, remoteClient.AgentId); // SL sends out messages to everyone in the group @@ -1028,12 +1061,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Todo: Security check, probably also want to send some kind of notification UUID InviteID = UUID.Random(); + GroupRequestID grid = GetClientGroupRequestID(remoteClient); - m_groupData.AddAgentToGroupInvite(GetRequestingAgentID(remoteClient), InviteID, groupID, roleID, invitedAgentID); + m_groupData.AddAgentToGroupInvite(grid, InviteID, groupID, roleID, invitedAgentID); // Check to see if the invite went through, if it did not then it's possible // the remoteClient did not validate or did not have permission to invite. - GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), InviteID); + GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(grid, InviteID); if (inviteInfo != null) { @@ -1045,7 +1079,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.imSessionID = inviteUUID; - // msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; + // msg.fromAgentID = remoteClient.AgentId.Guid; msg.fromAgentID = groupID.Guid; msg.toAgentID = invitedAgentID.Guid; //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); @@ -1098,6 +1132,57 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return child; } + private GroupRequestID GetClientGroupRequestID(IClientAPI client) + { + if (client == null) + { + return new GroupRequestID(); + } + + lock (m_clientRequestIDInfo) + { + if (!m_clientRequestIDInfo.ContainsKey(client.AgentId)) + { + GroupRequestIDInfo info = new GroupRequestIDInfo(); + info.RequestID.AgentID = client.AgentId; + info.RequestID.SessionID = client.SessionId; + + UserProfileData userProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(client.AgentId); + if (userProfile == null) + { + // This should be impossible. If I've been passed a reference to a client + // that client should be registered with the UserService. So something + // is horribly wrong somewhere. + + m_log.WarnFormat("[GROUPS]: Could not find a user profile for {0} / {1}", client.Name, client.AgentId); + + // Default to local user service and hope for the best? + info.RequestID.UserServiceURL = m_sceneList[0].CommsManager.NetworkServersInfo.UserURL; + + } + else if (userProfile is ForeignUserProfileData) + { + // They aren't from around here + ForeignUserProfileData fupd = (ForeignUserProfileData)userProfile; + info.RequestID.UserServiceURL = fupd.UserServerURI; + } + else + { + // They're a local user, use this: + info.RequestID.UserServiceURL = m_sceneList[0].CommsManager.NetworkServersInfo.UserURL; + } + + m_clientRequestIDInfo.Add(client.AgentId, info); + } + + m_clientRequestIDInfo[client.AgentId].LastUsedTMStamp = DateTime.Now; + + return m_clientRequestIDInfo[client.AgentId].RequestID; + } +// Unreachable code! +// return new GroupRequestID(); + } + /// /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'. /// @@ -1116,7 +1201,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups foreach (GroupMembershipData membership in data) { - if (GetRequestingAgentID(remoteClient) != dataForAgentID) + if (remoteClient.AgentId != dataForAgentID) { if (!membership.ListInProfile) { @@ -1144,18 +1229,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups OSDMap llDataStruct = new OSDMap(3); llDataStruct.Add("AgentData", AgentData); llDataStruct.Add("GroupData", GroupData); - llDataStruct.Add("NewGroupData", NewGroupData); - - if (m_debugEnabled) - { - m_log.InfoFormat("[GROUPS]: {0}", OSDParser.SerializeJsonString(llDataStruct)); - } + llDataStruct.Add("NewGroupData", NewGroupData); IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); if (queue != null) { - queue.Enqueue(EventQueueHelper.buildEvent("AgentGroupDataUpdate", llDataStruct), GetRequestingAgentID(remoteClient)); + queue.Enqueue(EventQueueHelper.buildEvent("AgentGroupDataUpdate", llDataStruct), remoteClient.AgentId); } } @@ -1228,7 +1308,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private GroupMembershipData[] GetProfileListedGroupMemberships(IClientAPI requestingClient, UUID dataForAgentID) { - List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); + List membershipData = m_groupData.GetAgentGroupMemberships(GetClientGroupRequestID(requestingClient), dataForAgentID); GroupMembershipData[] membershipArray; if (requestingClient.AgentId != dataForAgentID) @@ -1250,7 +1330,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); foreach (GroupMembershipData membership in membershipArray) { - m_log.InfoFormat("[GROUPS]: {0} :: {1} - {2} - {3}", dataForAgentID, membership.GroupName, membership.GroupTitle, membership.GroupPowers); + m_log.InfoFormat("[GROUPS]: {0} :: {1} - {2}", dataForAgentID, membership.GroupName, membership.GroupTitle); } } @@ -1262,12 +1342,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // TODO: All the client update functions need to be reexamined because most do too much and send too much stuff - UserAccount account = m_sceneList[0].UserAccountService.GetUserAccount(remoteClient.Scene.RegionInfo.ScopeID, dataForAgentID); + UserProfileData userProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(dataForAgentID); string firstname, lastname; - if (account != null) + if (userProfile != null) { - firstname = account.FirstName; - lastname = account.LastName; + firstname = userProfile.FirstName; + lastname = userProfile.SurName; } else { @@ -1308,24 +1388,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // } - #endregion - - private UUID GetRequestingAgentID(IClientAPI client) - { - UUID requestingAgentID = UUID.Zero; - if (client != null) - { - requestingAgentID = client.AgentId; - } - return requestingAgentID; - } + #endregion } - public class GroupNoticeInfo - { - public GroupNoticeData noticeData = new GroupNoticeData(); - public UUID GroupID = UUID.Zero; - public string Message = string.Empty; - public byte[] BinaryBucket = new byte[0]; - } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs index 6487967..9e0fa2d 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs @@ -36,41 +36,42 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { interface IGroupsServicesConnector { - UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); - void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); - GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName); - List FindGroups(UUID RequestingAgentID, string search); - List GetGroupMembers(UUID RequestingAgentID, UUID GroupID); + UUID CreateGroup(GroupRequestID requestID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); + void UpdateGroup(GroupRequestID requestID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); + GroupRecord GetGroupRecord(GroupRequestID requestID, UUID GroupID, string GroupName); + List FindGroups(GroupRequestID requestID, string search); + List GetGroupMembers(GroupRequestID requestID, UUID GroupID); - void AddGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); - void UpdateGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); - void RemoveGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID); - List GetGroupRoles(UUID RequestingAgentID, UUID GroupID); - List GetGroupRoleMembers(UUID RequestingAgentID, UUID GroupID); + void AddGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); + void UpdateGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); + void RemoveGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID); + List GetGroupRoles(GroupRequestID requestID, UUID GroupID); + List GetGroupRoleMembers(GroupRequestID requestID, UUID GroupID); - void AddAgentToGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); - void RemoveAgentFromGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID); + void AddAgentToGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); + void RemoveAgentFromGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID); - void AddAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID); - GroupInviteInfo GetAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID); - void RemoveAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID); + void AddAgentToGroupInvite(GroupRequestID requestID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID); + GroupInviteInfo GetAgentToGroupInvite(GroupRequestID requestID, UUID inviteID); + void RemoveAgentToGroupInvite(GroupRequestID requestID, UUID inviteID); - void AddAgentToGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); - void RemoveAgentFromGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); - List GetAgentGroupRoles(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - void SetAgentActiveGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - GroupMembershipData GetAgentActiveMembership(UUID RequestingAgentID, UUID AgentID); + void AddAgentToGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); + void RemoveAgentFromGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); + List GetAgentGroupRoles(GroupRequestID requestID, UUID AgentID, UUID GroupID); - void SetAgentActiveGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); - void SetAgentGroupInfo(UUID RequestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile); + void SetAgentActiveGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID); + GroupMembershipData GetAgentActiveMembership(GroupRequestID requestID, UUID AgentID); - GroupMembershipData GetAgentGroupMembership(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - List GetAgentGroupMemberships(UUID RequestingAgentID, UUID AgentID); + void SetAgentActiveGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); + void SetAgentGroupInfo(GroupRequestID requestID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile); - void AddGroupNotice(UUID RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); - GroupNoticeInfo GetGroupNotice(UUID RequestingAgentID, UUID noticeID); - List GetGroupNotices(UUID RequestingAgentID, UUID GroupID); + GroupMembershipData GetAgentGroupMembership(GroupRequestID requestID, UUID AgentID, UUID GroupID); + List GetAgentGroupMemberships(GroupRequestID requestID, UUID AgentID); + + void AddGroupNotice(GroupRequestID requestID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); + GroupNoticeInfo GetGroupNotice(GroupRequestID requestID, UUID noticeID); + List GetGroupNotices(GroupRequestID requestID, UUID GroupID); } public class GroupInviteInfo @@ -80,4 +81,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public UUID AgentID = UUID.Zero; public UUID InviteID = UUID.Zero; } + + public class GroupRequestID + { + public UUID AgentID = UUID.Zero; + public string UserServiceURL = string.Empty; + public UUID SessionID = UUID.Zero; + } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs deleted file mode 100644 index 590753e..0000000 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ /dev/null @@ -1,1278 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Reflection; - -using Nwc.XmlRpc; - -using log4net; -using Mono.Addins; -using Nini.Config; - -using OpenMetaverse; -using OpenMetaverse.StructuredData; - -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Services.Interfaces; - -/*************************************************************************** - * Simian Data Map - * =============== - * - * OwnerID -> Type -> Key - * ----------------------- - * - * UserID -> Group -> ActiveGroup - * + GroupID - * - * UserID -> GroupMember -> GroupID - * + SelectedRoleID [UUID] - * + AcceptNotices [bool] - * + ListInProfile [bool] - * + Contribution [int] - * - * UserID -> GroupRole[GroupID] -> RoleID - * - * GroupID -> Group -> GroupName - * + Charter - * + ShowInList - * + InsigniaID - * + MembershipFee - * + OpenEnrollment - * + AllowPublish - * + MaturePublish - * + FounderID - * + EveryonePowers - * + OwnerRoleID - * + OwnersPowers - * - * GroupID -> GroupRole -> RoleID - * + Name - * + Description - * + Title - * + Powers - * - * GroupID -> GroupMemberInvite -> InviteID - * + AgentID - * + RoleID - * - * GroupID -> GroupNotice -> NoticeID - * + TimeStamp [uint] - * + FromName [string] - * + Subject [string] - * + Message [string] - * + BinaryBucket [byte[]] - * - * */ - -namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups -{ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | - GroupPowers.Accountable | - GroupPowers.JoinChat | - GroupPowers.AllowVoiceChat | - GroupPowers.ReceiveNotices | - GroupPowers.StartProposal | - GroupPowers.VoteOnProposal; - - // Would this be cleaner as (GroupPowers)ulong.MaxValue; - public const GroupPowers m_DefaultOwnerPowers = GroupPowers.Accountable - | GroupPowers.AllowEditLand - | GroupPowers.AllowFly - | GroupPowers.AllowLandmark - | GroupPowers.AllowRez - | GroupPowers.AllowSetHome - | GroupPowers.AllowVoiceChat - | GroupPowers.AssignMember - | GroupPowers.AssignMemberLimited - | GroupPowers.ChangeActions - | GroupPowers.ChangeIdentity - | GroupPowers.ChangeMedia - | GroupPowers.ChangeOptions - | GroupPowers.CreateRole - | GroupPowers.DeedObject - | GroupPowers.DeleteRole - | GroupPowers.Eject - | GroupPowers.FindPlaces - | GroupPowers.Invite - | GroupPowers.JoinChat - | GroupPowers.LandChangeIdentity - | GroupPowers.LandDeed - | GroupPowers.LandDivideJoin - | GroupPowers.LandEdit - | GroupPowers.LandEjectAndFreeze - | GroupPowers.LandGardening - | GroupPowers.LandManageAllowed - | GroupPowers.LandManageBanned - | GroupPowers.LandManagePasses - | GroupPowers.LandOptions - | GroupPowers.LandRelease - | GroupPowers.LandSetSale - | GroupPowers.ModerateChat - | GroupPowers.ObjectManipulate - | GroupPowers.ObjectSetForSale - | GroupPowers.ReceiveNotices - | GroupPowers.RemoveMember - | GroupPowers.ReturnGroupOwned - | GroupPowers.ReturnGroupSet - | GroupPowers.ReturnNonGroup - | GroupPowers.RoleProperties - | GroupPowers.SendNotices - | GroupPowers.SetLandingPoint - | GroupPowers.StartProposal - | GroupPowers.VoteOnProposal; - - private bool m_connectorEnabled = false; - - private string m_serviceURL = string.Empty; - - private bool m_debugEnabled = false; - - // private IUserAccountService m_accountService = null; - - - #region IRegionModuleBase Members - - public string Name - { - get { return "SimianGroupsServicesConnector"; } - } - - // this module is not intended to be replaced, but there should only be 1 of them. - public Type ReplaceableInterface - { - get { return null; } - } - - public void Initialise(IConfigSource config) - { - IConfig groupsConfig = config.Configs["Groups"]; - - if (groupsConfig == null) - { - // Do not run this module by default. - return; - } - else - { - // if groups aren't enabled, we're not needed. - // if we're not specified as the connector to use, then we're not wanted - if ((groupsConfig.GetBoolean("Enabled", false) == false) - || (groupsConfig.GetString("ServicesConnectorModule", "Default") != Name)) - { - m_connectorEnabled = false; - return; - } - - m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); - - m_serviceURL = groupsConfig.GetString("XmlRpcServiceURL", string.Empty); - if ((m_serviceURL == null) || - (m_serviceURL == string.Empty)) - { - m_log.ErrorFormat("Please specify a valid Simian Server URL for XmlRpcServiceURL in OpenSim.ini, [Groups]"); - m_connectorEnabled = false; - return; - } - - // If we got all the config options we need, lets start'er'up - m_connectorEnabled = true; - - m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); - - } - } - - public void Close() - { - m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); - } - - public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) - { - if (m_connectorEnabled) - { - scene.RegisterModuleInterface(this); - } - } - - public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene) - { - if (scene.RequestModuleInterface() == this) - { - scene.UnregisterModuleInterface(this); - } - } - - public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene) - { - // TODO: May want to consider listenning for Agent Connections so we can pre-cache group info - // scene.EventManager.OnNewClient += OnNewClient; - } - - #endregion - - #region ISharedRegionModule Members - - public void PostInitialise() - { - // NoOp - } - - #endregion - - - - - #region IGroupsServicesConnector Members - - /// - /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. - /// - public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, - int membershipFee, bool openEnrollment, bool allowPublish, - bool maturePublish, UUID founderID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - UUID GroupID = UUID.Random(); - UUID OwnerRoleID = UUID.Random(); - - OSDMap GroupInfoMap = new OSDMap(); - GroupInfoMap["Charter"] = OSD.FromString(charter); - GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); - GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); - GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); - GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); - GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); - GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); - GroupInfoMap["FounderID"] = OSD.FromUUID(founderID); - GroupInfoMap["EveryonePowers"] = OSD.FromULong((ulong)m_DefaultEveryonePowers); - GroupInfoMap["OwnerRoleID"] = OSD.FromUUID(OwnerRoleID); - GroupInfoMap["OwnersPowers"] = OSD.FromULong((ulong)m_DefaultOwnerPowers); - - if(SimianAddGeneric(GroupID, "Group", name, GroupInfoMap)) - { - AddGroupRole(requestingAgentID, GroupID, UUID.Zero, "Everyone", "Members of " + name, "Member of " + name, (ulong)m_DefaultEveryonePowers); - AddGroupRole(requestingAgentID, GroupID, OwnerRoleID, "Owners", "Owners of " + name, "Owner of " + name, (ulong)m_DefaultOwnerPowers); - - AddAgentToGroup(requestingAgentID, requestingAgentID, GroupID, OwnerRoleID); - - return GroupID; - } - else - { - return UUID.Zero; - } - } - - - public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, - UUID insigniaID, int membershipFee, bool openEnrollment, - bool allowPublish, bool maturePublish) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - // TODO: Check to make sure requestingAgentID has permission to update group - - string GroupName; - OSDMap GroupInfoMap; - if( SimianGetFirstGenericEntry(groupID, "GroupInfo", out GroupName, out GroupInfoMap) ) - { - GroupInfoMap["Charter"] = OSD.FromString(charter); - GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); - GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); - GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); - GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); - GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); - GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); - - SimianAddGeneric(groupID, "Group", GroupName, GroupInfoMap); - } - - } - - - public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, - string title, ulong powers) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupRoleInfo = new OSDMap(); - GroupRoleInfo["Name"] = OSD.FromString(name); - GroupRoleInfo["Description"] = OSD.FromString(description); - GroupRoleInfo["Title"] = OSD.FromString(title); - GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); - - // TODO: Add security, make sure that requestingAgentID has permision to add roles - SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); - } - - public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // TODO: Add security - - // Can't delete the Everyone Role - if (roleID != UUID.Zero) - { - // Remove all GroupRole Members from Role - Dictionary GroupRoleMembers; - string GroupRoleMemberType = "GroupRole" + groupID.ToString(); - if (SimianGetGenericEntries(GroupRoleMemberType, roleID.ToString(), out GroupRoleMembers)) - { - foreach(UUID UserID in GroupRoleMembers.Keys) - { - EnsureRoleNotSelectedByMember(groupID, roleID, UserID); - - SimianRemoveGenericEntry(UserID, GroupRoleMemberType, roleID.ToString()); - } - } - - // Remove role - SimianRemoveGenericEntry(groupID, "GroupRole", roleID.ToString()); - } - } - - - public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, - string title, ulong powers) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // TODO: Security, check that requestingAgentID is allowed to update group roles - - OSDMap GroupRoleInfo; - if (SimianGetGenericEntry(groupID, "GroupRole", roleID.ToString(), out GroupRoleInfo)) - { - if (name != null) - { - GroupRoleInfo["Name"] = OSD.FromString(name); - } - if (description != null) - { - GroupRoleInfo["Description"] = OSD.FromString(description); - } - if (title != null) - { - GroupRoleInfo["Title"] = OSD.FromString(title); - } - GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); - - } - - - SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); - } - - public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupInfoMap = null; - if (groupID != UUID.Zero) - { - if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out GroupInfoMap)) - { - return null; - } - } - else if ((groupName != null) && (groupName != string.Empty)) - { - if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) - { - return null; - } - } - - GroupRecord GroupInfo = new GroupRecord(); - - GroupInfo.GroupID = groupID; - GroupInfo.GroupName = groupName; - GroupInfo.Charter = GroupInfoMap["Charter"].AsString(); - GroupInfo.ShowInList = GroupInfoMap["ShowInList"].AsBoolean(); - GroupInfo.GroupPicture = GroupInfoMap["InsigniaID"].AsUUID(); - GroupInfo.MembershipFee = GroupInfoMap["MembershipFee"].AsInteger(); - GroupInfo.OpenEnrollment = GroupInfoMap["OpenEnrollment"].AsBoolean(); - GroupInfo.AllowPublish = GroupInfoMap["AllowPublish"].AsBoolean(); - GroupInfo.MaturePublish = GroupInfoMap["MaturePublish"].AsBoolean(); - GroupInfo.FounderID = GroupInfoMap["FounderID"].AsUUID(); - GroupInfo.OwnerRoleID = GroupInfoMap["OwnerRoleID"].AsUUID(); - - return GroupInfo; - - } - - public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID groupID, UUID memberID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap groupProfile; - string groupName; - if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out groupProfile)) - { - // GroupProfileData is not nullable - return new GroupProfileData(); - } - - GroupProfileData MemberGroupProfile = new GroupProfileData(); - MemberGroupProfile.GroupID = groupID; - MemberGroupProfile.Name = groupName; - - if (groupProfile["Charter"] != null) - { - MemberGroupProfile.Charter = groupProfile["Charter"].AsString(); - } - - MemberGroupProfile.ShowInList = groupProfile["ShowInList"].AsString() == "1"; - MemberGroupProfile.InsigniaID = groupProfile["InsigniaID"].AsUUID(); - MemberGroupProfile.MembershipFee = groupProfile["MembershipFee"].AsInteger(); - MemberGroupProfile.OpenEnrollment = groupProfile["OpenEnrollment"].AsBoolean(); - MemberGroupProfile.AllowPublish = groupProfile["AllowPublish"].AsBoolean(); - MemberGroupProfile.MaturePublish = groupProfile["MaturePublish"].AsBoolean(); - MemberGroupProfile.FounderID = groupProfile["FounderID"].AsUUID();; - MemberGroupProfile.OwnerRole = groupProfile["OwnerRoleID"].AsUUID(); - - Dictionary Members; - if (SimianGetGenericEntries("GroupMember",groupID.ToString(), out Members)) - { - MemberGroupProfile.GroupMembershipCount = Members.Count; - } - - Dictionary Roles; - if (SimianGetGenericEntries(groupID, "GroupRole", out Roles)) - { - MemberGroupProfile.GroupRolesCount = Roles.Count; - } - - // TODO: Get Group Money balance from somewhere - // group.Money = 0; - - GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, memberID, groupID); - - MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; - MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; - - return MemberGroupProfile; - } - - public void SetAgentActiveGroup(UUID requestingAgentID, UUID agentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap ActiveGroup = new OSDMap(); - ActiveGroup.Add("GroupID", OSD.FromUUID(groupID)); - SimianAddGeneric(agentID, "Group", "ActiveGroup", ActiveGroup); - } - - public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupMemberInfo; - if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) - { - GroupMemberInfo = new OSDMap(); - } - - GroupMemberInfo["SelectedRoleID"] = OSD.FromUUID(roleID); - SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); - } - - public void SetAgentGroupInfo(UUID requestingAgentID, UUID agentID, UUID groupID, bool acceptNotices, bool listInProfile) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupMemberInfo; - if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) - { - GroupMemberInfo = new OSDMap(); - } - - GroupMemberInfo["AcceptNotices"] = OSD.FromBoolean(acceptNotices); - GroupMemberInfo["ListInProfile"] = OSD.FromBoolean(listInProfile); - GroupMemberInfo["Contribution"] = OSD.FromInteger(0); - GroupMemberInfo["SelectedRole"] = OSD.FromUUID(UUID.Zero); - SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); - } - - public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap Invite = new OSDMap(); - Invite["AgentID"] = OSD.FromUUID(agentID); - Invite["RoleID"] = OSD.FromUUID(roleID); - - SimianAddGeneric(groupID, "GroupMemberInvite", inviteID.ToString(), Invite); - } - - public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupMemberInvite; - UUID GroupID; - if (!SimianGetFirstGenericEntry("GroupMemberInvite", inviteID.ToString(), out GroupID, out GroupMemberInvite)) - { - return null; - } - - GroupInviteInfo inviteInfo = new GroupInviteInfo(); - inviteInfo.InviteID = inviteID; - inviteInfo.GroupID = GroupID; - inviteInfo.AgentID = GroupMemberInvite["AgentID"].AsUUID(); - inviteInfo.RoleID = GroupMemberInvite["RoleID"].AsUUID(); - - return inviteInfo; - } - - public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - GroupInviteInfo invite = GetAgentToGroupInvite(requestingAgentID, inviteID); - SimianRemoveGenericEntry(invite.GroupID, "GroupMemberInvite", inviteID.ToString()); - } - - public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // Setup Agent/Group information - SetAgentGroupInfo(requestingAgentID, AgentID, GroupID, true, true); - - // Add agent to Everyone Group - AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, UUID.Zero); - - // Add agent to Specified Role - AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, RoleID); - - // Set selected role in this group to specified role - SetAgentActiveGroupRole(requestingAgentID, AgentID, GroupID, RoleID); - } - - public void RemoveAgentFromGroup(UUID requestingAgentID, UUID agentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // If current active group is the group the agent is being removed from, change their group to UUID.Zero - GroupMembershipData memberActiveMembership = GetAgentActiveMembership(requestingAgentID, agentID); - if (memberActiveMembership.GroupID == groupID) - { - SetAgentActiveGroup(agentID, agentID, UUID.Zero); - } - - // Remove Group Member information for this group - SimianRemoveGenericEntry(agentID, "GroupMember", groupID.ToString()); - - // By using a Simian Generics Type consisting of a prefix and a groupID, - // combined with RoleID as key allows us to get a list of roles a particular member - // of a group is assigned to. - string GroupRoleMemberType = "GroupRole" + groupID.ToString(); - - // Take Agent out of all other group roles - Dictionary GroupRoles; - if (SimianGetGenericEntries(agentID, GroupRoleMemberType, out GroupRoles)) - { - foreach (string roleID in GroupRoles.Keys) - { - SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID); - } - } - } - - public void AddAgentToGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - SimianAddGeneric(agentID, "GroupRole" + groupID.ToString(), roleID.ToString(), new OSDMap()); - } - - public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // Cannot remove members from the Everyone Role - if (roleID != UUID.Zero) - { - EnsureRoleNotSelectedByMember(groupID, roleID, agentID); - - string GroupRoleMemberType = "GroupRole" + groupID.ToString(); - SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID.ToString()); - } - } - - public List FindGroups(UUID requestingAgentID, string search) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List findings = new List(); - - NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "Type", "Group" }, - { "Key", search }, - { "Fuzzy", "1" } - }; - - - OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); - if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) - { - OSDArray entryArray = (OSDArray)response["Entries"]; - foreach (OSDMap entryMap in entryArray) - { - DirGroupsReplyData data = new DirGroupsReplyData(); - data.groupID = entryMap["OwnerID"].AsUUID(); - data.groupName = entryMap["Key"].AsString(); - - // TODO: is there a better way to do this? - Dictionary Members; - if (SimianGetGenericEntries("GroupMember", data.groupID.ToString(), out Members)) - { - data.members = Members.Count; - } - else - { - data.members = 0; - } - - // TODO: sort results? - // data.searchOrder = order; - - findings.Add(data); - } - } - - - return findings; - } - - public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID agentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - GroupMembershipData data = new GroupMembershipData(); - - /////////////////////////////// - // Agent Specific Information: - // - OSDMap UserActiveGroup; - if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) - { - data.Active = UserActiveGroup["GroupID"].AsUUID().Equals(groupID); - } - - OSDMap UserGroupMemberInfo; - if( SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out UserGroupMemberInfo) ) - { - data.AcceptNotices = UserGroupMemberInfo["AcceptNotices"].AsBoolean(); - data.Contribution = UserGroupMemberInfo["Contribution"].AsInteger(); - data.ListInProfile = UserGroupMemberInfo["ListInProfile"].AsBoolean(); - data.ActiveRole = UserGroupMemberInfo["SelectedRoleID"].AsUUID(); - - /////////////////////////////// - // Role Specific Information: - // - - OSDMap GroupRoleInfo; - if( SimianGetGenericEntry(groupID, "GroupRole", data.ActiveRole.ToString(), out GroupRoleInfo) ) - { - data.GroupTitle = GroupRoleInfo["Title"].AsString(); - data.GroupPowers = GroupRoleInfo["Powers"].AsULong(); - } - } - - /////////////////////////////// - // Group Specific Information: - // - OSDMap GroupInfo; - string GroupName; - if( SimianGetFirstGenericEntry(groupID, "Group", out GroupName, out GroupInfo) ) - { - data.GroupID = groupID; - data.AllowPublish = GroupInfo["AllowPublish"].AsBoolean(); - data.Charter = GroupInfo["Charter"].AsString(); - data.FounderID = GroupInfo["FounderID"].AsUUID(); - data.GroupName = GroupName; - data.GroupPicture = GroupInfo["InsigniaID"].AsUUID(); - data.MaturePublish = GroupInfo["MaturePublish"].AsBoolean(); - data.MembershipFee = GroupInfo["MembershipFee"].AsInteger(); - data.OpenEnrollment = GroupInfo["OpenEnrollment"].AsBoolean(); - data.ShowInList = GroupInfo["ShowInList"].AsBoolean(); - } - - return data; - } - - public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID agentID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - UUID GroupID = UUID.Zero; - OSDMap UserActiveGroup; - if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) - { - GroupID = UserActiveGroup["GroupID"].AsUUID(); - } - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Active GroupID : {0}", GroupID.ToString()); - return GetAgentGroupMembership(requestingAgentID, agentID, GroupID); - } - - public List GetAgentGroupMemberships(UUID requestingAgentID, UUID agentID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List memberships = new List(); - - Dictionary GroupMemberShips; - if (SimianGetGenericEntries(agentID, "GroupMember", out GroupMemberShips)) - { - foreach (string key in GroupMemberShips.Keys) - { - memberships.Add(GetAgentGroupMembership(requestingAgentID, agentID, UUID.Parse(key))); - } - } - - return memberships; - } - - public List GetAgentGroupRoles(UUID requestingAgentID, UUID agentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List Roles = new List(); - - Dictionary GroupRoles; - if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) - { - Dictionary MemberRoles; - if (SimianGetGenericEntries(agentID, "GroupRole" + groupID.ToString(), out MemberRoles)) - { - foreach (KeyValuePair kvp in MemberRoles) - { - GroupRolesData data = new GroupRolesData(); - data.RoleID = UUID.Parse(kvp.Key); - data.Name = GroupRoles[kvp.Key]["Name"].AsString(); - data.Description = GroupRoles[kvp.Key]["Description"].AsString(); - data.Title = GroupRoles[kvp.Key]["Title"].AsString(); - data.Powers = GroupRoles[kvp.Key]["Powers"].AsULong(); - - Roles.Add(data); - } - } - } - return Roles; - } - - public List GetGroupRoles(UUID requestingAgentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List Roles = new List(); - - Dictionary GroupRoles; - if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) - { - foreach (KeyValuePair role in GroupRoles) - { - GroupRolesData data = new GroupRolesData(); - - data.RoleID = UUID.Parse(role.Key); - - data.Name = role.Value["Name"].AsString(); - data.Description = role.Value["Description"].AsString(); - data.Title = role.Value["Title"].AsString(); - data.Powers = role.Value["Powers"].AsULong(); - - Dictionary GroupRoleMembers; - if (SimianGetGenericEntries("GroupRole" + groupID.ToString(), role.Key, out GroupRoleMembers)) - { - data.Members = GroupRoleMembers.Count; - } - else - { - data.Members = 0; - } - - Roles.Add(data); - } - } - - return Roles; - - } - - - - public List GetGroupMembers(UUID requestingAgentID, UUID GroupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List members = new List(); - - OSDMap GroupInfo; - string GroupName; - UUID GroupOwnerRoleID = UUID.Zero; - if (!SimianGetFirstGenericEntry(GroupID, "Group", out GroupName, out GroupInfo)) - { - return members; - } - GroupOwnerRoleID = GroupInfo["OwnerRoleID"].AsUUID(); - - // Locally cache group roles, since we'll be needing this data for each member - Dictionary GroupRoles; - SimianGetGenericEntries(GroupID, "GroupRole", out GroupRoles); - - // Locally cache list of group owners - Dictionary GroupOwners; - SimianGetGenericEntries("GroupRole" + GroupID.ToString(), GroupOwnerRoleID.ToString(), out GroupOwners); - - - Dictionary GroupMembers; - if (SimianGetGenericEntries("GroupMember", GroupID.ToString(), out GroupMembers)) - { - foreach (KeyValuePair member in GroupMembers) - { - GroupMembersData data = new GroupMembersData(); - - data.AgentID = member.Key; - - UUID SelectedRoleID = member.Value["SelectedRoleID"].AsUUID(); - - data.AcceptNotices = member.Value["AcceptNotices"].AsBoolean(); - data.ListInProfile = member.Value["ListInProfile"].AsBoolean(); - data.Contribution = member.Value["Contribution"].AsInteger(); - - data.IsOwner = GroupOwners.ContainsKey(member.Key); - - OSDMap GroupRoleInfo = GroupRoles[SelectedRoleID.ToString()]; - data.Title = GroupRoleInfo["Title"].AsString(); - data.AgentPowers = GroupRoleInfo["Powers"].AsULong(); - - members.Add(data); - } - } - - return members; - - } - - public List GetGroupRoleMembers(UUID requestingAgentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List members = new List(); - - Dictionary GroupRoles; - if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) - { - foreach( KeyValuePair Role in GroupRoles ) - { - Dictionary GroupRoleMembers; - if( SimianGetGenericEntries("GroupRole"+groupID.ToString(), Role.Key, out GroupRoleMembers) ) - { - foreach( KeyValuePair GroupRoleMember in GroupRoleMembers ) - { - GroupRoleMembersData data = new GroupRoleMembersData(); - - data.MemberID = GroupRoleMember.Key; - data.RoleID = UUID.Parse(Role.Key); - - members.Add(data); - } - } - } - } - - return members; - } - - public List GetGroupNotices(UUID requestingAgentID, UUID GroupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List values = new List(); - - Dictionary Notices; - if (SimianGetGenericEntries(GroupID, "GroupNotice", out Notices)) - { - foreach (KeyValuePair Notice in Notices) - { - GroupNoticeData data = new GroupNoticeData(); - data.NoticeID = UUID.Parse(Notice.Key); - data.Timestamp = Notice.Value["TimeStamp"].AsUInteger(); - data.FromName = Notice.Value["FromName"].AsString(); - data.Subject = Notice.Value["Subject"].AsString(); - data.HasAttachment = Notice.Value["BinaryBucket"].AsBinary().Length > 0; - - //TODO: Figure out how to get this - data.AssetType = 0; - - values.Add(data); - } - } - - return values; - - } - public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupNotice; - UUID GroupID; - if (SimianGetFirstGenericEntry("GroupNotice", noticeID.ToString(), out GroupID, out GroupNotice)) - { - GroupNoticeInfo data = new GroupNoticeInfo(); - data.GroupID = GroupID; - data.Message = GroupNotice["Message"].AsString(); - data.BinaryBucket = GroupNotice["BinaryBucket"].AsBinary(); - data.noticeData.NoticeID = noticeID; - data.noticeData.Timestamp = GroupNotice["TimeStamp"].AsUInteger(); - data.noticeData.FromName = GroupNotice["FromName"].AsString(); - data.noticeData.Subject = GroupNotice["Subject"].AsString(); - data.noticeData.HasAttachment = data.BinaryBucket.Length > 0; - data.noticeData.AssetType = 0; - - if (data.Message == null) - { - data.Message = string.Empty; - } - - return data; - } - return null; - } - public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap Notice = new OSDMap(); - Notice["TimeStamp"] = OSD.FromUInteger((uint)Util.UnixTimeSinceEpoch()); - Notice["FromName"] = OSD.FromString(fromName); - Notice["Subject"] = OSD.FromString(subject); - Notice["Message"] = OSD.FromString(message); - Notice["BinaryBucket"] = OSD.FromBinary(binaryBucket); - - SimianAddGeneric(groupID, "GroupNotice", noticeID.ToString(), Notice); - - } - #endregion - - - private void EnsureRoleNotSelectedByMember(UUID groupID, UUID roleID, UUID userID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // If member's SelectedRole is roleID, change their selected role to Everyone - // before removing them from the role - OSDMap UserGroupInfo; - if (SimianGetGenericEntry(userID, "GroupMember", groupID.ToString(), out UserGroupInfo)) - { - if (UserGroupInfo["SelectedRoleID"].AsUUID() == roleID) - { - UserGroupInfo["SelectedRoleID"] = OSD.FromUUID(UUID.Zero); - } - SimianAddGeneric(userID, "GroupMember", groupID.ToString(), UserGroupInfo); - } - } - - - #region Simian Util Methods - private bool SimianAddGeneric(UUID ownerID, string type, string key, OSDMap map) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); - - string value = OSDParser.SerializeJsonString(map); - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] value: {0}", value); - - NameValueCollection RequestArgs = new NameValueCollection - { - { "RequestMethod", "AddGeneric" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type }, - { "Key", key }, - { "Value", value} - }; - - - OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); - if (Response["Success"].AsBoolean()) - { - return true; - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, Response["Message"]); - return false; - } - } - - /// - /// Returns the first of possibly many entries for Owner/Type pair - /// - private bool SimianGetFirstGenericEntry(UUID ownerID, string type, out string key, out OSDMap map) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type); - - NameValueCollection RequestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type } - }; - - - OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); - if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) - { - OSDArray entryArray = (OSDArray)Response["Entries"]; - if (entryArray.Count >= 1) - { - OSDMap entryMap = entryArray[0] as OSDMap; - key = entryMap["Key"].AsString(); - map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - - return true; - } - else - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); - } - key = null; - map = null; - return false; - } - private bool SimianGetFirstGenericEntry(string type, string key, out UUID ownerID, out OSDMap map) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); - - - NameValueCollection RequestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "Type", type }, - { "Key", key} - }; - - - OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); - if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) - { - OSDArray entryArray = (OSDArray)Response["Entries"]; - if (entryArray.Count >= 1) - { - OSDMap entryMap = entryArray[0] as OSDMap; - ownerID = entryMap["OwnerID"].AsUUID(); - map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - - return true; - } - else - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); - } - ownerID = UUID.Zero; - map = null; - return false; - } - - private bool SimianGetGenericEntry(UUID ownerID, string type, string key, out OSDMap map) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); - - NameValueCollection RequestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type }, - { "Key", key} - }; - - - OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); - if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) - { - OSDArray entryArray = (OSDArray)Response["Entries"]; - if (entryArray.Count == 1) - { - OSDMap entryMap = entryArray[0] as OSDMap; - key = entryMap["Key"].AsString(); - map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - - return true; - } - else - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); - } - map = null; - return false; - } - - private bool SimianGetGenericEntries(UUID ownerID, string type, out Dictionary maps) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name,ownerID, type); - - NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type } - }; - - - - OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); - if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) - { - maps = new Dictionary(); - - OSDArray entryArray = (OSDArray)response["Entries"]; - foreach (OSDMap entryMap in entryArray) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - maps.Add(entryMap["Key"].AsString(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); - } - if(maps.Count == 0) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - - return true; - } - else - { - maps = null; - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", response["Message"]); - } - return false; - } - private bool SimianGetGenericEntries(string type, string key, out Dictionary maps) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); - - NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "Type", type }, - { "Key", key } - }; - - - - OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); - if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) - { - maps = new Dictionary(); - - OSDArray entryArray = (OSDArray)response["Entries"]; - foreach (OSDMap entryMap in entryArray) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - maps.Add(entryMap["OwnerID"].AsUUID(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); - } - if (maps.Count == 0) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - return true; - } - else - { - maps = null; - m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR]: Error retrieving group info ({0})", response["Message"]); - } - return false; - } - - private bool SimianRemoveGenericEntry(UUID ownerID, string type, string key) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); - - NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "RemoveGeneric" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type }, - { "Key", key } - }; - - - OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); - if (response["Success"].AsBoolean()) - { - return true; - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, response["Message"]); - return false; - } - } - #endregion - } - -} - diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index ab343c8..964d0bb 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -40,16 +40,16 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; -using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; -using OpenSim.Services.Interfaces; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class XmlRpcGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | GroupPowers.Accountable | @@ -68,8 +68,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private string m_groupReadKey = string.Empty; private string m_groupWriteKey = string.Empty; - private IUserAccountService m_accountService = null; - #region IRegionModuleBase Members @@ -120,9 +118,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty); m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty); - - - // If we got all the config options we need, lets start'er'up m_connectorEnabled = true; } @@ -136,24 +131,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) { if (m_connectorEnabled) - { - - if (m_accountService == null) - { - m_accountService = scene.UserAccountService; - } - - scene.RegisterModuleInterface(this); - } } public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene) { if (scene.RequestModuleInterface() == this) - { scene.UnregisterModuleInterface(this); - } } public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene) @@ -173,12 +157,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion + + #region IGroupsServicesConnector Members /// /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. /// - public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, + public UUID CreateGroup(GroupRequestID requestID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID) { @@ -250,7 +236,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param); + Hashtable respData = XmlRpcCall(requestID, "groups.createGroup", param); if (respData.Contains("error")) { @@ -262,7 +248,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return UUID.Parse((string)respData["GroupID"]); } - public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, + public void UpdateGroup(GroupRequestID requestID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { @@ -276,10 +262,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["AllowPublish"] = allowPublish == true ? 1 : 0; param["MaturePublish"] = maturePublish == true ? 1 : 0; - XmlRpcCall(requestingAgentID, "groups.updateGroup", param); + XmlRpcCall(requestID, "groups.updateGroup", param); } - public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + public void AddGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -290,19 +276,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["Title"] = title; param["Powers"] = powers.ToString(); - XmlRpcCall(requestingAgentID, "groups.addRoleToGroup", param); + XmlRpcCall(requestID, "groups.addRoleToGroup", param); } - public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) + public void RemoveGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID) { Hashtable param = new Hashtable(); param["GroupID"] = groupID.ToString(); param["RoleID"] = roleID.ToString(); - XmlRpcCall(requestingAgentID, "groups.removeRoleFromGroup", param); + XmlRpcCall(requestID, "groups.removeRoleFromGroup", param); } - public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + public void UpdateGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -322,10 +308,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } param["Powers"] = powers.ToString(); - XmlRpcCall(requestingAgentID, "groups.updateGroupRole", param); + XmlRpcCall(requestID, "groups.updateGroupRole", param); } - public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID GroupID, string GroupName) + public GroupRecord GetGroupRecord(GroupRequestID requestID, UUID GroupID, string GroupName) { Hashtable param = new Hashtable(); if (GroupID != UUID.Zero) @@ -337,7 +323,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["Name"] = GroupName.ToString(); } - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getGroup", param); if (respData.Contains("error")) { @@ -348,12 +334,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID) + public GroupProfileData GetMemberGroupProfile(GroupRequestID requestID, UUID GroupID, UUID AgentID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getGroup", param); if (respData.Contains("error")) { @@ -361,35 +347,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return new GroupProfileData(); } - GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, AgentID, GroupID); + GroupMembershipData MemberInfo = GetAgentGroupMembership(requestID, AgentID, GroupID); GroupProfileData MemberGroupProfile = GroupProfileHashtableToGroupProfileData(respData); MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; return MemberGroupProfile; + } - public void SetAgentActiveGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) + + + public void SetAgentActiveGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - XmlRpcCall(requestingAgentID, "groups.setAgentActiveGroup", param); + XmlRpcCall(requestID, "groups.setAgentActiveGroup", param); } - public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) + public void SetAgentActiveGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["SelectedRoleID"] = RoleID.ToString(); - XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param); + XmlRpcCall(requestID, "groups.setAgentGroupInfo", param); } - public void SetAgentGroupInfo(UUID requestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) + public void SetAgentGroupInfo(GroupRequestID requestID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); @@ -397,11 +386,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["AcceptNotices"] = AcceptNotices ? "1" : "0"; param["ListInProfile"] = ListInProfile ? "1" : "0"; - XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param); + XmlRpcCall(requestID, "groups.setAgentGroupInfo", param); } - public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) + public void AddAgentToGroupInvite(GroupRequestID requestID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); @@ -409,16 +398,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["RoleID"] = roleID.ToString(); param["GroupID"] = groupID.ToString(); - XmlRpcCall(requestingAgentID, "groups.addAgentToGroupInvite", param); + XmlRpcCall(requestID, "groups.addAgentToGroupInvite", param); } - public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) + public GroupInviteInfo GetAgentToGroupInvite(GroupRequestID requestID, UUID inviteID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentToGroupInvite", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getAgentToGroupInvite", param); if (respData.Contains("error")) { @@ -434,59 +423,60 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return inviteInfo; } - public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) + public void RemoveAgentToGroupInvite(GroupRequestID requestID, UUID inviteID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); - XmlRpcCall(requestingAgentID, "groups.removeAgentToGroupInvite", param); + XmlRpcCall(requestID, "groups.removeAgentToGroupInvite", param); } - public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) + public void AddAgentToGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestingAgentID, "groups.addAgentToGroup", param); + XmlRpcCall(requestID, "groups.addAgentToGroup", param); } - public void RemoveAgentFromGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) + public void RemoveAgentFromGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroup", param); + XmlRpcCall(requestID, "groups.removeAgentFromGroup", param); } - public void AddAgentToGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) + public void AddAgentToGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestingAgentID, "groups.addAgentToGroupRole", param); + XmlRpcCall(requestID, "groups.addAgentToGroupRole", param); } - public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) + public void RemoveAgentFromGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroupRole", param); + XmlRpcCall(requestID, "groups.removeAgentFromGroupRole", param); } - public List FindGroups(UUID requestingAgentID, string search) + + public List FindGroups(GroupRequestID requestID, string search) { Hashtable param = new Hashtable(); param["Search"] = search; - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.findGroups", param); + Hashtable respData = XmlRpcCall(requestID, "groups.findGroups", param); List findings = new List(); @@ -508,13 +498,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return findings; } - public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID AgentID, UUID GroupID) + public GroupMembershipData GetAgentGroupMembership(GroupRequestID requestID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMembership", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getAgentGroupMembership", param); if (respData.Contains("error")) { @@ -526,12 +516,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return data; } - public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID AgentID) + public GroupMembershipData GetAgentActiveMembership(GroupRequestID requestID, UUID AgentID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentActiveMembership", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getAgentActiveMembership", param); if (respData.Contains("error")) { @@ -541,12 +531,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return HashTableToGroupMembershipData(respData); } - public List GetAgentGroupMemberships(UUID requestingAgentID, UUID AgentID) + + public List GetAgentGroupMemberships(GroupRequestID requestID, UUID AgentID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMemberships", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getAgentGroupMemberships", param); List memberships = new List(); @@ -561,13 +552,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return memberships; } - public List GetAgentGroupRoles(UUID requestingAgentID, UUID AgentID, UUID GroupID) + public List GetAgentGroupRoles(GroupRequestID requestID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentRoles", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getAgentRoles", param); List Roles = new List(); @@ -593,12 +584,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public List GetGroupRoles(UUID requestingAgentID, UUID GroupID) + public List GetGroupRoles(GroupRequestID requestID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoles", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getGroupRoles", param); List Roles = new List(); @@ -626,12 +617,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - public List GetGroupMembers(UUID requestingAgentID, UUID GroupID) + public List GetGroupMembers(GroupRequestID requestID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupMembers", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getGroupMembers", param); List members = new List(); @@ -659,12 +650,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public List GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID) + public List GetGroupRoleMembers(GroupRequestID requestID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoleMembers", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getGroupRoleMembers", param); List members = new List(); @@ -683,12 +674,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return members; } - public List GetGroupNotices(UUID requestingAgentID, UUID GroupID) + public List GetGroupNotices(GroupRequestID requestID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotices", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getGroupNotices", param); List values = new List(); @@ -710,12 +701,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return values; } - public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) + public GroupNoticeInfo GetGroupNotice(GroupRequestID requestID, UUID noticeID) { Hashtable param = new Hashtable(); param["NoticeID"] = noticeID.ToString(); - Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param); + Hashtable respData = XmlRpcCall(requestID, "groups.getGroupNotice", param); if (respData.Contains("error")) @@ -741,7 +732,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return data; } - public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) + public void AddGroupNotice(GroupRequestID requestID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) { string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, ""); @@ -754,7 +745,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["BinaryBucket"] = binBucket; param["TimeStamp"] = ((uint)Util.UnixTimeSinceEpoch()).ToString(); - XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param); + XmlRpcCall(requestID, "groups.addGroupNotice", param); } #endregion @@ -787,6 +778,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private GroupRecord GroupProfileHashtableToGroupRecord(Hashtable groupProfile) { + GroupRecord group = new GroupRecord(); group.GroupID = UUID.Parse((string)groupProfile["GroupID"]); group.GroupName = groupProfile["Name"].ToString(); @@ -805,7 +797,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return group; } - private static GroupMembershipData HashTableToGroupMembershipData(Hashtable respData) { GroupMembershipData data = new GroupMembershipData(); @@ -838,7 +829,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups data.MembershipFee = int.Parse((string)respData["MembershipFee"]); data.OpenEnrollment = ((string)respData["OpenEnrollment"] == "1"); data.ShowInList = ((string)respData["ShowInList"] == "1"); - return data; } @@ -847,14 +837,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Encapsulate the XmlRpc call to standardize security and error handling. /// - private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param) + private Hashtable XmlRpcCall(GroupRequestID requestID, string function, Hashtable param) { - string UserService; - UUID SessionID; - GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); - param.Add("requestingAgentID", requestingAgentID.ToString()); - param.Add("RequestingAgentUserService", UserService); - param.Add("RequestingSessionID", SessionID.ToString()); + if (requestID == null) + { + requestID = new GroupRequestID(); + } + param.Add("RequestingAgentID", requestID.AgentID.ToString()); + param.Add("RequestingAgentUserService", requestID.UserServiceURL); + param.Add("RequestingSessionID", requestID.SessionID.ToString()); param.Add("ReadKey", m_groupReadKey); @@ -945,49 +936,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } - - /// - /// Group Request Tokens are an attempt to allow the groups service to authenticate - /// requests. Currently uses UserService, AgentID, and SessionID - /// TODO: Find a better way to do this. - /// - /// - /// - private void GetClientGroupRequestID(UUID AgentID, out string UserServiceURL, out UUID SessionID) - { - UserServiceURL = ""; - SessionID = UUID.Zero; - - - // Need to rework this based on changes to User Services - /* - UserAccount userAccount = m_accountService.GetUserAccount(UUID.Zero,AgentID); - if (userAccount == null) - { - // This should be impossible. If I've been passed a reference to a client - // that client should be registered with the UserService. So something - // is horribly wrong somewhere. - - m_log.WarnFormat("[GROUPS]: Could not find a UserServiceURL for {0}", AgentID); - } - else if (userProfile is ForeignUserProfileData) - { - // They aren't from around here - ForeignUserProfileData fupd = (ForeignUserProfileData)userProfile; - UserServiceURL = fupd.UserServerURI; - SessionID = fupd.CurrentAgent.SessionID; + } - } - else - { - // They're a local user, use this: - UserServiceURL = m_commManager.NetworkServersInfo.UserURL; - SessionID = userProfile.CurrentAgent.SessionID; - } - */ - } - + public class GroupNoticeInfo + { + public GroupNoticeData noticeData = new GroupNoticeData(); + public UUID GroupID = UUID.Zero; + public string Message = string.Empty; + public byte[] BinaryBucket = new byte[0]; } } -- cgit v1.1 From 8a69070b513f821bf295c32ad771d5f5009bec61 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 Apr 2010 16:14:02 -0700 Subject: back port groups changes --- .../Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 266 ++-- .../Avatar/XmlRpcGroups/GroupsModule.cs | 299 ++--- .../XmlRpcGroups/IGroupsServicesConnector.cs | 66 +- .../SimianGroupsServicesConnectorModule.cs | 1329 ++++++++++++++++++++ .../XmlRpcGroupsServicesConnectorModule.cs | 281 +++-- bin/OpenSim.ini.example | 14 +- bin/config-include/GridCommon.ini.example | 6 + 7 files changed, 1815 insertions(+), 446 deletions(-) create mode 100644 OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 00fe5df..06aad91 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -28,41 +28,30 @@ using System; using System.Collections.Generic; using System.Reflection; - - using log4net; using Mono.Addins; using Nini.Config; - using OpenMetaverse; using OpenMetaverse.StructuredData; - using OpenSim.Framework; using OpenSim.Region.CoreModules.Framework.EventQueue; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; - using Caps = OpenSim.Framework.Capabilities.Caps; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class GroupsMessagingModule : ISharedRegionModule + public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_sceneList = new List(); private IMessageTransferModule m_msgTransferModule = null; - private IGroupsModule m_groupsModule = null; - - // TODO: Move this off to the Groups Server - public Dictionary> m_agentsInGroupSession = new Dictionary>(); - public Dictionary> m_agentsDroppedSession = new Dictionary>(); - + private IGroupsServicesConnector m_groupData = null; // Config Options private bool m_groupMessagingEnabled = false; @@ -108,8 +97,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(Scene scene) { - // NoOp + if (!m_groupMessagingEnabled) + return; + + scene.RegisterModuleInterface(this); } + public void RegionLoaded(Scene scene) { if (!m_groupMessagingEnabled) @@ -117,12 +110,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupsModule = scene.RequestModuleInterface(); + m_groupData = scene.RequestModuleInterface(); // No groups module, no groups messaging - if (m_groupsModule == null) + if (m_groupData == null) { - m_log.Error("[GROUPS-MESSAGING]: Could not get IGroupsModule, GroupsMessagingModule is now disabled."); + m_log.Error("[GROUPS-MESSAGING]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled."); Close(); m_groupMessagingEnabled = false; return; @@ -144,7 +137,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - } public void RemoveRegion(Scene scene) @@ -172,7 +164,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_sceneList.Clear(); - m_groupsModule = null; + m_groupData = null; m_msgTransferModule = null; } @@ -197,6 +189,75 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion + /// + /// Not really needed, but does confirm that the group exists. + /// + public bool StartGroupChatSession(UUID agentID, UUID groupID) + { + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID, groupID, null); + + if (groupInfo != null) + { + return true; + } + else + { + return false; + } + } + + public void SendMessageToGroup(GridInstantMessage im, UUID groupID) + { + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + + foreach (GroupMembersData member in m_groupData.GetGroupMembers(UUID.Zero, groupID)) + { + if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) + { + // Don't deliver messages to people who have dropped this session + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); + continue; + } + + // Copy Message + GridInstantMessage msg = new GridInstantMessage(); + msg.imSessionID = groupID.Guid; + msg.fromAgentName = im.fromAgentName; + msg.message = im.message; + msg.dialog = im.dialog; + msg.offline = im.offline; + msg.ParentEstateID = im.ParentEstateID; + msg.Position = im.Position; + msg.RegionID = im.RegionID; + msg.binaryBucket = im.binaryBucket; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + + msg.fromAgentID = im.fromAgentID; + msg.fromGroup = true; + + msg.toAgentID = member.AgentID.Guid; + + IClientAPI client = GetActiveClient(member.AgentID); + if (client == null) + { + // If they're not local, forward across the grid + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); + m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); + } + else + { + // Deliver locally, directly + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); + ProcessMessageFromGroupSession(msg); + } + } + } + #region SimGridEventHandlers private void OnNewClient(IClientAPI client) @@ -236,42 +297,46 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); + UUID AgentID = new UUID(msg.fromAgentID); + UUID GroupID = new UUID(msg.imSessionID); + switch (msg.dialog) { case (byte)InstantMessageDialog.SessionAdd: - AddAgentToGroupSession(msg.fromAgentID, msg.imSessionID); + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); break; case (byte)InstantMessageDialog.SessionDrop: - RemoveAgentFromGroupSession(msg.fromAgentID, msg.imSessionID); + m_groupData.AgentDroppedFromGroupChatSession(AgentID, GroupID); break; case (byte)InstantMessageDialog.SessionSend: - if (!m_agentsInGroupSession.ContainsKey(msg.toAgentID) - && !m_agentsDroppedSession.ContainsKey(msg.toAgentID)) + if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID) + && !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID, GroupID) + ) { // Agent not in session and hasn't dropped from session // Add them to the session for now, and Invite them - AddAgentToGroupSession(msg.toAgentID, msg.imSessionID); + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); UUID toAgentID = new UUID(msg.toAgentID); IClientAPI activeClient = GetActiveClient(toAgentID); if (activeClient != null) { - UUID groupID = new UUID(msg.fromAgentID); - - GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID); + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); if (groupInfo != null) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message"); // Force? open the group session dialog??? + // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); IEventQueue eq = activeClient.Scene.RequestModuleInterface(); eq.ChatterboxInvitation( - groupID + GroupID , groupInfo.GroupName , new UUID(msg.fromAgentID) - , msg.message, new UUID(msg.toAgentID) + , msg.message + , new UUID(msg.toAgentID) , msg.fromAgentName , msg.dialog , msg.timestamp @@ -285,7 +350,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ); eq.ChatterBoxSessionAgentListUpdates( - new UUID(groupID) + new UUID(GroupID) , new UUID(msg.fromAgentID) , new UUID(msg.toAgentID) , false //canVoiceChat @@ -295,7 +360,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } } - else if (!m_agentsDroppedSession.ContainsKey(msg.toAgentID)) + else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID)) { // User hasn't dropped, so they're in the session, // maybe we should deliver it. @@ -321,56 +386,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion - #region ClientEvents - - private void RemoveAgentFromGroupSession(Guid agentID, Guid sessionID) - { - if (m_agentsInGroupSession.ContainsKey(sessionID)) - { - // If in session remove - if (m_agentsInGroupSession[sessionID].Contains(agentID)) - { - m_agentsInGroupSession[sessionID].Remove(agentID); - } - - // If not in dropped list, add - if (!m_agentsDroppedSession[sessionID].Contains(agentID)) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Dropped {1} from session {0}", sessionID, agentID); - m_agentsDroppedSession[sessionID].Add(agentID); - } - } - } - - private void AddAgentToGroupSession(Guid agentID, Guid sessionID) - { - // Add Session Status if it doesn't exist for this session - CreateGroupSessionTracking(sessionID); - - // If nessesary, remove from dropped list - if (m_agentsDroppedSession[sessionID].Contains(agentID)) - { - m_agentsDroppedSession[sessionID].Remove(agentID); - } - - // If nessesary, add to in session list - if (!m_agentsInGroupSession[sessionID].Contains(agentID)) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Added {1} to session {0}", sessionID, agentID); - m_agentsInGroupSession[sessionID].Add(agentID); - } - } - - private void CreateGroupSessionTracking(Guid sessionID) - { - if (!m_agentsInGroupSession.ContainsKey(sessionID)) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Creating session tracking for : {0}", sessionID); - m_agentsInGroupSession.Add(sessionID, new List()); - m_agentsDroppedSession.Add(sessionID, new List()); - } - } + #region ClientEvents private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { if (m_debugEnabled) @@ -383,21 +400,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Start group IM session if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) { - UUID groupID = new UUID(im.toAgentID); + if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID); - GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID); + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); + + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); + if (groupInfo != null) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Start Group Session for {0}", groupInfo.GroupName); - - AddAgentToGroupSession(im.fromAgentID, im.imSessionID); + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); - ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, groupID); + ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID); IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); queue.ChatterBoxSessionAgentListUpdates( - new UUID(groupID) - , new UUID(im.fromAgentID) + GroupID + , AgentID , new UUID(im.toAgentID) , false //canVoiceChat , false //isModerator @@ -409,64 +428,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Send a message from locally connected client to a group if ((im.dialog == (byte)InstantMessageDialog.SessionSend)) { - UUID groupID = new UUID(im.toAgentID); + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", groupID, im.imSessionID.ToString()); + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); - SendMessageToGroup(im, groupID); + //If this agent is sending a message, then they want to be in the session + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); + + SendMessageToGroup(im, GroupID); } } #endregion - private void SendMessageToGroup(GridInstantMessage im, UUID groupID) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - foreach (GroupMembersData member in m_groupsModule.GroupMembersRequest(null, groupID)) - { - if (!m_agentsDroppedSession.ContainsKey(im.imSessionID) || m_agentsDroppedSession[im.imSessionID].Contains(member.AgentID.Guid)) - { - // Don't deliver messages to people who have dropped this session - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); - continue; - } - - // Copy Message - GridInstantMessage msg = new GridInstantMessage(); - msg.imSessionID = im.imSessionID; - msg.fromAgentName = im.fromAgentName; - msg.message = im.message; - msg.dialog = im.dialog; - msg.offline = im.offline; - msg.ParentEstateID = im.ParentEstateID; - msg.Position = im.Position; - msg.RegionID = im.RegionID; - msg.binaryBucket = im.binaryBucket; - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - - // Updat Pertinate fields to make it a "group message" - msg.fromAgentID = groupID.Guid; - msg.fromGroup = true; - - msg.toAgentID = member.AgentID.Guid; - - IClientAPI client = GetActiveClient(member.AgentID); - if (client == null) - { - // If they're not local, forward across the grid - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); - m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); - } - else - { - // Deliver locally, directly - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); - ProcessMessageFromGroupSession(msg); - } - } - } - void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -518,6 +494,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private IClientAPI GetActiveClient(UUID agentID) { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID); + IClientAPI child = null; // Try root avatar first @@ -529,16 +507,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ScenePresence user = (ScenePresence)scene.Entities[agentID]; if (!user.IsChildAgent) { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", user.ControllingClient.Name); return user.ControllingClient; } else { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", user.ControllingClient.Name); child = user.ControllingClient; } } } // If we didn't find a root, then just return whichever child we found, or null if none + if (child == null) + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); + } + else + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); + } return child; } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 8d32e66..edd5af7 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -87,16 +87,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private IGroupsServicesConnector m_groupData = null; - class GroupRequestIDInfo - { - public GroupRequestID RequestID = new GroupRequestID(); - public DateTime LastUsedTMStamp = DateTime.MinValue; - } - private Dictionary m_clientRequestIDInfo = new Dictionary(); - private const int m_clientRequestIDFlushTimeOut = 300000; // Every 5 minutes - private Timer m_clientRequestIDFlushTimer; - - // Configuration settings private bool m_groupsEnabled = false; private bool m_groupNoticesEnabled = true; @@ -133,30 +123,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupNoticesEnabled = groupsConfig.GetBoolean("NoticesEnabled", true); m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); - m_clientRequestIDFlushTimer = new Timer(); - m_clientRequestIDFlushTimer.Interval = m_clientRequestIDFlushTimeOut; - m_clientRequestIDFlushTimer.Elapsed += FlushClientRequestIDInfoCache; - m_clientRequestIDFlushTimer.AutoReset = true; - m_clientRequestIDFlushTimer.Start(); - } - } - - void FlushClientRequestIDInfoCache(object sender, ElapsedEventArgs e) - { - lock (m_clientRequestIDInfo) - { - TimeSpan cacheTimeout = new TimeSpan(0,0, m_clientRequestIDFlushTimeOut / 1000); - UUID[] CurrentKeys = new UUID[m_clientRequestIDInfo.Count]; - foreach (UUID key in CurrentKeys) - { - if (m_clientRequestIDInfo.ContainsKey(key)) - { - if (DateTime.Now - m_clientRequestIDInfo[key].LastUsedTMStamp > cacheTimeout) - { - m_clientRequestIDInfo.Remove(key); - } - } - } } } @@ -234,8 +200,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; if (m_debugEnabled) m_log.Debug("[GROUPS]: Shutting down Groups module."); - - m_clientRequestIDFlushTimer.Stop(); } public Type ReplaceableInterface @@ -272,14 +236,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Used for Notices and Group Invites/Accept/Reject client.OnInstantMessage += OnInstantMessage; - lock (m_clientRequestIDInfo) - { - if (m_clientRequestIDInfo.ContainsKey(client.AgentId)) - { - // flush any old RequestID information - m_clientRequestIDInfo.Remove(client.AgentId); - } - } + // Send client thier groups information. SendAgentGroupDataUpdate(client, client.AgentId); } @@ -287,7 +244,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetClientGroupRequestID(remoteClient), avatarID).ToArray(); + //GroupMembershipData[] avatarGroups = m_groupData.GetAgentGroupMemberships(GetRequestingAgentID(remoteClient), avatarID).ToArray(); GroupMembershipData[] avatarGroups = GetProfileListedGroupMemberships(remoteClient, avatarID); remoteClient.SendAvatarGroupsReply(avatarID, avatarGroups); } @@ -331,10 +288,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", + System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); // TODO: This currently ignores pretty much all the query flags including Mature and sort order - remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetClientGroupRequestID(remoteClient), queryText).ToArray()); + remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentID(remoteClient), queryText).ToArray()); } } @@ -348,7 +308,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups string activeGroupName = string.Empty; ulong activeGroupPowers = (ulong)GroupPowers.None; - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetClientGroupRequestID(remoteClient), dataForAgentID); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient), dataForAgentID); if (membership != null) { activeGroupID = membership.GroupID; @@ -361,13 +321,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups SendScenePresenceUpdate(dataForAgentID, activeGroupTitle); } - private void HandleUUIDGroupNameRequest(UUID GroupID,IClientAPI remoteClient) + private void HandleUUIDGroupNameRequest(UUID GroupID, IClientAPI remoteClient) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); string GroupName; - GroupRecord group = m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), GroupID, null); + GroupRecord group = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null); if (group != null) { GroupName = group.GroupName; @@ -388,7 +348,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) { UUID inviteID = new UUID(im.imSessionID); - GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); + GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); if (inviteInfo == null) { @@ -407,7 +367,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received an accept invite notice."); // and the sessionid is the role - m_groupData.AddAgentToGroup(GetClientGroupRequestID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); + m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), inviteInfo.AgentID, inviteInfo.GroupID, inviteInfo.RoleID); GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; @@ -431,14 +391,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // TODO: If the inviter is still online, they need an agent dataupdate // and maybe group membership updates for the invitee - m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); + m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); } // Reject if (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Received a reject invite notice."); - m_groupData.RemoveAgentToGroupInvite(GetClientGroupRequestID(remoteClient), inviteID); + m_groupData.RemoveAgentToGroupInvite(GetRequestingAgentID(remoteClient), inviteID); } } } @@ -452,7 +412,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } UUID GroupID = new UUID(im.toAgentID); - if (m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), GroupID, null) != null) + if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), GroupID, null) != null) { UUID NoticeID = UUID.Random(); string Subject = im.message.Substring(0, im.message.IndexOf('|')); @@ -496,14 +456,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - m_groupData.AddGroupNotice(GetClientGroupRequestID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); + m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); if (OnNewGroupNotice != null) { OnNewGroupNotice(GroupID, NoticeID); } // Send notice out to everyone that wants notices - foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetClientGroupRequestID(remoteClient), GroupID)) + foreach (GroupMembersData member in m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), GroupID)) { if (m_debugEnabled) { @@ -549,7 +509,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups IClientAPI ejectee = GetActiveClient(ejecteeID); if (ejectee != null) { - UUID groupID = new UUID(im.fromAgentID); + UUID groupID = new UUID(im.imSessionID); ejectee.SendAgentDropGroup(groupID); } } @@ -588,20 +548,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public GroupRecord GetGroupRecord(UUID GroupID) { - return m_groupData.GetGroupRecord(null, GroupID, null); + return m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); } + public GroupRecord GetGroupRecord(string name) + { + return m_groupData.GetGroupRecord(UUID.Zero, UUID.Zero, name); + } + public void ActivateGroup(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentActiveGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID); + m_groupData.SetAgentActiveGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); // Changing active group changes title, active powers, all kinds of things // anyone who is in any region that can see this client, should probably be // updated with new group info. At a minimum, they should get ScenePresence // updated with new title. - UpdateAllClientsWithGroupInfo(remoteClient.AgentId); + UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); } /// @@ -611,10 +576,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - List agentRoles = m_groupData.GetAgentGroupRoles(grID, remoteClient.AgentId, groupID); - GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(grID, remoteClient.AgentId, groupID); + List agentRoles = m_groupData.GetAgentGroupRoles(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); + GroupMembershipData agentMembership = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); List titles = new List(); foreach (GroupRolesData role in agentRoles) @@ -636,8 +600,15 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public List GroupMembersRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + List data = m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), groupID); - List data = m_groupData.GetGroupMembers(GetClientGroupRequestID(remoteClient), groupID); + if (m_debugEnabled) + { + foreach (GroupMembersData member in data) + { + m_log.DebugFormat("[GROUPS]: Member({0}) - IsOwner({1})", member.AgentID, member.IsOwner); + } + } return data; @@ -647,21 +618,25 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List data = m_groupData.GetGroupRoles(GetClientGroupRequestID(remoteClient), groupID); + List data = m_groupData.GetGroupRoles(GetRequestingAgentID(remoteClient), groupID); return data; - } public List GroupRoleMembersRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - List data = m_groupData.GetGroupRoleMembers(GetClientGroupRequestID(remoteClient), groupID); + List data = m_groupData.GetGroupRoleMembers(GetRequestingAgentID(remoteClient), groupID); + if (m_debugEnabled) + { + foreach (GroupRoleMembersData member in data) + { + m_log.DebugFormat("[GROUPS]: Member({0}) - Role({1})", member.MemberID, member.RoleID); + } + } return data; - - } public GroupProfileData GroupProfileRequest(IClientAPI remoteClient, UUID groupID) @@ -670,17 +645,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupProfileData profile = new GroupProfileData(); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - GroupRecord groupInfo = m_groupData.GetGroupRecord(GetClientGroupRequestID(remoteClient), groupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); if (groupInfo != null) { profile.AllowPublish = groupInfo.AllowPublish; profile.Charter = groupInfo.Charter; profile.FounderID = groupInfo.FounderID; profile.GroupID = groupID; - profile.GroupMembershipCount = m_groupData.GetGroupMembers(grID, groupID).Count; - profile.GroupRolesCount = m_groupData.GetGroupRoles(grID, groupID).Count; + profile.GroupMembershipCount = m_groupData.GetGroupMembers(GetRequestingAgentID(remoteClient), groupID).Count; + profile.GroupRolesCount = m_groupData.GetGroupRoles(GetRequestingAgentID(remoteClient), groupID).Count; profile.InsigniaID = groupInfo.GroupPicture; profile.MaturePublish = groupInfo.MaturePublish; profile.MembershipFee = groupInfo.MembershipFee; @@ -691,7 +665,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups profile.ShowInList = groupInfo.ShowInList; } - GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(grID, remoteClient.AgentId, groupID); + GroupMembershipData memberInfo = m_groupData.GetAgentGroupMembership(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); if (memberInfo != null) { profile.MemberTitle = memberInfo.GroupTitle; @@ -705,40 +679,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - return m_groupData.GetAgentGroupMemberships(null, agentID).ToArray(); + return m_groupData.GetAgentGroupMemberships(UUID.Zero, agentID).ToArray(); } public GroupMembershipData GetMembershipData(UUID groupID, UUID agentID) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS]: {0} called with groupID={1}, agentID={2}", + System.Reflection.MethodBase.GetCurrentMethod().Name, groupID, agentID); - return m_groupData.GetAgentGroupMembership(null, agentID, groupID); + return m_groupData.GetAgentGroupMembership(UUID.Zero, agentID, groupID); } public void UpdateGroupInfo(IClientAPI remoteClient, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - // TODO: Security Check? - - m_groupData.UpdateGroup(GetClientGroupRequestID(remoteClient), groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); + // Note: Permissions checking for modification rights is handled by the Groups Server/Service + m_groupData.UpdateGroup(GetRequestingAgentID(remoteClient), groupID, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish); } public void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile) { - // TODO: Security Check? + // Note: Permissions checking for modification rights is handled by the Groups Server/Service if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentGroupInfo(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, acceptNotices, listInProfile); + m_groupData.SetAgentGroupInfo(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, acceptNotices, listInProfile); } public UUID CreateGroup(IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - - if (m_groupData.GetGroupRecord(grID, UUID.Zero, name) != null) + if (m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), UUID.Zero, name) != null) { remoteClient.SendCreateGroupReply(UUID.Zero, false, "A group with the same name already exists."); return UUID.Zero; @@ -754,12 +728,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } money.ApplyGroupCreationCharge(remoteClient.AgentId); } - UUID groupID = m_groupData.CreateGroup(grID, name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, remoteClient.AgentId); + UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); remoteClient.SendCreateGroupReply(groupID, true, "Group created successfullly"); // Update the founder with new group information. - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); return groupID; } @@ -770,7 +744,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // ToDo: check if agent is a member of group and is allowed to see notices? - return m_groupData.GetGroupNotices(GetClientGroupRequestID(remoteClient), groupID).ToArray(); + return m_groupData.GetGroupNotices(GetRequestingAgentID(remoteClient), groupID).ToArray(); } /// @@ -780,7 +754,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupMembershipData membership = m_groupData.GetAgentActiveMembership(null, avatarID); + GroupMembershipData membership = m_groupData.GetAgentActiveMembership(UUID.Zero, avatarID); if (membership != null) { return membership.GroupTitle; @@ -795,13 +769,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.SetAgentActiveGroupRole(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, titleRoleID); + m_groupData.SetAgentActiveGroupRole(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, titleRoleID); // TODO: Not sure what all is needed here, but if the active group role change is for the group // the client currently has set active, then we need to do a scene presence update too - // if (m_groupData.GetAgentActiveMembership(remoteClient.AgentId).GroupID == GroupID) + // if (m_groupData.GetAgentActiveMembership(GetRequestingAgentID(remoteClient)).GroupID == GroupID) - UpdateAllClientsWithGroupInfo(remoteClient.AgentId); + UpdateAllClientsWithGroupInfo(GetRequestingAgentID(remoteClient)); } @@ -811,16 +785,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Security Checks are handled in the Groups Service. - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - switch ((OpenMetaverse.GroupRoleUpdate)updateType) { case OpenMetaverse.GroupRoleUpdate.Create: - m_groupData.AddGroupRole(grID, groupID, UUID.Random(), name, description, title, powers); + m_groupData.AddGroupRole(GetRequestingAgentID(remoteClient), groupID, UUID.Random(), name, description, title, powers); break; case OpenMetaverse.GroupRoleUpdate.Delete: - m_groupData.RemoveGroupRole(grID, groupID, roleID); + m_groupData.RemoveGroupRole(GetRequestingAgentID(remoteClient), groupID, roleID); break; case OpenMetaverse.GroupRoleUpdate.UpdateAll: @@ -831,7 +803,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GroupPowers gp = (GroupPowers)powers; m_log.DebugFormat("[GROUPS]: Role ({0}) updated with Powers ({1}) ({2})", name, powers.ToString(), gp.ToString()); } - m_groupData.UpdateGroupRole(grID, groupID, roleID, name, description, title, powers); + m_groupData.UpdateGroupRole(GetRequestingAgentID(remoteClient), groupID, roleID, name, description, title, powers); break; case OpenMetaverse.GroupRoleUpdate.NoUpdate: @@ -842,7 +814,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void GroupRoleChanges(IClientAPI remoteClient, UUID groupID, UUID roleID, UUID memberID, uint changes) @@ -850,18 +822,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Todo: Security check - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - switch (changes) { case 0: // Add - m_groupData.AddAgentToGroupRole(grID, memberID, groupID, roleID); + m_groupData.AddAgentToGroupRole(GetRequestingAgentID(remoteClient), memberID, groupID, roleID); break; case 1: // Remove - m_groupData.RemoveAgentFromGroupRole(grID, memberID, groupID, roleID); + m_groupData.RemoveAgentFromGroupRole(GetRequestingAgentID(remoteClient), memberID, groupID, roleID); break; default: @@ -870,25 +840,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } // TODO: This update really should send out updates for everyone in the role that just got changed. - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void GroupNoticeRequest(IClientAPI remoteClient, UUID groupNoticeID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); - - GroupNoticeInfo data = m_groupData.GetGroupNotice(grID, groupNoticeID); + GroupNoticeInfo data = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), groupNoticeID); if (data != null) { - GroupRecord groupInfo = m_groupData.GetGroupRecord(grID, data.GroupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; msg.fromAgentID = data.GroupID.Guid; - msg.toAgentID = remoteClient.AgentId.Guid; + msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName; msg.message = data.noticeData.Subject + "|" + data.Message; @@ -900,7 +868,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.RegionID = UUID.Zero.Guid; msg.binaryBucket = data.BinaryBucket; - OutgoingInstantMessage(msg, remoteClient.AgentId); + OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); } } @@ -920,7 +888,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.Position = Vector3.Zero; msg.RegionID = UUID.Zero.Guid; - GroupNoticeInfo info = m_groupData.GetGroupNotice(null, groupNoticeID); + GroupNoticeInfo info = m_groupData.GetGroupNotice(agentID, groupNoticeID); if (info != null) { msg.fromAgentID = info.GroupID.Guid; @@ -947,7 +915,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Send agent information about his groups - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void JoinGroupRequest(IClientAPI remoteClient, UUID groupID) @@ -955,19 +923,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); // Should check to see if OpenEnrollment, or if there's an outstanding invitation - m_groupData.AddAgentToGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID, UUID.Zero); + m_groupData.AddAgentToGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID, UUID.Zero); remoteClient.SendJoinGroupReply(groupID, true); // Should this send updates to everyone in the group? - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void LeaveGroupRequest(IClientAPI remoteClient, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupData.RemoveAgentFromGroup(GetClientGroupRequestID(remoteClient), remoteClient.AgentId, groupID); + m_groupData.RemoveAgentFromGroup(GetRequestingAgentID(remoteClient), GetRequestingAgentID(remoteClient), groupID); remoteClient.SendLeaveGroupReply(groupID, true); @@ -975,21 +943,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // SL sends out notifcations to the group messaging session that the person has left // Should this also update everyone who is in the group? - SendAgentGroupDataUpdate(remoteClient, remoteClient.AgentId); + SendAgentGroupDataUpdate(remoteClient, GetRequestingAgentID(remoteClient)); } public void EjectGroupMemberRequest(IClientAPI remoteClient, UUID groupID, UUID ejecteeID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - GroupRequestID grID = GetClientGroupRequestID(remoteClient); // Todo: Security check? - m_groupData.RemoveAgentFromGroup(grID, ejecteeID, groupID); + m_groupData.RemoveAgentFromGroup(GetRequestingAgentID(remoteClient), ejecteeID, groupID); - remoteClient.SendEjectGroupMemberReply(remoteClient.AgentId, groupID, true); + remoteClient.SendEjectGroupMemberReply(GetRequestingAgentID(remoteClient), groupID, true); - GroupRecord groupInfo = m_groupData.GetGroupRecord(grID, groupID, null); + GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), groupID, null); UserProfileData userProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(ejecteeID); if ((groupInfo == null) || (userProfile == null)) @@ -1002,7 +969,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups GridInstantMessage msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; - msg.fromAgentID = remoteClient.AgentId.Guid; + msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; // msg.fromAgentID = info.GroupID; msg.toAgentID = ejecteeID.Guid; //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); @@ -1028,8 +995,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg = new GridInstantMessage(); msg.imSessionID = UUID.Zero.Guid; - msg.fromAgentID = remoteClient.AgentId.Guid; - msg.toAgentID = remoteClient.AgentId.Guid; + msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; + msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; msg.timestamp = 0; msg.fromAgentName = remoteClient.Name; if (userProfile != null) @@ -1047,7 +1014,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.Position = Vector3.Zero; msg.RegionID = remoteClient.Scene.RegionInfo.RegionID.Guid; msg.binaryBucket = new byte[0]; - OutgoingInstantMessage(msg, remoteClient.AgentId); + OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); // SL sends out messages to everyone in the group @@ -1061,13 +1028,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Todo: Security check, probably also want to send some kind of notification UUID InviteID = UUID.Random(); - GroupRequestID grid = GetClientGroupRequestID(remoteClient); - m_groupData.AddAgentToGroupInvite(grid, InviteID, groupID, roleID, invitedAgentID); + m_groupData.AddAgentToGroupInvite(GetRequestingAgentID(remoteClient), InviteID, groupID, roleID, invitedAgentID); // Check to see if the invite went through, if it did not then it's possible // the remoteClient did not validate or did not have permission to invite. - GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(grid, InviteID); + GroupInviteInfo inviteInfo = m_groupData.GetAgentToGroupInvite(GetRequestingAgentID(remoteClient), InviteID); if (inviteInfo != null) { @@ -1079,7 +1045,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups msg.imSessionID = inviteUUID; - // msg.fromAgentID = remoteClient.AgentId.Guid; + // msg.fromAgentID = GetRequestingAgentID(remoteClient).Guid; msg.fromAgentID = groupID.Guid; msg.toAgentID = invitedAgentID.Guid; //msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); @@ -1132,57 +1098,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return child; } - private GroupRequestID GetClientGroupRequestID(IClientAPI client) - { - if (client == null) - { - return new GroupRequestID(); - } - - lock (m_clientRequestIDInfo) - { - if (!m_clientRequestIDInfo.ContainsKey(client.AgentId)) - { - GroupRequestIDInfo info = new GroupRequestIDInfo(); - info.RequestID.AgentID = client.AgentId; - info.RequestID.SessionID = client.SessionId; - - UserProfileData userProfile = m_sceneList[0].CommsManager.UserService.GetUserProfile(client.AgentId); - if (userProfile == null) - { - // This should be impossible. If I've been passed a reference to a client - // that client should be registered with the UserService. So something - // is horribly wrong somewhere. - - m_log.WarnFormat("[GROUPS]: Could not find a user profile for {0} / {1}", client.Name, client.AgentId); - - // Default to local user service and hope for the best? - info.RequestID.UserServiceURL = m_sceneList[0].CommsManager.NetworkServersInfo.UserURL; - - } - else if (userProfile is ForeignUserProfileData) - { - // They aren't from around here - ForeignUserProfileData fupd = (ForeignUserProfileData)userProfile; - info.RequestID.UserServiceURL = fupd.UserServerURI; - } - else - { - // They're a local user, use this: - info.RequestID.UserServiceURL = m_sceneList[0].CommsManager.NetworkServersInfo.UserURL; - } - - m_clientRequestIDInfo.Add(client.AgentId, info); - } - - m_clientRequestIDInfo[client.AgentId].LastUsedTMStamp = DateTime.Now; - - return m_clientRequestIDInfo[client.AgentId].RequestID; - } -// Unreachable code! -// return new GroupRequestID(); - } - /// /// Send 'remoteClient' the group membership 'data' for agent 'dataForAgentID'. /// @@ -1231,6 +1146,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups llDataStruct.Add("GroupData", GroupData); llDataStruct.Add("NewGroupData", NewGroupData); + if (m_debugEnabled) + { + m_log.InfoFormat("[GROUPS]: {0}", OSDParser.SerializeJsonString(llDataStruct)); + } + IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); if (queue != null) @@ -1308,7 +1228,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private GroupMembershipData[] GetProfileListedGroupMemberships(IClientAPI requestingClient, UUID dataForAgentID) { - List membershipData = m_groupData.GetAgentGroupMemberships(GetClientGroupRequestID(requestingClient), dataForAgentID); + List membershipData = m_groupData.GetAgentGroupMemberships(requestingClient.AgentId, dataForAgentID); GroupMembershipData[] membershipArray; if (requestingClient.AgentId != dataForAgentID) @@ -1330,7 +1250,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.InfoFormat("[GROUPS]: Get group membership information for {0} requested by {1}", dataForAgentID, requestingClient.AgentId); foreach (GroupMembershipData membership in membershipArray) { - m_log.InfoFormat("[GROUPS]: {0} :: {1} - {2}", dataForAgentID, membership.GroupName, membership.GroupTitle); + m_log.InfoFormat("[GROUPS]: {0} :: {1} - {2} - {3}", dataForAgentID, membership.GroupName, membership.GroupTitle, membership.GroupPowers); } } @@ -1389,6 +1309,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } #endregion + + private UUID GetRequestingAgentID(IClientAPI client) + { + UUID requestingAgentID = UUID.Zero; + if (client != null) + { + requestingAgentID = client.AgentId; + } + return requestingAgentID; + } } + public class GroupNoticeInfo + { + public GroupNoticeData noticeData = new GroupNoticeData(); + public UUID GroupID = UUID.Zero; + public string Message = string.Empty; + public byte[] BinaryBucket = new byte[0]; + } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs index 9e0fa2d..a046e09 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs @@ -36,42 +36,47 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { interface IGroupsServicesConnector { - UUID CreateGroup(GroupRequestID requestID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); - void UpdateGroup(GroupRequestID requestID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); - GroupRecord GetGroupRecord(GroupRequestID requestID, UUID GroupID, string GroupName); - List FindGroups(GroupRequestID requestID, string search); - List GetGroupMembers(GroupRequestID requestID, UUID GroupID); + UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); + void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); + GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName); + List FindGroups(UUID RequestingAgentID, string search); + List GetGroupMembers(UUID RequestingAgentID, UUID GroupID); - void AddGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); - void UpdateGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); - void RemoveGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID); - List GetGroupRoles(GroupRequestID requestID, UUID GroupID); - List GetGroupRoleMembers(GroupRequestID requestID, UUID GroupID); + void AddGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); + void UpdateGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers); + void RemoveGroupRole(UUID RequestingAgentID, UUID groupID, UUID roleID); + List GetGroupRoles(UUID RequestingAgentID, UUID GroupID); + List GetGroupRoleMembers(UUID RequestingAgentID, UUID GroupID); - void AddAgentToGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - void RemoveAgentFromGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID); + void AddAgentToGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + void RemoveAgentFromGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - void AddAgentToGroupInvite(GroupRequestID requestID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID); - GroupInviteInfo GetAgentToGroupInvite(GroupRequestID requestID, UUID inviteID); - void RemoveAgentToGroupInvite(GroupRequestID requestID, UUID inviteID); + void AddAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID); + GroupInviteInfo GetAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID); + void RemoveAgentToGroupInvite(UUID RequestingAgentID, UUID inviteID); + void AddAgentToGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + void RemoveAgentFromGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + List GetAgentGroupRoles(UUID RequestingAgentID, UUID AgentID, UUID GroupID); - void AddAgentToGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - void RemoveAgentFromGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - List GetAgentGroupRoles(GroupRequestID requestID, UUID AgentID, UUID GroupID); + void SetAgentActiveGroup(UUID RequestingAgentID, UUID AgentID, UUID GroupID); + GroupMembershipData GetAgentActiveMembership(UUID RequestingAgentID, UUID AgentID); - void SetAgentActiveGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID); - GroupMembershipData GetAgentActiveMembership(GroupRequestID requestID, UUID AgentID); + void SetAgentActiveGroupRole(UUID RequestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID); + void SetAgentGroupInfo(UUID RequestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile); - void SetAgentActiveGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID); - void SetAgentGroupInfo(GroupRequestID requestID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile); + GroupMembershipData GetAgentGroupMembership(UUID RequestingAgentID, UUID AgentID, UUID GroupID); + List GetAgentGroupMemberships(UUID RequestingAgentID, UUID AgentID); - GroupMembershipData GetAgentGroupMembership(GroupRequestID requestID, UUID AgentID, UUID GroupID); - List GetAgentGroupMemberships(GroupRequestID requestID, UUID AgentID); + void AddGroupNotice(UUID RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); + GroupNoticeInfo GetGroupNotice(UUID RequestingAgentID, UUID noticeID); + List GetGroupNotices(UUID RequestingAgentID, UUID GroupID); - void AddGroupNotice(GroupRequestID requestID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); - GroupNoticeInfo GetGroupNotice(GroupRequestID requestID, UUID noticeID); - List GetGroupNotices(GroupRequestID requestID, UUID GroupID); + void ResetAgentGroupChatSessions(UUID agentID); + bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID); + bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID); + void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID); + void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID); } public class GroupInviteInfo @@ -81,11 +86,4 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public UUID AgentID = UUID.Zero; public UUID InviteID = UUID.Zero; } - - public class GroupRequestID - { - public UUID AgentID = UUID.Zero; - public string UserServiceURL = string.Empty; - public UUID SessionID = UUID.Zero; - } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs new file mode 100644 index 0000000..669373f --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -0,0 +1,1329 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Reflection; + +using Nwc.XmlRpc; + +using log4net; +using Mono.Addins; +using Nini.Config; + +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; + +/*************************************************************************** + * Simian Data Map + * =============== + * + * OwnerID -> Type -> Key + * ----------------------- + * + * UserID -> Group -> ActiveGroup + * + GroupID + * + * UserID -> GroupSessionDropped -> GroupID + * UserID -> GroupSessionInvited -> GroupID + * + * UserID -> GroupMember -> GroupID + * + SelectedRoleID [UUID] + * + AcceptNotices [bool] + * + ListInProfile [bool] + * + Contribution [int] + * + * UserID -> GroupRole[GroupID] -> RoleID + * + * + * GroupID -> Group -> GroupName + * + Charter + * + ShowInList + * + InsigniaID + * + MembershipFee + * + OpenEnrollment + * + AllowPublish + * + MaturePublish + * + FounderID + * + EveryonePowers + * + OwnerRoleID + * + OwnersPowers + * + * GroupID -> GroupRole -> RoleID + * + Name + * + Description + * + Title + * + Powers + * + * GroupID -> GroupMemberInvite -> InviteID + * + AgentID + * + RoleID + * + * GroupID -> GroupNotice -> NoticeID + * + TimeStamp [uint] + * + FromName [string] + * + Subject [string] + * + Message [string] + * + BinaryBucket [byte[]] + * + * */ + +namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class SimianGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | + GroupPowers.Accountable | + GroupPowers.JoinChat | + GroupPowers.AllowVoiceChat | + GroupPowers.ReceiveNotices | + GroupPowers.StartProposal | + GroupPowers.VoteOnProposal; + + // Would this be cleaner as (GroupPowers)ulong.MaxValue; + public const GroupPowers m_DefaultOwnerPowers = GroupPowers.Accountable + | GroupPowers.AllowEditLand + | GroupPowers.AllowFly + | GroupPowers.AllowLandmark + | GroupPowers.AllowRez + | GroupPowers.AllowSetHome + | GroupPowers.AllowVoiceChat + | GroupPowers.AssignMember + | GroupPowers.AssignMemberLimited + | GroupPowers.ChangeActions + | GroupPowers.ChangeIdentity + | GroupPowers.ChangeMedia + | GroupPowers.ChangeOptions + | GroupPowers.CreateRole + | GroupPowers.DeedObject + | GroupPowers.DeleteRole + | GroupPowers.Eject + | GroupPowers.FindPlaces + | GroupPowers.Invite + | GroupPowers.JoinChat + | GroupPowers.LandChangeIdentity + | GroupPowers.LandDeed + | GroupPowers.LandDivideJoin + | GroupPowers.LandEdit + | GroupPowers.LandEjectAndFreeze + | GroupPowers.LandGardening + | GroupPowers.LandManageAllowed + | GroupPowers.LandManageBanned + | GroupPowers.LandManagePasses + | GroupPowers.LandOptions + | GroupPowers.LandRelease + | GroupPowers.LandSetSale + | GroupPowers.ModerateChat + | GroupPowers.ObjectManipulate + | GroupPowers.ObjectSetForSale + | GroupPowers.ReceiveNotices + | GroupPowers.RemoveMember + | GroupPowers.ReturnGroupOwned + | GroupPowers.ReturnGroupSet + | GroupPowers.ReturnNonGroup + | GroupPowers.RoleProperties + | GroupPowers.SendNotices + | GroupPowers.SetLandingPoint + | GroupPowers.StartProposal + | GroupPowers.VoteOnProposal; + + private bool m_connectorEnabled = false; + + private string m_groupsServerURI = string.Empty; + + private bool m_debugEnabled = false; + + // private IUserAccountService m_accountService = null; + + + #region IRegionModuleBase Members + + public string Name + { + get { return "SimianGroupsServicesConnector"; } + } + + // this module is not intended to be replaced, but there should only be 1 of them. + public Type ReplaceableInterface + { + get { return null; } + } + + public void Initialise(IConfigSource config) + { + IConfig groupsConfig = config.Configs["Groups"]; + + if (groupsConfig == null) + { + // Do not run this module by default. + return; + } + else + { + // if groups aren't enabled, we're not needed. + // if we're not specified as the connector to use, then we're not wanted + if ((groupsConfig.GetBoolean("Enabled", false) == false) + || (groupsConfig.GetString("ServicesConnectorModule", "Default") != Name)) + { + m_connectorEnabled = false; + return; + } + + m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); + + m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); + if ((m_groupsServerURI == null) || + (m_groupsServerURI == string.Empty)) + { + m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]"); + m_connectorEnabled = false; + return; + } + + // If we got all the config options we need, lets start'er'up + m_connectorEnabled = true; + + m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); + + } + } + + public void Close() + { + m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); + } + + public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) + { + if (m_connectorEnabled) + { + scene.RegisterModuleInterface(this); + } + } + + public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene) + { + if (scene.RequestModuleInterface() == this) + { + scene.UnregisterModuleInterface(this); + } + } + + public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene) + { + // TODO: May want to consider listenning for Agent Connections so we can pre-cache group info + // scene.EventManager.OnNewClient += OnNewClient; + } + + #endregion + + #region ISharedRegionModule Members + + public void PostInitialise() + { + // NoOp + } + + #endregion + + + + + #region IGroupsServicesConnector Members + + /// + /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. + /// + public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, + int membershipFee, bool openEnrollment, bool allowPublish, + bool maturePublish, UUID founderID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + UUID GroupID = UUID.Random(); + UUID OwnerRoleID = UUID.Random(); + + OSDMap GroupInfoMap = new OSDMap(); + GroupInfoMap["Charter"] = OSD.FromString(charter); + GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); + GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); + GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); + GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); + GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); + GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); + GroupInfoMap["FounderID"] = OSD.FromUUID(founderID); + GroupInfoMap["EveryonePowers"] = OSD.FromULong((ulong)m_DefaultEveryonePowers); + GroupInfoMap["OwnerRoleID"] = OSD.FromUUID(OwnerRoleID); + GroupInfoMap["OwnersPowers"] = OSD.FromULong((ulong)m_DefaultOwnerPowers); + + if(SimianAddGeneric(GroupID, "Group", name, GroupInfoMap)) + { + AddGroupRole(requestingAgentID, GroupID, UUID.Zero, "Everyone", "Members of " + name, "Member of " + name, (ulong)m_DefaultEveryonePowers); + AddGroupRole(requestingAgentID, GroupID, OwnerRoleID, "Owners", "Owners of " + name, "Owner of " + name, (ulong)m_DefaultOwnerPowers); + + AddAgentToGroup(requestingAgentID, requestingAgentID, GroupID, OwnerRoleID); + + return GroupID; + } + else + { + return UUID.Zero; + } + } + + + public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, + UUID insigniaID, int membershipFee, bool openEnrollment, + bool allowPublish, bool maturePublish) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + // TODO: Check to make sure requestingAgentID has permission to update group + + string GroupName; + OSDMap GroupInfoMap; + if( SimianGetFirstGenericEntry(groupID, "GroupInfo", out GroupName, out GroupInfoMap) ) + { + GroupInfoMap["Charter"] = OSD.FromString(charter); + GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); + GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); + GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); + GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); + GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); + GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); + + SimianAddGeneric(groupID, "Group", GroupName, GroupInfoMap); + } + + } + + + public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + string title, ulong powers) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupRoleInfo = new OSDMap(); + GroupRoleInfo["Name"] = OSD.FromString(name); + GroupRoleInfo["Description"] = OSD.FromString(description); + GroupRoleInfo["Title"] = OSD.FromString(title); + GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); + + // TODO: Add security, make sure that requestingAgentID has permision to add roles + SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); + } + + public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // TODO: Add security + + // Can't delete the Everyone Role + if (roleID != UUID.Zero) + { + // Remove all GroupRole Members from Role + Dictionary GroupRoleMembers; + string GroupRoleMemberType = "GroupRole" + groupID.ToString(); + if (SimianGetGenericEntries(GroupRoleMemberType, roleID.ToString(), out GroupRoleMembers)) + { + foreach(UUID UserID in GroupRoleMembers.Keys) + { + EnsureRoleNotSelectedByMember(groupID, roleID, UserID); + + SimianRemoveGenericEntry(UserID, GroupRoleMemberType, roleID.ToString()); + } + } + + // Remove role + SimianRemoveGenericEntry(groupID, "GroupRole", roleID.ToString()); + } + } + + + public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, + string title, ulong powers) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // TODO: Security, check that requestingAgentID is allowed to update group roles + + OSDMap GroupRoleInfo; + if (SimianGetGenericEntry(groupID, "GroupRole", roleID.ToString(), out GroupRoleInfo)) + { + if (name != null) + { + GroupRoleInfo["Name"] = OSD.FromString(name); + } + if (description != null) + { + GroupRoleInfo["Description"] = OSD.FromString(description); + } + if (title != null) + { + GroupRoleInfo["Title"] = OSD.FromString(title); + } + GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); + + } + + + SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); + } + + public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupInfoMap = null; + if (groupID != UUID.Zero) + { + if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out GroupInfoMap)) + { + return null; + } + } + else if ((groupName != null) && (groupName != string.Empty)) + { + if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) + { + return null; + } + } + + GroupRecord GroupInfo = new GroupRecord(); + + GroupInfo.GroupID = groupID; + GroupInfo.GroupName = groupName; + GroupInfo.Charter = GroupInfoMap["Charter"].AsString(); + GroupInfo.ShowInList = GroupInfoMap["ShowInList"].AsBoolean(); + GroupInfo.GroupPicture = GroupInfoMap["InsigniaID"].AsUUID(); + GroupInfo.MembershipFee = GroupInfoMap["MembershipFee"].AsInteger(); + GroupInfo.OpenEnrollment = GroupInfoMap["OpenEnrollment"].AsBoolean(); + GroupInfo.AllowPublish = GroupInfoMap["AllowPublish"].AsBoolean(); + GroupInfo.MaturePublish = GroupInfoMap["MaturePublish"].AsBoolean(); + GroupInfo.FounderID = GroupInfoMap["FounderID"].AsUUID(); + GroupInfo.OwnerRoleID = GroupInfoMap["OwnerRoleID"].AsUUID(); + + return GroupInfo; + + } + + public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID groupID, UUID memberID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap groupProfile; + string groupName; + if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out groupProfile)) + { + // GroupProfileData is not nullable + return new GroupProfileData(); + } + + GroupProfileData MemberGroupProfile = new GroupProfileData(); + MemberGroupProfile.GroupID = groupID; + MemberGroupProfile.Name = groupName; + + if (groupProfile["Charter"] != null) + { + MemberGroupProfile.Charter = groupProfile["Charter"].AsString(); + } + + MemberGroupProfile.ShowInList = groupProfile["ShowInList"].AsString() == "1"; + MemberGroupProfile.InsigniaID = groupProfile["InsigniaID"].AsUUID(); + MemberGroupProfile.MembershipFee = groupProfile["MembershipFee"].AsInteger(); + MemberGroupProfile.OpenEnrollment = groupProfile["OpenEnrollment"].AsBoolean(); + MemberGroupProfile.AllowPublish = groupProfile["AllowPublish"].AsBoolean(); + MemberGroupProfile.MaturePublish = groupProfile["MaturePublish"].AsBoolean(); + MemberGroupProfile.FounderID = groupProfile["FounderID"].AsUUID();; + MemberGroupProfile.OwnerRole = groupProfile["OwnerRoleID"].AsUUID(); + + Dictionary Members; + if (SimianGetGenericEntries("GroupMember",groupID.ToString(), out Members)) + { + MemberGroupProfile.GroupMembershipCount = Members.Count; + } + + Dictionary Roles; + if (SimianGetGenericEntries(groupID, "GroupRole", out Roles)) + { + MemberGroupProfile.GroupRolesCount = Roles.Count; + } + + // TODO: Get Group Money balance from somewhere + // group.Money = 0; + + GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, memberID, groupID); + + MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; + MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; + + return MemberGroupProfile; + } + + public void SetAgentActiveGroup(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap ActiveGroup = new OSDMap(); + ActiveGroup.Add("GroupID", OSD.FromUUID(groupID)); + SimianAddGeneric(agentID, "Group", "ActiveGroup", ActiveGroup); + } + + public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupMemberInfo; + if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) + { + GroupMemberInfo = new OSDMap(); + } + + GroupMemberInfo["SelectedRoleID"] = OSD.FromUUID(roleID); + SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); + } + + public void SetAgentGroupInfo(UUID requestingAgentID, UUID agentID, UUID groupID, bool acceptNotices, bool listInProfile) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupMemberInfo; + if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) + { + GroupMemberInfo = new OSDMap(); + } + + GroupMemberInfo["AcceptNotices"] = OSD.FromBoolean(acceptNotices); + GroupMemberInfo["ListInProfile"] = OSD.FromBoolean(listInProfile); + GroupMemberInfo["Contribution"] = OSD.FromInteger(0); + GroupMemberInfo["SelectedRole"] = OSD.FromUUID(UUID.Zero); + SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); + } + + public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap Invite = new OSDMap(); + Invite["AgentID"] = OSD.FromUUID(agentID); + Invite["RoleID"] = OSD.FromUUID(roleID); + + SimianAddGeneric(groupID, "GroupMemberInvite", inviteID.ToString(), Invite); + } + + public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupMemberInvite; + UUID GroupID; + if (!SimianGetFirstGenericEntry("GroupMemberInvite", inviteID.ToString(), out GroupID, out GroupMemberInvite)) + { + return null; + } + + GroupInviteInfo inviteInfo = new GroupInviteInfo(); + inviteInfo.InviteID = inviteID; + inviteInfo.GroupID = GroupID; + inviteInfo.AgentID = GroupMemberInvite["AgentID"].AsUUID(); + inviteInfo.RoleID = GroupMemberInvite["RoleID"].AsUUID(); + + return inviteInfo; + } + + public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupInviteInfo invite = GetAgentToGroupInvite(requestingAgentID, inviteID); + SimianRemoveGenericEntry(invite.GroupID, "GroupMemberInvite", inviteID.ToString()); + } + + public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Setup Agent/Group information + SetAgentGroupInfo(requestingAgentID, AgentID, GroupID, true, true); + + // Add agent to Everyone Group + AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, UUID.Zero); + + // Add agent to Specified Role + AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, RoleID); + + // Set selected role in this group to specified role + SetAgentActiveGroupRole(requestingAgentID, AgentID, GroupID, RoleID); + } + + public void RemoveAgentFromGroup(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // If current active group is the group the agent is being removed from, change their group to UUID.Zero + GroupMembershipData memberActiveMembership = GetAgentActiveMembership(requestingAgentID, agentID); + if (memberActiveMembership.GroupID == groupID) + { + SetAgentActiveGroup(agentID, agentID, UUID.Zero); + } + + // Remove Group Member information for this group + SimianRemoveGenericEntry(agentID, "GroupMember", groupID.ToString()); + + // By using a Simian Generics Type consisting of a prefix and a groupID, + // combined with RoleID as key allows us to get a list of roles a particular member + // of a group is assigned to. + string GroupRoleMemberType = "GroupRole" + groupID.ToString(); + + // Take Agent out of all other group roles + Dictionary GroupRoles; + if (SimianGetGenericEntries(agentID, GroupRoleMemberType, out GroupRoles)) + { + foreach (string roleID in GroupRoles.Keys) + { + SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID); + } + } + } + + public void AddAgentToGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + SimianAddGeneric(agentID, "GroupRole" + groupID.ToString(), roleID.ToString(), new OSDMap()); + } + + public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // Cannot remove members from the Everyone Role + if (roleID != UUID.Zero) + { + EnsureRoleNotSelectedByMember(groupID, roleID, agentID); + + string GroupRoleMemberType = "GroupRole" + groupID.ToString(); + SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID.ToString()); + } + } + + public List FindGroups(UUID requestingAgentID, string search) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List findings = new List(); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Type", "Group" }, + { "Key", search }, + { "Fuzzy", "1" } + }; + + + OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)response["Entries"]; + foreach (OSDMap entryMap in entryArray) + { + DirGroupsReplyData data = new DirGroupsReplyData(); + data.groupID = entryMap["OwnerID"].AsUUID(); + data.groupName = entryMap["Key"].AsString(); + + // TODO: is there a better way to do this? + Dictionary Members; + if (SimianGetGenericEntries("GroupMember", data.groupID.ToString(), out Members)) + { + data.members = Members.Count; + } + else + { + data.members = 0; + } + + // TODO: sort results? + // data.searchOrder = order; + + findings.Add(data); + } + } + + + return findings; + } + + public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupMembershipData data = new GroupMembershipData(); + + /////////////////////////////// + // Agent Specific Information: + // + OSDMap UserActiveGroup; + if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) + { + data.Active = UserActiveGroup["GroupID"].AsUUID().Equals(groupID); + } + + OSDMap UserGroupMemberInfo; + if( SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out UserGroupMemberInfo) ) + { + data.AcceptNotices = UserGroupMemberInfo["AcceptNotices"].AsBoolean(); + data.Contribution = UserGroupMemberInfo["Contribution"].AsInteger(); + data.ListInProfile = UserGroupMemberInfo["ListInProfile"].AsBoolean(); + data.ActiveRole = UserGroupMemberInfo["SelectedRoleID"].AsUUID(); + + /////////////////////////////// + // Role Specific Information: + // + + OSDMap GroupRoleInfo; + if( SimianGetGenericEntry(groupID, "GroupRole", data.ActiveRole.ToString(), out GroupRoleInfo) ) + { + data.GroupTitle = GroupRoleInfo["Title"].AsString(); + data.GroupPowers = GroupRoleInfo["Powers"].AsULong(); + } + } + + /////////////////////////////// + // Group Specific Information: + // + OSDMap GroupInfo; + string GroupName; + if( SimianGetFirstGenericEntry(groupID, "Group", out GroupName, out GroupInfo) ) + { + data.GroupID = groupID; + data.AllowPublish = GroupInfo["AllowPublish"].AsBoolean(); + data.Charter = GroupInfo["Charter"].AsString(); + data.FounderID = GroupInfo["FounderID"].AsUUID(); + data.GroupName = GroupName; + data.GroupPicture = GroupInfo["InsigniaID"].AsUUID(); + data.MaturePublish = GroupInfo["MaturePublish"].AsBoolean(); + data.MembershipFee = GroupInfo["MembershipFee"].AsInteger(); + data.OpenEnrollment = GroupInfo["OpenEnrollment"].AsBoolean(); + data.ShowInList = GroupInfo["ShowInList"].AsBoolean(); + } + + return data; + } + + public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID agentID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + UUID GroupID = UUID.Zero; + OSDMap UserActiveGroup; + if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) + { + GroupID = UserActiveGroup["GroupID"].AsUUID(); + } + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Active GroupID : {0}", GroupID.ToString()); + return GetAgentGroupMembership(requestingAgentID, agentID, GroupID); + } + + public List GetAgentGroupMemberships(UUID requestingAgentID, UUID agentID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List memberships = new List(); + + Dictionary GroupMemberShips; + if (SimianGetGenericEntries(agentID, "GroupMember", out GroupMemberShips)) + { + foreach (string key in GroupMemberShips.Keys) + { + memberships.Add(GetAgentGroupMembership(requestingAgentID, agentID, UUID.Parse(key))); + } + } + + return memberships; + } + + public List GetAgentGroupRoles(UUID requestingAgentID, UUID agentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List Roles = new List(); + + Dictionary GroupRoles; + if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) + { + Dictionary MemberRoles; + if (SimianGetGenericEntries(agentID, "GroupRole" + groupID.ToString(), out MemberRoles)) + { + foreach (KeyValuePair kvp in MemberRoles) + { + GroupRolesData data = new GroupRolesData(); + data.RoleID = UUID.Parse(kvp.Key); + data.Name = GroupRoles[kvp.Key]["Name"].AsString(); + data.Description = GroupRoles[kvp.Key]["Description"].AsString(); + data.Title = GroupRoles[kvp.Key]["Title"].AsString(); + data.Powers = GroupRoles[kvp.Key]["Powers"].AsULong(); + + Roles.Add(data); + } + } + } + return Roles; + } + + public List GetGroupRoles(UUID requestingAgentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List Roles = new List(); + + Dictionary GroupRoles; + if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) + { + foreach (KeyValuePair role in GroupRoles) + { + GroupRolesData data = new GroupRolesData(); + + data.RoleID = UUID.Parse(role.Key); + + data.Name = role.Value["Name"].AsString(); + data.Description = role.Value["Description"].AsString(); + data.Title = role.Value["Title"].AsString(); + data.Powers = role.Value["Powers"].AsULong(); + + Dictionary GroupRoleMembers; + if (SimianGetGenericEntries("GroupRole" + groupID.ToString(), role.Key, out GroupRoleMembers)) + { + data.Members = GroupRoleMembers.Count; + } + else + { + data.Members = 0; + } + + Roles.Add(data); + } + } + + return Roles; + + } + + + + public List GetGroupMembers(UUID requestingAgentID, UUID GroupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List members = new List(); + + OSDMap GroupInfo; + string GroupName; + UUID GroupOwnerRoleID = UUID.Zero; + if (!SimianGetFirstGenericEntry(GroupID, "Group", out GroupName, out GroupInfo)) + { + return members; + } + GroupOwnerRoleID = GroupInfo["OwnerRoleID"].AsUUID(); + + // Locally cache group roles, since we'll be needing this data for each member + Dictionary GroupRoles; + SimianGetGenericEntries(GroupID, "GroupRole", out GroupRoles); + + // Locally cache list of group owners + Dictionary GroupOwners; + SimianGetGenericEntries("GroupRole" + GroupID.ToString(), GroupOwnerRoleID.ToString(), out GroupOwners); + + + Dictionary GroupMembers; + if (SimianGetGenericEntries("GroupMember", GroupID.ToString(), out GroupMembers)) + { + foreach (KeyValuePair member in GroupMembers) + { + GroupMembersData data = new GroupMembersData(); + + data.AgentID = member.Key; + + UUID SelectedRoleID = member.Value["SelectedRoleID"].AsUUID(); + + data.AcceptNotices = member.Value["AcceptNotices"].AsBoolean(); + data.ListInProfile = member.Value["ListInProfile"].AsBoolean(); + data.Contribution = member.Value["Contribution"].AsInteger(); + + data.IsOwner = GroupOwners.ContainsKey(member.Key); + + OSDMap GroupRoleInfo = GroupRoles[SelectedRoleID.ToString()]; + data.Title = GroupRoleInfo["Title"].AsString(); + data.AgentPowers = GroupRoleInfo["Powers"].AsULong(); + + members.Add(data); + } + } + + return members; + + } + + public List GetGroupRoleMembers(UUID requestingAgentID, UUID groupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List members = new List(); + + Dictionary GroupRoles; + if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) + { + foreach( KeyValuePair Role in GroupRoles ) + { + Dictionary GroupRoleMembers; + if( SimianGetGenericEntries("GroupRole"+groupID.ToString(), Role.Key, out GroupRoleMembers) ) + { + foreach( KeyValuePair GroupRoleMember in GroupRoleMembers ) + { + GroupRoleMembersData data = new GroupRoleMembersData(); + + data.MemberID = GroupRoleMember.Key; + data.RoleID = UUID.Parse(Role.Key); + + members.Add(data); + } + } + } + } + + return members; + } + + public List GetGroupNotices(UUID requestingAgentID, UUID GroupID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + List values = new List(); + + Dictionary Notices; + if (SimianGetGenericEntries(GroupID, "GroupNotice", out Notices)) + { + foreach (KeyValuePair Notice in Notices) + { + GroupNoticeData data = new GroupNoticeData(); + data.NoticeID = UUID.Parse(Notice.Key); + data.Timestamp = Notice.Value["TimeStamp"].AsUInteger(); + data.FromName = Notice.Value["FromName"].AsString(); + data.Subject = Notice.Value["Subject"].AsString(); + data.HasAttachment = Notice.Value["BinaryBucket"].AsBinary().Length > 0; + + //TODO: Figure out how to get this + data.AssetType = 0; + + values.Add(data); + } + } + + return values; + + } + public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap GroupNotice; + UUID GroupID; + if (SimianGetFirstGenericEntry("GroupNotice", noticeID.ToString(), out GroupID, out GroupNotice)) + { + GroupNoticeInfo data = new GroupNoticeInfo(); + data.GroupID = GroupID; + data.Message = GroupNotice["Message"].AsString(); + data.BinaryBucket = GroupNotice["BinaryBucket"].AsBinary(); + data.noticeData.NoticeID = noticeID; + data.noticeData.Timestamp = GroupNotice["TimeStamp"].AsUInteger(); + data.noticeData.FromName = GroupNotice["FromName"].AsString(); + data.noticeData.Subject = GroupNotice["Subject"].AsString(); + data.noticeData.HasAttachment = data.BinaryBucket.Length > 0; + data.noticeData.AssetType = 0; + + if (data.Message == null) + { + data.Message = string.Empty; + } + + return data; + } + return null; + } + public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + OSDMap Notice = new OSDMap(); + Notice["TimeStamp"] = OSD.FromUInteger((uint)Util.UnixTimeSinceEpoch()); + Notice["FromName"] = OSD.FromString(fromName); + Notice["Subject"] = OSD.FromString(subject); + Notice["Message"] = OSD.FromString(message); + Notice["BinaryBucket"] = OSD.FromBinary(binaryBucket); + + SimianAddGeneric(groupID, "GroupNotice", noticeID.ToString(), Notice); + + } + #endregion + + #region GroupSessionTracking + + public void ResetAgentGroupChatSessions(UUID agentID) + { + Dictionary agentSessions; + + if (SimianGetGenericEntries(agentID, "GroupSessionDropped", out agentSessions)) + { + foreach (string GroupID in agentSessions.Keys) + { + SimianRemoveGenericEntry(agentID, "GroupSessionDropped", GroupID); + } + } + + if (SimianGetGenericEntries(agentID, "GroupSessionInvited", out agentSessions)) + { + foreach (string GroupID in agentSessions.Keys) + { + SimianRemoveGenericEntry(agentID, "GroupSessionInvited", GroupID); + } + } + } + + public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) + { + OSDMap session; + return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); + } + + public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) + { + SimianAddGeneric(agentID, "GroupSessionDropped", groupID.ToString(), new OSDMap()); + } + + public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + SimianAddGeneric(agentID, "GroupSessionInvited", groupID.ToString(), new OSDMap()); + } + + public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + OSDMap session; + return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); + } + + #endregion + + private void EnsureRoleNotSelectedByMember(UUID groupID, UUID roleID, UUID userID) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + // If member's SelectedRole is roleID, change their selected role to Everyone + // before removing them from the role + OSDMap UserGroupInfo; + if (SimianGetGenericEntry(userID, "GroupMember", groupID.ToString(), out UserGroupInfo)) + { + if (UserGroupInfo["SelectedRoleID"].AsUUID() == roleID) + { + UserGroupInfo["SelectedRoleID"] = OSD.FromUUID(UUID.Zero); + } + SimianAddGeneric(userID, "GroupMember", groupID.ToString(), UserGroupInfo); + } + } + + + #region Simian Util Methods + private bool SimianAddGeneric(UUID ownerID, string type, string key, OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); + + string value = OSDParser.SerializeJsonString(map); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] value: {0}", value); + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "AddGeneric" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type }, + { "Key", key }, + { "Value", value} + }; + + + OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); + if (Response["Success"].AsBoolean()) + { + return true; + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, Response["Message"]); + return false; + } + } + + /// + /// Returns the first of possibly many entries for Owner/Type pair + /// + private bool SimianGetFirstGenericEntry(UUID ownerID, string type, out string key, out OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type); + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type } + }; + + + OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); + if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)Response["Entries"]; + if (entryArray.Count >= 1) + { + OSDMap entryMap = entryArray[0] as OSDMap; + key = entryMap["Key"].AsString(); + map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + + return true; + } + else + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); + } + key = null; + map = null; + return false; + } + private bool SimianGetFirstGenericEntry(string type, string key, out UUID ownerID, out OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); + + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Type", type }, + { "Key", key} + }; + + + OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); + if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)Response["Entries"]; + if (entryArray.Count >= 1) + { + OSDMap entryMap = entryArray[0] as OSDMap; + ownerID = entryMap["OwnerID"].AsUUID(); + map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + + return true; + } + else + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); + } + ownerID = UUID.Zero; + map = null; + return false; + } + + private bool SimianGetGenericEntry(UUID ownerID, string type, string key, out OSDMap map) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); + + NameValueCollection RequestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type }, + { "Key", key} + }; + + + OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); + if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) + { + OSDArray entryArray = (OSDArray)Response["Entries"]; + if (entryArray.Count == 1) + { + OSDMap entryMap = entryArray[0] as OSDMap; + key = entryMap["Key"].AsString(); + map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); + + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + + return true; + } + else + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); + } + map = null; + return false; + } + + private bool SimianGetGenericEntries(UUID ownerID, string type, out Dictionary maps) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name,ownerID, type); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type } + }; + + + + OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + maps = new Dictionary(); + + OSDArray entryArray = (OSDArray)response["Entries"]; + foreach (OSDMap entryMap in entryArray) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + maps.Add(entryMap["Key"].AsString(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); + } + if(maps.Count == 0) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + + return true; + } + else + { + maps = null; + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", response["Message"]); + } + return false; + } + private bool SimianGetGenericEntries(string type, string key, out Dictionary maps) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "GetGenerics" }, + { "Type", type }, + { "Key", key } + }; + + + + OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) + { + maps = new Dictionary(); + + OSDArray entryArray = (OSDArray)response["Entries"]; + foreach (OSDMap entryMap in entryArray) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); + maps.Add(entryMap["OwnerID"].AsUUID(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); + } + if (maps.Count == 0) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); + } + return true; + } + else + { + maps = null; + m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR]: Error retrieving group info ({0})", response["Message"]); + } + return false; + } + + private bool SimianRemoveGenericEntry(UUID ownerID, string type, string key) + { + if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); + + NameValueCollection requestArgs = new NameValueCollection + { + { "RequestMethod", "RemoveGeneric" }, + { "OwnerID", ownerID.ToString() }, + { "Type", type }, + { "Key", key } + }; + + + OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + if (response["Success"].AsBoolean()) + { + return true; + } + else + { + m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, response["Message"]); + return false; + } + } + #endregion + + } + +} + diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 964d0bb..2a60b00 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -47,9 +47,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class XmlRpcGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector { - private static readonly ILog m_log = - LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | GroupPowers.Accountable | @@ -61,7 +59,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_connectorEnabled = false; - private string m_serviceURL = string.Empty; + private string m_groupsServerURI = string.Empty; private bool m_disableKeepAlive = false; @@ -69,6 +67,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private string m_groupWriteKey = string.Empty; + // Used to track which agents are have dropped from a group chat session + // Should be reset per agent, on logon + // TODO: move this to Flotsam XmlRpc Service + // SessionID, List + private Dictionary> m_groupsAgentsDroppedFromChatSession = new Dictionary>(); + private Dictionary> m_groupsAgentsInvitedToChatSession = new Dictionary>(); + + #region IRegionModuleBase Members public string Name @@ -104,11 +110,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); - m_serviceURL = groupsConfig.GetString("XmlRpcServiceURL", string.Empty); - if ((m_serviceURL == null) || - (m_serviceURL == string.Empty)) + m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); + if ((m_groupsServerURI == null) || + (m_groupsServerURI == string.Empty)) { - m_log.ErrorFormat("Please specify a valid URL for XmlRpcServiceURL in OpenSim.ini, [Groups]"); + m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]"); m_connectorEnabled = false; return; } @@ -118,6 +124,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty); m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty); + + + // If we got all the config options we need, lets start'er'up m_connectorEnabled = true; } @@ -131,13 +140,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) { if (m_connectorEnabled) + { scene.RegisterModuleInterface(this); + } } public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene) { if (scene.RequestModuleInterface() == this) + { scene.UnregisterModuleInterface(this); + } } public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene) @@ -157,14 +170,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion - - #region IGroupsServicesConnector Members /// /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. /// - public UUID CreateGroup(GroupRequestID requestID, string name, string charter, bool showInList, UUID insigniaID, + public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID) { @@ -236,7 +247,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - Hashtable respData = XmlRpcCall(requestID, "groups.createGroup", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param); if (respData.Contains("error")) { @@ -248,7 +259,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return UUID.Parse((string)respData["GroupID"]); } - public void UpdateGroup(GroupRequestID requestID, UUID groupID, string charter, bool showInList, + public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish) { @@ -262,10 +273,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["AllowPublish"] = allowPublish == true ? 1 : 0; param["MaturePublish"] = maturePublish == true ? 1 : 0; - XmlRpcCall(requestID, "groups.updateGroup", param); + XmlRpcCall(requestingAgentID, "groups.updateGroup", param); } - public void AddGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, + public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -276,19 +287,19 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["Title"] = title; param["Powers"] = powers.ToString(); - XmlRpcCall(requestID, "groups.addRoleToGroup", param); + XmlRpcCall(requestingAgentID, "groups.addRoleToGroup", param); } - public void RemoveGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID) + public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) { Hashtable param = new Hashtable(); param["GroupID"] = groupID.ToString(); param["RoleID"] = roleID.ToString(); - XmlRpcCall(requestID, "groups.removeRoleFromGroup", param); + XmlRpcCall(requestingAgentID, "groups.removeRoleFromGroup", param); } - public void UpdateGroupRole(GroupRequestID requestID, UUID groupID, UUID roleID, string name, string description, + public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, string title, ulong powers) { Hashtable param = new Hashtable(); @@ -308,10 +319,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } param["Powers"] = powers.ToString(); - XmlRpcCall(requestID, "groups.updateGroupRole", param); + XmlRpcCall(requestingAgentID, "groups.updateGroupRole", param); } - public GroupRecord GetGroupRecord(GroupRequestID requestID, UUID GroupID, string GroupName) + public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID GroupID, string GroupName) { Hashtable param = new Hashtable(); if (GroupID != UUID.Zero) @@ -323,7 +334,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["Name"] = GroupName.ToString(); } - Hashtable respData = XmlRpcCall(requestID, "groups.getGroup", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param); if (respData.Contains("error")) { @@ -334,12 +345,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public GroupProfileData GetMemberGroupProfile(GroupRequestID requestID, UUID GroupID, UUID AgentID) + public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID GroupID, UUID AgentID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroup", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroup", param); if (respData.Contains("error")) { @@ -347,38 +358,35 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return new GroupProfileData(); } - GroupMembershipData MemberInfo = GetAgentGroupMembership(requestID, AgentID, GroupID); + GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, AgentID, GroupID); GroupProfileData MemberGroupProfile = GroupProfileHashtableToGroupProfileData(respData); MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; return MemberGroupProfile; - } - - - public void SetAgentActiveGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public void SetAgentActiveGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - XmlRpcCall(requestID, "groups.setAgentActiveGroup", param); + XmlRpcCall(requestingAgentID, "groups.setAgentActiveGroup", param); } - public void SetAgentActiveGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["SelectedRoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.setAgentGroupInfo", param); + XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param); } - public void SetAgentGroupInfo(GroupRequestID requestID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) + public void SetAgentGroupInfo(UUID requestingAgentID, UUID AgentID, UUID GroupID, bool AcceptNotices, bool ListInProfile) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); @@ -386,11 +394,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["AcceptNotices"] = AcceptNotices ? "1" : "0"; param["ListInProfile"] = ListInProfile ? "1" : "0"; - XmlRpcCall(requestID, "groups.setAgentGroupInfo", param); + XmlRpcCall(requestingAgentID, "groups.setAgentGroupInfo", param); } - public void AddAgentToGroupInvite(GroupRequestID requestID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) + public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); @@ -398,16 +406,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["RoleID"] = roleID.ToString(); param["GroupID"] = groupID.ToString(); - XmlRpcCall(requestID, "groups.addAgentToGroupInvite", param); + XmlRpcCall(requestingAgentID, "groups.addAgentToGroupInvite", param); } - public GroupInviteInfo GetAgentToGroupInvite(GroupRequestID requestID, UUID inviteID) + public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentToGroupInvite", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentToGroupInvite", param); if (respData.Contains("error")) { @@ -423,60 +431,59 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return inviteInfo; } - public void RemoveAgentToGroupInvite(GroupRequestID requestID, UUID inviteID) + public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) { Hashtable param = new Hashtable(); param["InviteID"] = inviteID.ToString(); - XmlRpcCall(requestID, "groups.removeAgentToGroupInvite", param); + XmlRpcCall(requestingAgentID, "groups.removeAgentToGroupInvite", param); } - public void AddAgentToGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.addAgentToGroup", param); + XmlRpcCall(requestingAgentID, "groups.addAgentToGroup", param); } - public void RemoveAgentFromGroup(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public void RemoveAgentFromGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - XmlRpcCall(requestID, "groups.removeAgentFromGroup", param); + XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroup", param); } - public void AddAgentToGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void AddAgentToGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.addAgentToGroupRole", param); + XmlRpcCall(requestingAgentID, "groups.addAgentToGroupRole", param); } - public void RemoveAgentFromGroupRole(GroupRequestID requestID, UUID AgentID, UUID GroupID, UUID RoleID) + public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); param["RoleID"] = RoleID.ToString(); - XmlRpcCall(requestID, "groups.removeAgentFromGroupRole", param); + XmlRpcCall(requestingAgentID, "groups.removeAgentFromGroupRole", param); } - - public List FindGroups(GroupRequestID requestID, string search) + public List FindGroups(UUID requestingAgentID, string search) { Hashtable param = new Hashtable(); param["Search"] = search; - Hashtable respData = XmlRpcCall(requestID, "groups.findGroups", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.findGroups", param); List findings = new List(); @@ -498,13 +505,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return findings; } - public GroupMembershipData GetAgentGroupMembership(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentGroupMembership", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMembership", param); if (respData.Contains("error")) { @@ -516,12 +523,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return data; } - public GroupMembershipData GetAgentActiveMembership(GroupRequestID requestID, UUID AgentID) + public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID AgentID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentActiveMembership", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentActiveMembership", param); if (respData.Contains("error")) { @@ -531,13 +538,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return HashTableToGroupMembershipData(respData); } - - public List GetAgentGroupMemberships(GroupRequestID requestID, UUID AgentID) + public List GetAgentGroupMemberships(UUID requestingAgentID, UUID AgentID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentGroupMemberships", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentGroupMemberships", param); List memberships = new List(); @@ -552,13 +558,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return memberships; } - public List GetAgentGroupRoles(GroupRequestID requestID, UUID AgentID, UUID GroupID) + public List GetAgentGroupRoles(UUID requestingAgentID, UUID AgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["AgentID"] = AgentID.ToString(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getAgentRoles", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getAgentRoles", param); List Roles = new List(); @@ -584,12 +590,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public List GetGroupRoles(GroupRequestID requestID, UUID GroupID) + public List GetGroupRoles(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupRoles", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoles", param); List Roles = new List(); @@ -617,12 +623,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - public List GetGroupMembers(GroupRequestID requestID, UUID GroupID) + public List GetGroupMembers(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupMembers", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupMembers", param); List members = new List(); @@ -650,12 +656,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } - public List GetGroupRoleMembers(GroupRequestID requestID, UUID GroupID) + public List GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupRoleMembers", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupRoleMembers", param); List members = new List(); @@ -674,12 +680,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return members; } - public List GetGroupNotices(GroupRequestID requestID, UUID GroupID) + public List GetGroupNotices(UUID requestingAgentID, UUID GroupID) { Hashtable param = new Hashtable(); param["GroupID"] = GroupID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupNotices", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotices", param); List values = new List(); @@ -701,12 +707,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return values; } - public GroupNoticeInfo GetGroupNotice(GroupRequestID requestID, UUID noticeID) + public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) { Hashtable param = new Hashtable(); param["NoticeID"] = noticeID.ToString(); - Hashtable respData = XmlRpcCall(requestID, "groups.getGroupNotice", param); + Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param); if (respData.Contains("error")) @@ -732,7 +738,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return data; } - public void AddGroupNotice(GroupRequestID requestID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) + public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) { string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, ""); @@ -745,7 +751,70 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param["BinaryBucket"] = binBucket; param["TimeStamp"] = ((uint)Util.UnixTimeSinceEpoch()).ToString(); - XmlRpcCall(requestID, "groups.addGroupNotice", param); + XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param); + } + + + + #endregion + + #region GroupSessionTracking + + public void ResetAgentGroupChatSessions(UUID agentID) + { + foreach (List agentList in m_groupsAgentsDroppedFromChatSession.Values) + { + agentList.Remove(agentID); + } + } + + public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + // If we're tracking this group, and we can find them in the tracking, then they've been invited + return m_groupsAgentsInvitedToChatSession.ContainsKey(groupID) + && m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID); + } + + public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) + { + // If we're tracking drops for this group, + // and we find them, well... then they've dropped + return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID) + && m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID); + } + + public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) + { + if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + // If not in dropped list, add + if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID); + } + } + } + + public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + // Add Session Status if it doesn't exist for this session + CreateGroupChatSessionTracking(groupID); + + // If nessesary, remove from dropped list + if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID); + } + } + + private void CreateGroupChatSessionTracking(UUID groupID) + { + if (!m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + m_groupsAgentsDroppedFromChatSession.Add(groupID, new List()); + m_groupsAgentsInvitedToChatSession.Add(groupID, new List()); + } + } #endregion @@ -778,7 +847,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private GroupRecord GroupProfileHashtableToGroupRecord(Hashtable groupProfile) { - GroupRecord group = new GroupRecord(); group.GroupID = UUID.Parse((string)groupProfile["GroupID"]); group.GroupName = groupProfile["Name"].ToString(); @@ -797,6 +865,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return group; } + private static GroupMembershipData HashTableToGroupMembershipData(Hashtable respData) { GroupMembershipData data = new GroupMembershipData(); @@ -829,6 +898,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups data.MembershipFee = int.Parse((string)respData["MembershipFee"]); data.OpenEnrollment = ((string)respData["OpenEnrollment"] == "1"); data.ShowInList = ((string)respData["ShowInList"] == "1"); + return data; } @@ -837,15 +907,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Encapsulate the XmlRpc call to standardize security and error handling. /// - private Hashtable XmlRpcCall(GroupRequestID requestID, string function, Hashtable param) + private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param) { - if (requestID == null) - { - requestID = new GroupRequestID(); - } - param.Add("RequestingAgentID", requestID.AgentID.ToString()); - param.Add("RequestingAgentUserService", requestID.UserServiceURL); - param.Add("RequestingSessionID", requestID.SessionID.ToString()); + string UserService; + UUID SessionID; + GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); + param.Add("requestingAgentID", requestingAgentID.ToString()); + param.Add("RequestingAgentUserService", UserService); + param.Add("RequestingSessionID", SessionID.ToString()); param.Add("ReadKey", m_groupReadKey); @@ -862,7 +931,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups try { - resp = req.Send(m_serviceURL, 10000); + resp = req.Send(m_groupsServerURI, 10000); } catch (Exception e) { @@ -936,15 +1005,49 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } + + /// + /// Group Request Tokens are an attempt to allow the groups service to authenticate + /// requests. + /// TODO: This broke after the big grid refactor, either find a better way, or discard this + /// + /// + /// + private void GetClientGroupRequestID(UUID AgentID, out string UserServiceURL, out UUID SessionID) + { + UserServiceURL = ""; + SessionID = UUID.Zero; - } - public class GroupNoticeInfo - { - public GroupNoticeData noticeData = new GroupNoticeData(); - public UUID GroupID = UUID.Zero; - public string Message = string.Empty; - public byte[] BinaryBucket = new byte[0]; + // Need to rework this based on changes to User Services + /* + UserAccount userAccount = m_accountService.GetUserAccount(UUID.Zero,AgentID); + if (userAccount == null) + { + // This should be impossible. If I've been passed a reference to a client + // that client should be registered with the UserService. So something + // is horribly wrong somewhere. + + m_log.WarnFormat("[GROUPS]: Could not find a UserServiceURL for {0}", AgentID); + + } + else if (userProfile is ForeignUserProfileData) + { + // They aren't from around here + ForeignUserProfileData fupd = (ForeignUserProfileData)userProfile; + UserServiceURL = fupd.UserServerURI; + SessionID = fupd.CurrentAgent.SessionID; + + } + else + { + // They're a local user, use this: + UserServiceURL = m_commManager.NetworkServersInfo.UserURL; + SessionID = userProfile.CurrentAgent.SessionID; + } + */ + } + } } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 5214718..4a8629f 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -1302,10 +1302,18 @@ ;MessagingModule = GroupsMessagingModule ;MessagingEnabled = true - ; Service connector to Groups Service [Select One] - ; XmlRpc Service Connector to the Flotsam XmlRpc Groups Service Implementation + ; Service connector to Groups Service [Select One] ServicesConnectorModule + + + ; Simian Grid Service for Groups + ;ServicesConnectorModule = SimianGroupsServicesConnector + ;GroupsServerURI = http://mygridserver.com:82/Grid/ + + ; XmlRpc Service Connector to the Flotsam XmlRpc Groups Service settings ;ServicesConnectorModule = XmlRpcGroupsServicesConnector - ;XmlRpcServiceURL = http://yourxmlrpcserver.com/xmlrpc.php + ;GroupsServerURI = http://yourxmlrpcserver.com/xmlrpc.php + + ; XmlRpc Service Settings ;XmlRpcServiceReadKey = 1234 ;XmlRpcServiceWriteKey = 1234 diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index 6da0f1e..8fc2425 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -20,6 +20,12 @@ ; change this to your grid-wide grid server ; GridServerURI = "http://mygridserver.com:8003" +[Groups] + ; + ; change this to your grid-wide groups server + ; + GroupsServerURI = "http://mygridserver.com:82/Grid/" + [Modules] ;; Choose 0 or 1 cache modules, and the corresponding config file, if it exists. -- cgit v1.1 From 91cfce3758a7021f483bb653371693cc3d64580a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 Apr 2010 16:14:02 -0700 Subject: back port groups changes Signed-off-by: Melanie --- .../Framework/Interfaces/IGroupsMessagingModule.cs | 73 ++ .../SimianGroupsServicesConnectorModule.cs | 1329 -------------------- bin/OpenSim.ini.example | 5 - 3 files changed, 73 insertions(+), 1334 deletions(-) create mode 100644 OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs delete mode 100644 OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs new file mode 100644 index 0000000..f158236 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IGroupsMessagingModule.cs @@ -0,0 +1,73 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Interfaces +{ + /// + /// Provide mechanisms for messaging groups. + /// + /// + /// TODO: Provide a mechanism for receiving group messages as well as sending them + /// + public interface IGroupsMessagingModule + { + /// + /// Start a group chat session. + /// + /// You must call this before calling SendMessageToGroup(). If a chat session for this group is already taking + /// place then the agent will added to that session. + /// + /// A UUID that represents the agent being added. If you are agentless (e.g. you are + /// a region module), then you can use any random ID. + /// + /// + /// The ID for the group to join. Currently, the session ID used is identical to the + /// group ID. + /// + /// + /// True if the chat session was started successfully, false otherwise. + /// + bool StartGroupChatSession(UUID agentID, UUID groupID); + + /// + /// Send a message to an entire group. + /// + /// + /// The message itself. The fields that must be populated are + /// + /// imSessionID - Populate this with the group ID (session ID and group ID are currently identical) + /// fromAgentName - Populate this with whatever arbitrary name you want to show up in the chat dialog + /// message - The message itself + /// dialog - This must be (byte)InstantMessageDialog.SessionSend + /// + /// + void SendMessageToGroup(GridInstantMessage im, UUID groupID); + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs deleted file mode 100644 index 669373f..0000000 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Reflection; - -using Nwc.XmlRpc; - -using log4net; -using Mono.Addins; -using Nini.Config; - -using OpenMetaverse; -using OpenMetaverse.StructuredData; - -using OpenSim.Framework; -using OpenSim.Framework.Communications; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Services.Interfaces; - -/*************************************************************************** - * Simian Data Map - * =============== - * - * OwnerID -> Type -> Key - * ----------------------- - * - * UserID -> Group -> ActiveGroup - * + GroupID - * - * UserID -> GroupSessionDropped -> GroupID - * UserID -> GroupSessionInvited -> GroupID - * - * UserID -> GroupMember -> GroupID - * + SelectedRoleID [UUID] - * + AcceptNotices [bool] - * + ListInProfile [bool] - * + Contribution [int] - * - * UserID -> GroupRole[GroupID] -> RoleID - * - * - * GroupID -> Group -> GroupName - * + Charter - * + ShowInList - * + InsigniaID - * + MembershipFee - * + OpenEnrollment - * + AllowPublish - * + MaturePublish - * + FounderID - * + EveryonePowers - * + OwnerRoleID - * + OwnersPowers - * - * GroupID -> GroupRole -> RoleID - * + Name - * + Description - * + Title - * + Powers - * - * GroupID -> GroupMemberInvite -> InviteID - * + AgentID - * + RoleID - * - * GroupID -> GroupNotice -> NoticeID - * + TimeStamp [uint] - * + FromName [string] - * + Subject [string] - * + Message [string] - * + BinaryBucket [byte[]] - * - * */ - -namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups -{ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class SimianGroupsServicesConnectorModule : ISharedRegionModule, IGroupsServicesConnector - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | - GroupPowers.Accountable | - GroupPowers.JoinChat | - GroupPowers.AllowVoiceChat | - GroupPowers.ReceiveNotices | - GroupPowers.StartProposal | - GroupPowers.VoteOnProposal; - - // Would this be cleaner as (GroupPowers)ulong.MaxValue; - public const GroupPowers m_DefaultOwnerPowers = GroupPowers.Accountable - | GroupPowers.AllowEditLand - | GroupPowers.AllowFly - | GroupPowers.AllowLandmark - | GroupPowers.AllowRez - | GroupPowers.AllowSetHome - | GroupPowers.AllowVoiceChat - | GroupPowers.AssignMember - | GroupPowers.AssignMemberLimited - | GroupPowers.ChangeActions - | GroupPowers.ChangeIdentity - | GroupPowers.ChangeMedia - | GroupPowers.ChangeOptions - | GroupPowers.CreateRole - | GroupPowers.DeedObject - | GroupPowers.DeleteRole - | GroupPowers.Eject - | GroupPowers.FindPlaces - | GroupPowers.Invite - | GroupPowers.JoinChat - | GroupPowers.LandChangeIdentity - | GroupPowers.LandDeed - | GroupPowers.LandDivideJoin - | GroupPowers.LandEdit - | GroupPowers.LandEjectAndFreeze - | GroupPowers.LandGardening - | GroupPowers.LandManageAllowed - | GroupPowers.LandManageBanned - | GroupPowers.LandManagePasses - | GroupPowers.LandOptions - | GroupPowers.LandRelease - | GroupPowers.LandSetSale - | GroupPowers.ModerateChat - | GroupPowers.ObjectManipulate - | GroupPowers.ObjectSetForSale - | GroupPowers.ReceiveNotices - | GroupPowers.RemoveMember - | GroupPowers.ReturnGroupOwned - | GroupPowers.ReturnGroupSet - | GroupPowers.ReturnNonGroup - | GroupPowers.RoleProperties - | GroupPowers.SendNotices - | GroupPowers.SetLandingPoint - | GroupPowers.StartProposal - | GroupPowers.VoteOnProposal; - - private bool m_connectorEnabled = false; - - private string m_groupsServerURI = string.Empty; - - private bool m_debugEnabled = false; - - // private IUserAccountService m_accountService = null; - - - #region IRegionModuleBase Members - - public string Name - { - get { return "SimianGroupsServicesConnector"; } - } - - // this module is not intended to be replaced, but there should only be 1 of them. - public Type ReplaceableInterface - { - get { return null; } - } - - public void Initialise(IConfigSource config) - { - IConfig groupsConfig = config.Configs["Groups"]; - - if (groupsConfig == null) - { - // Do not run this module by default. - return; - } - else - { - // if groups aren't enabled, we're not needed. - // if we're not specified as the connector to use, then we're not wanted - if ((groupsConfig.GetBoolean("Enabled", false) == false) - || (groupsConfig.GetString("ServicesConnectorModule", "Default") != Name)) - { - m_connectorEnabled = false; - return; - } - - m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); - - m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); - if ((m_groupsServerURI == null) || - (m_groupsServerURI == string.Empty)) - { - m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]"); - m_connectorEnabled = false; - return; - } - - // If we got all the config options we need, lets start'er'up - m_connectorEnabled = true; - - m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); - - } - } - - public void Close() - { - m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); - } - - public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) - { - if (m_connectorEnabled) - { - scene.RegisterModuleInterface(this); - } - } - - public void RemoveRegion(OpenSim.Region.Framework.Scenes.Scene scene) - { - if (scene.RequestModuleInterface() == this) - { - scene.UnregisterModuleInterface(this); - } - } - - public void RegionLoaded(OpenSim.Region.Framework.Scenes.Scene scene) - { - // TODO: May want to consider listenning for Agent Connections so we can pre-cache group info - // scene.EventManager.OnNewClient += OnNewClient; - } - - #endregion - - #region ISharedRegionModule Members - - public void PostInitialise() - { - // NoOp - } - - #endregion - - - - - #region IGroupsServicesConnector Members - - /// - /// Create a Group, including Everyone and Owners Role, place FounderID in both groups, select Owner as selected role, and newly created group as agent's active role. - /// - public UUID CreateGroup(UUID requestingAgentID, string name, string charter, bool showInList, UUID insigniaID, - int membershipFee, bool openEnrollment, bool allowPublish, - bool maturePublish, UUID founderID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - UUID GroupID = UUID.Random(); - UUID OwnerRoleID = UUID.Random(); - - OSDMap GroupInfoMap = new OSDMap(); - GroupInfoMap["Charter"] = OSD.FromString(charter); - GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); - GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); - GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); - GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); - GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); - GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); - GroupInfoMap["FounderID"] = OSD.FromUUID(founderID); - GroupInfoMap["EveryonePowers"] = OSD.FromULong((ulong)m_DefaultEveryonePowers); - GroupInfoMap["OwnerRoleID"] = OSD.FromUUID(OwnerRoleID); - GroupInfoMap["OwnersPowers"] = OSD.FromULong((ulong)m_DefaultOwnerPowers); - - if(SimianAddGeneric(GroupID, "Group", name, GroupInfoMap)) - { - AddGroupRole(requestingAgentID, GroupID, UUID.Zero, "Everyone", "Members of " + name, "Member of " + name, (ulong)m_DefaultEveryonePowers); - AddGroupRole(requestingAgentID, GroupID, OwnerRoleID, "Owners", "Owners of " + name, "Owner of " + name, (ulong)m_DefaultOwnerPowers); - - AddAgentToGroup(requestingAgentID, requestingAgentID, GroupID, OwnerRoleID); - - return GroupID; - } - else - { - return UUID.Zero; - } - } - - - public void UpdateGroup(UUID requestingAgentID, UUID groupID, string charter, bool showInList, - UUID insigniaID, int membershipFee, bool openEnrollment, - bool allowPublish, bool maturePublish) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - // TODO: Check to make sure requestingAgentID has permission to update group - - string GroupName; - OSDMap GroupInfoMap; - if( SimianGetFirstGenericEntry(groupID, "GroupInfo", out GroupName, out GroupInfoMap) ) - { - GroupInfoMap["Charter"] = OSD.FromString(charter); - GroupInfoMap["ShowInList"] = OSD.FromBoolean(showInList); - GroupInfoMap["InsigniaID"] = OSD.FromUUID(insigniaID); - GroupInfoMap["MembershipFee"] = OSD.FromInteger(0); - GroupInfoMap["OpenEnrollment"] = OSD.FromBoolean(openEnrollment); - GroupInfoMap["AllowPublish"] = OSD.FromBoolean(allowPublish); - GroupInfoMap["MaturePublish"] = OSD.FromBoolean(maturePublish); - - SimianAddGeneric(groupID, "Group", GroupName, GroupInfoMap); - } - - } - - - public void AddGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, - string title, ulong powers) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupRoleInfo = new OSDMap(); - GroupRoleInfo["Name"] = OSD.FromString(name); - GroupRoleInfo["Description"] = OSD.FromString(description); - GroupRoleInfo["Title"] = OSD.FromString(title); - GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); - - // TODO: Add security, make sure that requestingAgentID has permision to add roles - SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); - } - - public void RemoveGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // TODO: Add security - - // Can't delete the Everyone Role - if (roleID != UUID.Zero) - { - // Remove all GroupRole Members from Role - Dictionary GroupRoleMembers; - string GroupRoleMemberType = "GroupRole" + groupID.ToString(); - if (SimianGetGenericEntries(GroupRoleMemberType, roleID.ToString(), out GroupRoleMembers)) - { - foreach(UUID UserID in GroupRoleMembers.Keys) - { - EnsureRoleNotSelectedByMember(groupID, roleID, UserID); - - SimianRemoveGenericEntry(UserID, GroupRoleMemberType, roleID.ToString()); - } - } - - // Remove role - SimianRemoveGenericEntry(groupID, "GroupRole", roleID.ToString()); - } - } - - - public void UpdateGroupRole(UUID requestingAgentID, UUID groupID, UUID roleID, string name, string description, - string title, ulong powers) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // TODO: Security, check that requestingAgentID is allowed to update group roles - - OSDMap GroupRoleInfo; - if (SimianGetGenericEntry(groupID, "GroupRole", roleID.ToString(), out GroupRoleInfo)) - { - if (name != null) - { - GroupRoleInfo["Name"] = OSD.FromString(name); - } - if (description != null) - { - GroupRoleInfo["Description"] = OSD.FromString(description); - } - if (title != null) - { - GroupRoleInfo["Title"] = OSD.FromString(title); - } - GroupRoleInfo["Powers"] = OSD.FromULong((ulong)powers); - - } - - - SimianAddGeneric(groupID, "GroupRole", roleID.ToString(), GroupRoleInfo); - } - - public GroupRecord GetGroupRecord(UUID requestingAgentID, UUID groupID, string groupName) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupInfoMap = null; - if (groupID != UUID.Zero) - { - if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out GroupInfoMap)) - { - return null; - } - } - else if ((groupName != null) && (groupName != string.Empty)) - { - if (!SimianGetFirstGenericEntry("Group", groupName, out groupID, out GroupInfoMap)) - { - return null; - } - } - - GroupRecord GroupInfo = new GroupRecord(); - - GroupInfo.GroupID = groupID; - GroupInfo.GroupName = groupName; - GroupInfo.Charter = GroupInfoMap["Charter"].AsString(); - GroupInfo.ShowInList = GroupInfoMap["ShowInList"].AsBoolean(); - GroupInfo.GroupPicture = GroupInfoMap["InsigniaID"].AsUUID(); - GroupInfo.MembershipFee = GroupInfoMap["MembershipFee"].AsInteger(); - GroupInfo.OpenEnrollment = GroupInfoMap["OpenEnrollment"].AsBoolean(); - GroupInfo.AllowPublish = GroupInfoMap["AllowPublish"].AsBoolean(); - GroupInfo.MaturePublish = GroupInfoMap["MaturePublish"].AsBoolean(); - GroupInfo.FounderID = GroupInfoMap["FounderID"].AsUUID(); - GroupInfo.OwnerRoleID = GroupInfoMap["OwnerRoleID"].AsUUID(); - - return GroupInfo; - - } - - public GroupProfileData GetMemberGroupProfile(UUID requestingAgentID, UUID groupID, UUID memberID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap groupProfile; - string groupName; - if (!SimianGetFirstGenericEntry(groupID, "Group", out groupName, out groupProfile)) - { - // GroupProfileData is not nullable - return new GroupProfileData(); - } - - GroupProfileData MemberGroupProfile = new GroupProfileData(); - MemberGroupProfile.GroupID = groupID; - MemberGroupProfile.Name = groupName; - - if (groupProfile["Charter"] != null) - { - MemberGroupProfile.Charter = groupProfile["Charter"].AsString(); - } - - MemberGroupProfile.ShowInList = groupProfile["ShowInList"].AsString() == "1"; - MemberGroupProfile.InsigniaID = groupProfile["InsigniaID"].AsUUID(); - MemberGroupProfile.MembershipFee = groupProfile["MembershipFee"].AsInteger(); - MemberGroupProfile.OpenEnrollment = groupProfile["OpenEnrollment"].AsBoolean(); - MemberGroupProfile.AllowPublish = groupProfile["AllowPublish"].AsBoolean(); - MemberGroupProfile.MaturePublish = groupProfile["MaturePublish"].AsBoolean(); - MemberGroupProfile.FounderID = groupProfile["FounderID"].AsUUID();; - MemberGroupProfile.OwnerRole = groupProfile["OwnerRoleID"].AsUUID(); - - Dictionary Members; - if (SimianGetGenericEntries("GroupMember",groupID.ToString(), out Members)) - { - MemberGroupProfile.GroupMembershipCount = Members.Count; - } - - Dictionary Roles; - if (SimianGetGenericEntries(groupID, "GroupRole", out Roles)) - { - MemberGroupProfile.GroupRolesCount = Roles.Count; - } - - // TODO: Get Group Money balance from somewhere - // group.Money = 0; - - GroupMembershipData MemberInfo = GetAgentGroupMembership(requestingAgentID, memberID, groupID); - - MemberGroupProfile.MemberTitle = MemberInfo.GroupTitle; - MemberGroupProfile.PowersMask = MemberInfo.GroupPowers; - - return MemberGroupProfile; - } - - public void SetAgentActiveGroup(UUID requestingAgentID, UUID agentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap ActiveGroup = new OSDMap(); - ActiveGroup.Add("GroupID", OSD.FromUUID(groupID)); - SimianAddGeneric(agentID, "Group", "ActiveGroup", ActiveGroup); - } - - public void SetAgentActiveGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupMemberInfo; - if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) - { - GroupMemberInfo = new OSDMap(); - } - - GroupMemberInfo["SelectedRoleID"] = OSD.FromUUID(roleID); - SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); - } - - public void SetAgentGroupInfo(UUID requestingAgentID, UUID agentID, UUID groupID, bool acceptNotices, bool listInProfile) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupMemberInfo; - if (!SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out GroupMemberInfo)) - { - GroupMemberInfo = new OSDMap(); - } - - GroupMemberInfo["AcceptNotices"] = OSD.FromBoolean(acceptNotices); - GroupMemberInfo["ListInProfile"] = OSD.FromBoolean(listInProfile); - GroupMemberInfo["Contribution"] = OSD.FromInteger(0); - GroupMemberInfo["SelectedRole"] = OSD.FromUUID(UUID.Zero); - SimianAddGeneric(agentID, "GroupMember", groupID.ToString(), GroupMemberInfo); - } - - public void AddAgentToGroupInvite(UUID requestingAgentID, UUID inviteID, UUID groupID, UUID roleID, UUID agentID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap Invite = new OSDMap(); - Invite["AgentID"] = OSD.FromUUID(agentID); - Invite["RoleID"] = OSD.FromUUID(roleID); - - SimianAddGeneric(groupID, "GroupMemberInvite", inviteID.ToString(), Invite); - } - - public GroupInviteInfo GetAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupMemberInvite; - UUID GroupID; - if (!SimianGetFirstGenericEntry("GroupMemberInvite", inviteID.ToString(), out GroupID, out GroupMemberInvite)) - { - return null; - } - - GroupInviteInfo inviteInfo = new GroupInviteInfo(); - inviteInfo.InviteID = inviteID; - inviteInfo.GroupID = GroupID; - inviteInfo.AgentID = GroupMemberInvite["AgentID"].AsUUID(); - inviteInfo.RoleID = GroupMemberInvite["RoleID"].AsUUID(); - - return inviteInfo; - } - - public void RemoveAgentToGroupInvite(UUID requestingAgentID, UUID inviteID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - GroupInviteInfo invite = GetAgentToGroupInvite(requestingAgentID, inviteID); - SimianRemoveGenericEntry(invite.GroupID, "GroupMemberInvite", inviteID.ToString()); - } - - public void AddAgentToGroup(UUID requestingAgentID, UUID AgentID, UUID GroupID, UUID RoleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // Setup Agent/Group information - SetAgentGroupInfo(requestingAgentID, AgentID, GroupID, true, true); - - // Add agent to Everyone Group - AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, UUID.Zero); - - // Add agent to Specified Role - AddAgentToGroupRole(requestingAgentID, AgentID, GroupID, RoleID); - - // Set selected role in this group to specified role - SetAgentActiveGroupRole(requestingAgentID, AgentID, GroupID, RoleID); - } - - public void RemoveAgentFromGroup(UUID requestingAgentID, UUID agentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // If current active group is the group the agent is being removed from, change their group to UUID.Zero - GroupMembershipData memberActiveMembership = GetAgentActiveMembership(requestingAgentID, agentID); - if (memberActiveMembership.GroupID == groupID) - { - SetAgentActiveGroup(agentID, agentID, UUID.Zero); - } - - // Remove Group Member information for this group - SimianRemoveGenericEntry(agentID, "GroupMember", groupID.ToString()); - - // By using a Simian Generics Type consisting of a prefix and a groupID, - // combined with RoleID as key allows us to get a list of roles a particular member - // of a group is assigned to. - string GroupRoleMemberType = "GroupRole" + groupID.ToString(); - - // Take Agent out of all other group roles - Dictionary GroupRoles; - if (SimianGetGenericEntries(agentID, GroupRoleMemberType, out GroupRoles)) - { - foreach (string roleID in GroupRoles.Keys) - { - SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID); - } - } - } - - public void AddAgentToGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - SimianAddGeneric(agentID, "GroupRole" + groupID.ToString(), roleID.ToString(), new OSDMap()); - } - - public void RemoveAgentFromGroupRole(UUID requestingAgentID, UUID agentID, UUID groupID, UUID roleID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // Cannot remove members from the Everyone Role - if (roleID != UUID.Zero) - { - EnsureRoleNotSelectedByMember(groupID, roleID, agentID); - - string GroupRoleMemberType = "GroupRole" + groupID.ToString(); - SimianRemoveGenericEntry(agentID, GroupRoleMemberType, roleID.ToString()); - } - } - - public List FindGroups(UUID requestingAgentID, string search) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List findings = new List(); - - NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "Type", "Group" }, - { "Key", search }, - { "Fuzzy", "1" } - }; - - - OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); - if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) - { - OSDArray entryArray = (OSDArray)response["Entries"]; - foreach (OSDMap entryMap in entryArray) - { - DirGroupsReplyData data = new DirGroupsReplyData(); - data.groupID = entryMap["OwnerID"].AsUUID(); - data.groupName = entryMap["Key"].AsString(); - - // TODO: is there a better way to do this? - Dictionary Members; - if (SimianGetGenericEntries("GroupMember", data.groupID.ToString(), out Members)) - { - data.members = Members.Count; - } - else - { - data.members = 0; - } - - // TODO: sort results? - // data.searchOrder = order; - - findings.Add(data); - } - } - - - return findings; - } - - public GroupMembershipData GetAgentGroupMembership(UUID requestingAgentID, UUID agentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - GroupMembershipData data = new GroupMembershipData(); - - /////////////////////////////// - // Agent Specific Information: - // - OSDMap UserActiveGroup; - if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) - { - data.Active = UserActiveGroup["GroupID"].AsUUID().Equals(groupID); - } - - OSDMap UserGroupMemberInfo; - if( SimianGetGenericEntry(agentID, "GroupMember", groupID.ToString(), out UserGroupMemberInfo) ) - { - data.AcceptNotices = UserGroupMemberInfo["AcceptNotices"].AsBoolean(); - data.Contribution = UserGroupMemberInfo["Contribution"].AsInteger(); - data.ListInProfile = UserGroupMemberInfo["ListInProfile"].AsBoolean(); - data.ActiveRole = UserGroupMemberInfo["SelectedRoleID"].AsUUID(); - - /////////////////////////////// - // Role Specific Information: - // - - OSDMap GroupRoleInfo; - if( SimianGetGenericEntry(groupID, "GroupRole", data.ActiveRole.ToString(), out GroupRoleInfo) ) - { - data.GroupTitle = GroupRoleInfo["Title"].AsString(); - data.GroupPowers = GroupRoleInfo["Powers"].AsULong(); - } - } - - /////////////////////////////// - // Group Specific Information: - // - OSDMap GroupInfo; - string GroupName; - if( SimianGetFirstGenericEntry(groupID, "Group", out GroupName, out GroupInfo) ) - { - data.GroupID = groupID; - data.AllowPublish = GroupInfo["AllowPublish"].AsBoolean(); - data.Charter = GroupInfo["Charter"].AsString(); - data.FounderID = GroupInfo["FounderID"].AsUUID(); - data.GroupName = GroupName; - data.GroupPicture = GroupInfo["InsigniaID"].AsUUID(); - data.MaturePublish = GroupInfo["MaturePublish"].AsBoolean(); - data.MembershipFee = GroupInfo["MembershipFee"].AsInteger(); - data.OpenEnrollment = GroupInfo["OpenEnrollment"].AsBoolean(); - data.ShowInList = GroupInfo["ShowInList"].AsBoolean(); - } - - return data; - } - - public GroupMembershipData GetAgentActiveMembership(UUID requestingAgentID, UUID agentID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - UUID GroupID = UUID.Zero; - OSDMap UserActiveGroup; - if (SimianGetGenericEntry(agentID, "Group", "ActiveGroup", out UserActiveGroup)) - { - GroupID = UserActiveGroup["GroupID"].AsUUID(); - } - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Active GroupID : {0}", GroupID.ToString()); - return GetAgentGroupMembership(requestingAgentID, agentID, GroupID); - } - - public List GetAgentGroupMemberships(UUID requestingAgentID, UUID agentID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List memberships = new List(); - - Dictionary GroupMemberShips; - if (SimianGetGenericEntries(agentID, "GroupMember", out GroupMemberShips)) - { - foreach (string key in GroupMemberShips.Keys) - { - memberships.Add(GetAgentGroupMembership(requestingAgentID, agentID, UUID.Parse(key))); - } - } - - return memberships; - } - - public List GetAgentGroupRoles(UUID requestingAgentID, UUID agentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List Roles = new List(); - - Dictionary GroupRoles; - if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) - { - Dictionary MemberRoles; - if (SimianGetGenericEntries(agentID, "GroupRole" + groupID.ToString(), out MemberRoles)) - { - foreach (KeyValuePair kvp in MemberRoles) - { - GroupRolesData data = new GroupRolesData(); - data.RoleID = UUID.Parse(kvp.Key); - data.Name = GroupRoles[kvp.Key]["Name"].AsString(); - data.Description = GroupRoles[kvp.Key]["Description"].AsString(); - data.Title = GroupRoles[kvp.Key]["Title"].AsString(); - data.Powers = GroupRoles[kvp.Key]["Powers"].AsULong(); - - Roles.Add(data); - } - } - } - return Roles; - } - - public List GetGroupRoles(UUID requestingAgentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List Roles = new List(); - - Dictionary GroupRoles; - if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) - { - foreach (KeyValuePair role in GroupRoles) - { - GroupRolesData data = new GroupRolesData(); - - data.RoleID = UUID.Parse(role.Key); - - data.Name = role.Value["Name"].AsString(); - data.Description = role.Value["Description"].AsString(); - data.Title = role.Value["Title"].AsString(); - data.Powers = role.Value["Powers"].AsULong(); - - Dictionary GroupRoleMembers; - if (SimianGetGenericEntries("GroupRole" + groupID.ToString(), role.Key, out GroupRoleMembers)) - { - data.Members = GroupRoleMembers.Count; - } - else - { - data.Members = 0; - } - - Roles.Add(data); - } - } - - return Roles; - - } - - - - public List GetGroupMembers(UUID requestingAgentID, UUID GroupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List members = new List(); - - OSDMap GroupInfo; - string GroupName; - UUID GroupOwnerRoleID = UUID.Zero; - if (!SimianGetFirstGenericEntry(GroupID, "Group", out GroupName, out GroupInfo)) - { - return members; - } - GroupOwnerRoleID = GroupInfo["OwnerRoleID"].AsUUID(); - - // Locally cache group roles, since we'll be needing this data for each member - Dictionary GroupRoles; - SimianGetGenericEntries(GroupID, "GroupRole", out GroupRoles); - - // Locally cache list of group owners - Dictionary GroupOwners; - SimianGetGenericEntries("GroupRole" + GroupID.ToString(), GroupOwnerRoleID.ToString(), out GroupOwners); - - - Dictionary GroupMembers; - if (SimianGetGenericEntries("GroupMember", GroupID.ToString(), out GroupMembers)) - { - foreach (KeyValuePair member in GroupMembers) - { - GroupMembersData data = new GroupMembersData(); - - data.AgentID = member.Key; - - UUID SelectedRoleID = member.Value["SelectedRoleID"].AsUUID(); - - data.AcceptNotices = member.Value["AcceptNotices"].AsBoolean(); - data.ListInProfile = member.Value["ListInProfile"].AsBoolean(); - data.Contribution = member.Value["Contribution"].AsInteger(); - - data.IsOwner = GroupOwners.ContainsKey(member.Key); - - OSDMap GroupRoleInfo = GroupRoles[SelectedRoleID.ToString()]; - data.Title = GroupRoleInfo["Title"].AsString(); - data.AgentPowers = GroupRoleInfo["Powers"].AsULong(); - - members.Add(data); - } - } - - return members; - - } - - public List GetGroupRoleMembers(UUID requestingAgentID, UUID groupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List members = new List(); - - Dictionary GroupRoles; - if (SimianGetGenericEntries(groupID, "GroupRole", out GroupRoles)) - { - foreach( KeyValuePair Role in GroupRoles ) - { - Dictionary GroupRoleMembers; - if( SimianGetGenericEntries("GroupRole"+groupID.ToString(), Role.Key, out GroupRoleMembers) ) - { - foreach( KeyValuePair GroupRoleMember in GroupRoleMembers ) - { - GroupRoleMembersData data = new GroupRoleMembersData(); - - data.MemberID = GroupRoleMember.Key; - data.RoleID = UUID.Parse(Role.Key); - - members.Add(data); - } - } - } - } - - return members; - } - - public List GetGroupNotices(UUID requestingAgentID, UUID GroupID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - List values = new List(); - - Dictionary Notices; - if (SimianGetGenericEntries(GroupID, "GroupNotice", out Notices)) - { - foreach (KeyValuePair Notice in Notices) - { - GroupNoticeData data = new GroupNoticeData(); - data.NoticeID = UUID.Parse(Notice.Key); - data.Timestamp = Notice.Value["TimeStamp"].AsUInteger(); - data.FromName = Notice.Value["FromName"].AsString(); - data.Subject = Notice.Value["Subject"].AsString(); - data.HasAttachment = Notice.Value["BinaryBucket"].AsBinary().Length > 0; - - //TODO: Figure out how to get this - data.AssetType = 0; - - values.Add(data); - } - } - - return values; - - } - public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap GroupNotice; - UUID GroupID; - if (SimianGetFirstGenericEntry("GroupNotice", noticeID.ToString(), out GroupID, out GroupNotice)) - { - GroupNoticeInfo data = new GroupNoticeInfo(); - data.GroupID = GroupID; - data.Message = GroupNotice["Message"].AsString(); - data.BinaryBucket = GroupNotice["BinaryBucket"].AsBinary(); - data.noticeData.NoticeID = noticeID; - data.noticeData.Timestamp = GroupNotice["TimeStamp"].AsUInteger(); - data.noticeData.FromName = GroupNotice["FromName"].AsString(); - data.noticeData.Subject = GroupNotice["Subject"].AsString(); - data.noticeData.HasAttachment = data.BinaryBucket.Length > 0; - data.noticeData.AssetType = 0; - - if (data.Message == null) - { - data.Message = string.Empty; - } - - return data; - } - return null; - } - public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - OSDMap Notice = new OSDMap(); - Notice["TimeStamp"] = OSD.FromUInteger((uint)Util.UnixTimeSinceEpoch()); - Notice["FromName"] = OSD.FromString(fromName); - Notice["Subject"] = OSD.FromString(subject); - Notice["Message"] = OSD.FromString(message); - Notice["BinaryBucket"] = OSD.FromBinary(binaryBucket); - - SimianAddGeneric(groupID, "GroupNotice", noticeID.ToString(), Notice); - - } - #endregion - - #region GroupSessionTracking - - public void ResetAgentGroupChatSessions(UUID agentID) - { - Dictionary agentSessions; - - if (SimianGetGenericEntries(agentID, "GroupSessionDropped", out agentSessions)) - { - foreach (string GroupID in agentSessions.Keys) - { - SimianRemoveGenericEntry(agentID, "GroupSessionDropped", GroupID); - } - } - - if (SimianGetGenericEntries(agentID, "GroupSessionInvited", out agentSessions)) - { - foreach (string GroupID in agentSessions.Keys) - { - SimianRemoveGenericEntry(agentID, "GroupSessionInvited", GroupID); - } - } - } - - public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) - { - OSDMap session; - return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); - } - - public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) - { - SimianAddGeneric(agentID, "GroupSessionDropped", groupID.ToString(), new OSDMap()); - } - - public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) - { - SimianAddGeneric(agentID, "GroupSessionInvited", groupID.ToString(), new OSDMap()); - } - - public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) - { - OSDMap session; - return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); - } - - #endregion - - private void EnsureRoleNotSelectedByMember(UUID groupID, UUID roleID, UUID userID) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - // If member's SelectedRole is roleID, change their selected role to Everyone - // before removing them from the role - OSDMap UserGroupInfo; - if (SimianGetGenericEntry(userID, "GroupMember", groupID.ToString(), out UserGroupInfo)) - { - if (UserGroupInfo["SelectedRoleID"].AsUUID() == roleID) - { - UserGroupInfo["SelectedRoleID"] = OSD.FromUUID(UUID.Zero); - } - SimianAddGeneric(userID, "GroupMember", groupID.ToString(), UserGroupInfo); - } - } - - - #region Simian Util Methods - private bool SimianAddGeneric(UUID ownerID, string type, string key, OSDMap map) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); - - string value = OSDParser.SerializeJsonString(map); - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] value: {0}", value); - - NameValueCollection RequestArgs = new NameValueCollection - { - { "RequestMethod", "AddGeneric" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type }, - { "Key", key }, - { "Value", value} - }; - - - OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); - if (Response["Success"].AsBoolean()) - { - return true; - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, Response["Message"]); - return false; - } - } - - /// - /// Returns the first of possibly many entries for Owner/Type pair - /// - private bool SimianGetFirstGenericEntry(UUID ownerID, string type, out string key, out OSDMap map) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type); - - NameValueCollection RequestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type } - }; - - - OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); - if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) - { - OSDArray entryArray = (OSDArray)Response["Entries"]; - if (entryArray.Count >= 1) - { - OSDMap entryMap = entryArray[0] as OSDMap; - key = entryMap["Key"].AsString(); - map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - - return true; - } - else - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); - } - key = null; - map = null; - return false; - } - private bool SimianGetFirstGenericEntry(string type, string key, out UUID ownerID, out OSDMap map) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); - - - NameValueCollection RequestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "Type", type }, - { "Key", key} - }; - - - OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); - if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) - { - OSDArray entryArray = (OSDArray)Response["Entries"]; - if (entryArray.Count >= 1) - { - OSDMap entryMap = entryArray[0] as OSDMap; - ownerID = entryMap["OwnerID"].AsUUID(); - map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - - return true; - } - else - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); - } - ownerID = UUID.Zero; - map = null; - return false; - } - - private bool SimianGetGenericEntry(UUID ownerID, string type, string key, out OSDMap map) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); - - NameValueCollection RequestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type }, - { "Key", key} - }; - - - OSDMap Response = WebUtil.PostToService(m_groupsServerURI, RequestArgs); - if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) - { - OSDArray entryArray = (OSDArray)Response["Entries"]; - if (entryArray.Count == 1) - { - OSDMap entryMap = entryArray[0] as OSDMap; - key = entryMap["Key"].AsString(); - map = (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString()); - - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - - return true; - } - else - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", Response["Message"]); - } - map = null; - return false; - } - - private bool SimianGetGenericEntries(UUID ownerID, string type, out Dictionary maps) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name,ownerID, type); - - NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type } - }; - - - - OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); - if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) - { - maps = new Dictionary(); - - OSDArray entryArray = (OSDArray)response["Entries"]; - foreach (OSDMap entryMap in entryArray) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - maps.Add(entryMap["Key"].AsString(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); - } - if(maps.Count == 0) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - - return true; - } - else - { - maps = null; - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error retrieving group info ({0})", response["Message"]); - } - return false; - } - private bool SimianGetGenericEntries(string type, string key, out Dictionary maps) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2})", System.Reflection.MethodBase.GetCurrentMethod().Name, type, key); - - NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "GetGenerics" }, - { "Type", type }, - { "Key", key } - }; - - - - OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); - if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) - { - maps = new Dictionary(); - - OSDArray entryArray = (OSDArray)response["Entries"]; - foreach (OSDMap entryMap in entryArray) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Generics Result {0}", entryMap["Value"].AsString()); - maps.Add(entryMap["OwnerID"].AsUUID(), (OSDMap)OSDParser.DeserializeJson(entryMap["Value"].AsString())); - } - if (maps.Count == 0) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] No Generics Results"); - } - return true; - } - else - { - maps = null; - m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR]: Error retrieving group info ({0})", response["Message"]); - } - return false; - } - - private bool SimianRemoveGenericEntry(UUID ownerID, string type, string key) - { - if (m_debugEnabled) m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] {0} called ({1},{2},{3})", System.Reflection.MethodBase.GetCurrentMethod().Name, ownerID, type, key); - - NameValueCollection requestArgs = new NameValueCollection - { - { "RequestMethod", "RemoveGeneric" }, - { "OwnerID", ownerID.ToString() }, - { "Type", type }, - { "Key", key } - }; - - - OSDMap response = WebUtil.PostToService(m_groupsServerURI, requestArgs); - if (response["Success"].AsBoolean()) - { - return true; - } - else - { - m_log.WarnFormat("[SIMIAN GROUPS CONNECTOR]: Error {0}, {1}, {2}, {3}", ownerID, type, key, response["Message"]); - return false; - } - } - #endregion - - } - -} - diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 4a8629f..0df122d 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -1304,11 +1304,6 @@ ; Service connector to Groups Service [Select One] ServicesConnectorModule - - ; Simian Grid Service for Groups - ;ServicesConnectorModule = SimianGroupsServicesConnector - ;GroupsServerURI = http://mygridserver.com:82/Grid/ - ; XmlRpc Service Connector to the Flotsam XmlRpc Groups Service settings ;ServicesConnectorModule = XmlRpcGroupsServicesConnector ;GroupsServerURI = http://yourxmlrpcserver.com/xmlrpc.php -- cgit v1.1 From e0f9b1a69994be3e5771ebdcb0f2c253f67150db Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 5 May 2010 21:12:02 +0200 Subject: Removed a test for a "can't happen" case. ParentGroup is never null anymore. --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d216eff..6ab3c62 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2033,14 +2033,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); - if (part.ParentGroup == null) - { - if ((targetPos.z < ground) && disable_underground_movement) - targetPos.z = ground; - LSL_Vector real_vec = SetPosAdjust(currentPos, targetPos); - part.UpdateOffSet(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); - } - else if (part.ParentGroup.RootPart == part) + if (part.ParentGroup.RootPart == part) { if ((targetPos.z < ground) && disable_underground_movement) targetPos.z = ground; @@ -2050,7 +2043,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - //it's late... i think this is right ? if (llVecDist(new LSL_Vector(0,0,0), targetPos) <= 10.0f) { part.OffsetPosition = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z); -- cgit v1.1 From 65775b87e5000a07634240ab8ce39aaecd30d1e6 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 5 May 2010 23:06:36 +0200 Subject: Add a XMLRPC method to remotely set the login level for the LLLoginService. This requires a special XMLRPC call, which has to supply the credentials of a god user (User level >= 200). Disabled by default. Also Adds a configuration option to set the initial permitted login level. --- OpenSim/Server/Handlers/Login/LLLoginHandlers.cs | 37 +++++++++++++++ .../Handlers/Login/LLLoginServiceInConnector.cs | 1 + OpenSim/Services/Interfaces/ILoginService.cs | 1 + OpenSim/Services/LLLoginService/LLLoginService.cs | 53 ++++++++++++++++++++++ bin/Robust.ini.example | 1 + 5 files changed, 93 insertions(+) diff --git a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs index daf2704..83b3e31 100644 --- a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs +++ b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs @@ -99,6 +99,43 @@ namespace OpenSim.Server.Handlers.Login } + public XmlRpcResponse HandleXMLRPCSetLoginLevel(XmlRpcRequest request, IPEndPoint remoteClient) + { + Hashtable requestData = (Hashtable)request.Params[0]; + + if (requestData != null) + { + if (requestData.ContainsKey("first") && requestData["first"] != null && + requestData.ContainsKey("last") && requestData["last"] != null && + requestData.ContainsKey("level") && requestData["level"] != null && + requestData.ContainsKey("passwd") && requestData["passwd"] != null) + { + string first = requestData["first"].ToString(); + string last = requestData["last"].ToString(); + string passwd = requestData["passwd"].ToString(); + int level = Int32.Parse(requestData["level"].ToString()); + + m_log.InfoFormat("[LOGIN]: XMLRPC Set Level to {2} Requested by {0} {1}", first, last, level); + + Hashtable reply = m_LocalService.SetLevel(first, last, passwd, level, remoteClient); + + XmlRpcResponse response = new XmlRpcResponse(); + response.Value = reply; + + return response; + + } + } + + XmlRpcResponse failResponse = new XmlRpcResponse(); + Hashtable failHash = new Hashtable(); + failHash["success"] = "false"; + failResponse.Value = failHash; + + return failResponse; + + } + public OSD HandleLLSDLogin(OSD request, IPEndPoint remoteClient) { if (request.Type == OSDType.Map) diff --git a/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs b/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs index e24055b..67e8392 100644 --- a/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs +++ b/OpenSim/Server/Handlers/Login/LLLoginServiceInConnector.cs @@ -88,6 +88,7 @@ namespace OpenSim.Server.Handlers.Login { LLLoginHandlers loginHandlers = new LLLoginHandlers(m_LoginService); server.AddXmlRPCHandler("login_to_simulator", loginHandlers.HandleXMLRPCLogin, false); + server.AddXmlRPCHandler("set_login_level", loginHandlers.HandleXMLRPCSetLoginLevel, false); server.SetDefaultLLSDHandler(loginHandlers.HandleLLSDLogin); } diff --git a/OpenSim/Services/Interfaces/ILoginService.cs b/OpenSim/Services/Interfaces/ILoginService.cs index 49efbe2..513ab4a 100644 --- a/OpenSim/Services/Interfaces/ILoginService.cs +++ b/OpenSim/Services/Interfaces/ILoginService.cs @@ -48,6 +48,7 @@ namespace OpenSim.Services.Interfaces public interface ILoginService { LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID, IPEndPoint clientIP); + Hashtable SetLevel(string firstName, string lastName, string passwd, int level, IPEndPoint clientIP); } diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 5301140..5b950e0 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections; using System.Collections.Generic; using System.Net; using System.Reflection; @@ -70,6 +71,7 @@ namespace OpenSim.Services.LLLoginService private bool m_RequireInventory; protected int m_MinLoginLevel; private string m_GatekeeperURL; + private bool m_AllowRemoteSetLoginLevel; IConfig m_LoginServerConfig; @@ -93,6 +95,8 @@ namespace OpenSim.Services.LLLoginService m_DefaultRegionName = m_LoginServerConfig.GetString("DefaultRegion", String.Empty); m_WelcomeMessage = m_LoginServerConfig.GetString("WelcomeMessage", "Welcome to OpenSim!"); m_RequireInventory = m_LoginServerConfig.GetBoolean("RequireInventory", true); + m_AllowRemoteSetLoginLevel = m_LoginServerConfig.GetBoolean("AllowRemoteSetLoginLevel", false); + m_MinLoginLevel = m_LoginServerConfig.GetInt("MinLoginLevel", 0); m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty); // These are required; the others aren't @@ -147,6 +151,55 @@ namespace OpenSim.Services.LLLoginService { } + public Hashtable SetLevel(string firstName, string lastName, string passwd, int level, IPEndPoint clientIP) + { + Hashtable response = new Hashtable(); + response["success"] = "false"; + + if (!m_AllowRemoteSetLoginLevel) + return response; + + try + { + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, firstName, lastName); + if (account == null) + { + m_log.InfoFormat("[LLOGIN SERVICE]: Set Level failed, user {0} {1} not found", firstName, lastName); + return response; + } + + if (account.UserLevel < 200) + { + m_log.InfoFormat("[LLOGIN SERVICE]: Set Level failed, reason: user level too low"); + return response; + } + + // + // Authenticate this user + // + // We don't support clear passwords here + // + string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30); + UUID secureSession = UUID.Zero; + if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession))) + { + m_log.InfoFormat("[LLOGIN SERVICE]: SetLevel failed, reason: authentication failed"); + return response; + } + } + catch (Exception e) + { + m_log.Error("[LLOGIN SERVICE]: SetLevel failed, exception " + e.ToString()); + return response; + } + + m_MinLoginLevel = level; + m_log.InfoFormat("[LLOGIN SERVICE]: Login level set to {0} by {1} {2}", level, firstName, lastName); + + response["success"] = true; + return response; + } + public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID, IPEndPoint clientIP) { bool success = false; diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index cfc08bc..2679523 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -126,6 +126,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 FriendsService = "OpenSim.Services.FriendsService.dll:FriendsService" WelcomeMessage = "Welcome, Avatar!" + AllowRemoteSetLoginLevel = "false"; [GridInfoService] -- cgit v1.1 From 733a07e061cdcb6095677758a264ba976bb94b93 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 6 May 2010 00:34:49 +0200 Subject: Plumb the viewer version string through into AgentCircuitData. Now all that is left os to figure out what black magic turns AgentCircuitData into AgentData and then copy that into the ScenePresence, where m_Viewer is already added with this commit and waits for the data. --- OpenSim/Framework/AgentCircuitData.cs | 11 +++++++++++ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 6 ++++++ OpenSim/Server/Handlers/Login/LLLoginHandlers.cs | 4 ++-- OpenSim/Services/Interfaces/ILoginService.cs | 2 +- OpenSim/Services/LLLoginService/LLLoginService.cs | 13 +++++++------ 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index 353e5bf..783a833 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -108,6 +108,11 @@ namespace OpenSim.Framework public string ServiceSessionID = string.Empty; /// + /// Viewer's version string + /// + public string Viewer; + + /// /// Position the Agent's Avatar starts in the region /// public Vector3 startpos; @@ -136,6 +141,7 @@ namespace OpenSim.Framework BaseFolder = new UUID(cAgent.BaseFolder); CapsPath = cAgent.CapsPath; ChildrenCapSeeds = cAgent.ChildrenCapSeeds; + Viewer = cAgent.Viewer; } /// @@ -173,6 +179,7 @@ namespace OpenSim.Framework args["service_session_id"] = OSD.FromString(ServiceSessionID); args["start_pos"] = OSD.FromString(startpos.ToString()); args["appearance_serial"] = OSD.FromInteger(Appearance.Serial); + args["viewer"] = OSD.FromString(Viewer); if (Appearance != null) { @@ -272,6 +279,8 @@ namespace OpenSim.Framework SessionID = args["session_id"].AsUUID(); if (args["service_session_id"] != null) ServiceSessionID = args["service_session_id"].AsString(); + if (args["viewer"] != null) + Viewer = args["viewer"].AsString(); if (args["start_pos"] != null) Vector3.TryParse(args["start_pos"].AsString(), out startpos); @@ -339,6 +348,7 @@ namespace OpenSim.Framework public float startposx; public float startposy; public float startposz; + public string Viewer; public sAgentCircuitData() { @@ -360,6 +370,7 @@ namespace OpenSim.Framework BaseFolder = cAgent.BaseFolder.Guid; CapsPath = cAgent.CapsPath; ChildrenCapSeeds = cAgent.ChildrenCapSeeds; + Viewer = cAgent.Viewer; } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 562232c..987180b 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -227,6 +227,7 @@ namespace OpenSim.Region.Framework.Scenes private int m_lastColCount = -1; //KF: Look for Collision chnages private int m_updateCount = 0; //KF: Update Anims for a while private static readonly int UPDATE_COUNT = 10; // how many frames to update for + private string m_Viewer = String.Empty; private const int NumMovementsBetweenRayCast = 5; @@ -664,6 +665,11 @@ namespace OpenSim.Region.Framework.Scenes set { m_flyDisabled = value; } } + public string Viewer + { + get { return m_Viewer; } + } + #endregion #region Constructor(s) diff --git a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs index 83b3e31..c9bf996 100644 --- a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs +++ b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs @@ -86,7 +86,7 @@ namespace OpenSim.Server.Handlers.Login m_log.InfoFormat("[LOGIN]: XMLRPC Login Requested for {0} {1}, starting in {2}, using {3}", first, last, startLocation, clientVersion); LoginResponse reply = null; - reply = m_LocalService.Login(first, last, passwd, startLocation, scopeID, remoteClient); + reply = m_LocalService.Login(first, last, passwd, startLocation, scopeID, clientVersion, remoteClient); XmlRpcResponse response = new XmlRpcResponse(); response.Value = reply.ToHashtable(); @@ -157,7 +157,7 @@ namespace OpenSim.Server.Handlers.Login m_log.Info("[LOGIN]: LLSD Login Requested for: '" + map["first"].AsString() + "' '" + map["last"].AsString() + "' / " + startLocation); LoginResponse reply = null; - reply = m_LocalService.Login(map["first"].AsString(), map["last"].AsString(), map["passwd"].AsString(), startLocation, scopeID, remoteClient); + reply = m_LocalService.Login(map["first"].AsString(), map["last"].AsString(), map["passwd"].AsString(), startLocation, scopeID, String.Empty, remoteClient); return reply.ToOSDMap(); } diff --git a/OpenSim/Services/Interfaces/ILoginService.cs b/OpenSim/Services/Interfaces/ILoginService.cs index 513ab4a..9e57339 100644 --- a/OpenSim/Services/Interfaces/ILoginService.cs +++ b/OpenSim/Services/Interfaces/ILoginService.cs @@ -47,7 +47,7 @@ namespace OpenSim.Services.Interfaces public interface ILoginService { - LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID, IPEndPoint clientIP); + LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID, string clientVersion, IPEndPoint clientIP); Hashtable SetLevel(string firstName, string lastName, string passwd, int level, IPEndPoint clientIP); } diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 5b950e0..9efdd11 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -200,7 +200,7 @@ namespace OpenSim.Services.LLLoginService return response; } - public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID, IPEndPoint clientIP) + public LoginResponse Login(string firstName, string lastName, string passwd, string startLocation, UUID scopeID, string clientVersion, IPEndPoint clientIP) { bool success = false; UUID session = UUID.Random(); @@ -326,7 +326,7 @@ namespace OpenSim.Services.LLLoginService // Instantiate/get the simulation interface and launch an agent at the destination // string reason = string.Empty; - AgentCircuitData aCircuit = LaunchAgentAtGrid(gatekeeper, destination, account, avatar, session, secureSession, position, where, out where, out reason); + AgentCircuitData aCircuit = LaunchAgentAtGrid(gatekeeper, destination, account, avatar, session, secureSession, position, where, clientVersion, out where, out reason); if (aCircuit == null) { @@ -592,7 +592,7 @@ namespace OpenSim.Services.LLLoginService } protected AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarData avatar, - UUID session, UUID secureSession, Vector3 position, string currentWhere, out string where, out string reason) + UUID session, UUID secureSession, Vector3 position, string currentWhere, string viewer, out string where, out string reason) { where = currentWhere; ISimulationService simConnector = null; @@ -632,7 +632,7 @@ namespace OpenSim.Services.LLLoginService if (m_UserAgentService == null && simConnector != null) { circuitCode = (uint)Util.RandomClass.Next(); ; - aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position); + aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, viewer); success = LaunchAgentDirectly(simConnector, destination, aCircuit, out reason); if (!success && m_GridService != null) { @@ -657,7 +657,7 @@ namespace OpenSim.Services.LLLoginService if (m_UserAgentService != null) { circuitCode = (uint)Util.RandomClass.Next(); ; - aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position); + aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, viewer); success = LaunchAgentIndirectly(gatekeeper, destination, aCircuit, out reason); if (!success && m_GridService != null) { @@ -686,7 +686,7 @@ namespace OpenSim.Services.LLLoginService } private AgentCircuitData MakeAgent(GridRegion region, UserAccount account, - AvatarData avatar, UUID session, UUID secureSession, uint circuit, Vector3 position) + AvatarData avatar, UUID session, UUID secureSession, uint circuit, Vector3 position, string viewer) { AgentCircuitData aCircuit = new AgentCircuitData(); @@ -707,6 +707,7 @@ namespace OpenSim.Services.LLLoginService aCircuit.SecureSessionID = secureSession; aCircuit.SessionID = session; aCircuit.startpos = position; + aCircuit.Viewer = viewer; SetServiceURLs(aCircuit, account); return aCircuit; -- cgit v1.1 From 2d9a20529d6818093747eb764d86efa11f3874d5 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 6 May 2010 00:54:21 +0200 Subject: Plumb Viewer version into ScenePresence for initial login. It's still not carried along --- OpenSim/Region/Framework/Scenes/Scene.cs | 1 + OpenSim/Region/Framework/Scenes/ScenePresence.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0ca5948..bebd463 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2680,6 +2680,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = CreateAndAddScenePresence(client); if (aCircuit != null) sp.Appearance = aCircuit.Appearance; + sp.Viewer = aCircuit.Viewer; // HERE!!! Do the initial attachments right here // first agent upon login is a root agent by design. diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 987180b..f649dfe 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -668,6 +668,7 @@ namespace OpenSim.Region.Framework.Scenes public string Viewer { get { return m_Viewer; } + set { m_Viewer = value; } } #endregion -- cgit v1.1 From 02dea4ce580a08a9a4119ed063ed36704bb44825 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 6 May 2010 02:02:12 +0200 Subject: Remove the m_Viewer variable and make the property a shortcut to the proper field in AgentCircuitData instead --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 +---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 897fda6..0ca5948 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2679,10 +2679,7 @@ namespace OpenSim.Region.Framework.Scenes ScenePresence sp = CreateAndAddScenePresence(client); if (aCircuit != null) - { sp.Appearance = aCircuit.Appearance; - sp.Viewer = aCircuit.Viewer; - } // HERE!!! Do the initial attachments right here // first agent upon login is a root agent by design. diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index f649dfe..cb24784 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -227,8 +227,6 @@ namespace OpenSim.Region.Framework.Scenes private int m_lastColCount = -1; //KF: Look for Collision chnages private int m_updateCount = 0; //KF: Update Anims for a while private static readonly int UPDATE_COUNT = 10; // how many frames to update for - private string m_Viewer = String.Empty; - private const int NumMovementsBetweenRayCast = 5; private bool CameraConstraintActive; @@ -667,8 +665,7 @@ namespace OpenSim.Region.Framework.Scenes public string Viewer { - get { return m_Viewer; } - set { m_Viewer = value; } + get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; } } #endregion -- cgit v1.1 From 69d0201d4c3c62cda339eda35c15978837a7e2a3 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 6 May 2010 16:38:23 +0100 Subject: Revert "Patch from mcortez: Update groups, add ALPHA Siman grid connector for groups" Causes an exception within HttpServer, headers have already been sent. This reverts commit 8187fccd258bf0936d3db8663844e07a7b81e9fc. --- .../Avatar/XmlRpcGroups/GroupsMessagingModule.cs | 274 ++++++++++----------- .../Avatar/XmlRpcGroups/GroupsModule.cs | 3 +- .../XmlRpcGroups/IGroupsServicesConnector.cs | 6 + .../SimianGroupsServicesConnectorModule.cs | 142 +++++++++-- .../XmlRpcGroupsServicesConnectorModule.cs | 217 ++++++++++++---- 5 files changed, 436 insertions(+), 206 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 00fe5df..185d44d 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -28,41 +28,30 @@ using System; using System.Collections.Generic; using System.Reflection; - - using log4net; using Mono.Addins; using Nini.Config; - using OpenMetaverse; using OpenMetaverse.StructuredData; - using OpenSim.Framework; using OpenSim.Region.CoreModules.Framework.EventQueue; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; - using Caps = OpenSim.Framework.Capabilities.Caps; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] - public class GroupsMessagingModule : ISharedRegionModule + public class GroupsMessagingModule : ISharedRegionModule, IGroupsMessagingModule { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_sceneList = new List(); private IMessageTransferModule m_msgTransferModule = null; - private IGroupsModule m_groupsModule = null; - - // TODO: Move this off to the Groups Server - public Dictionary> m_agentsInGroupSession = new Dictionary>(); - public Dictionary> m_agentsDroppedSession = new Dictionary>(); - + private IGroupsServicesConnector m_groupData = null; // Config Options private bool m_groupMessagingEnabled = false; @@ -108,8 +97,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(Scene scene) { - // NoOp + if (!m_groupMessagingEnabled) + return; + + scene.RegisterModuleInterface(this); } + public void RegionLoaded(Scene scene) { if (!m_groupMessagingEnabled) @@ -117,12 +110,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - m_groupsModule = scene.RequestModuleInterface(); + m_groupData = scene.RequestModuleInterface(); // No groups module, no groups messaging - if (m_groupsModule == null) + if (m_groupData == null) { - m_log.Error("[GROUPS-MESSAGING]: Could not get IGroupsModule, GroupsMessagingModule is now disabled."); + m_log.Error("[GROUPS-MESSAGING]: Could not get IGroupsServicesConnector, GroupsMessagingModule is now disabled."); Close(); m_groupMessagingEnabled = false; return; @@ -144,7 +137,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - + scene.EventManager.OnClientLogin += OnClientLogin; } public void RemoveRegion(Scene scene) @@ -172,7 +165,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_sceneList.Clear(); - m_groupsModule = null; + m_groupData = null; m_msgTransferModule = null; } @@ -197,8 +190,84 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion + /// + /// Not really needed, but does confirm that the group exists. + /// + public bool StartGroupChatSession(UUID agentID, UUID groupID) + { + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + GroupRecord groupInfo = m_groupData.GetGroupRecord(agentID, groupID, null); + + if (groupInfo != null) + { + return true; + } + else + { + return false; + } + } + + public void SendMessageToGroup(GridInstantMessage im, UUID groupID) + { + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + + + foreach (GroupMembersData member in m_groupData.GetGroupMembers(UUID.Zero, groupID)) + { + if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) + { + // Don't deliver messages to people who have dropped this session + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); + continue; + } + + // Copy Message + GridInstantMessage msg = new GridInstantMessage(); + msg.imSessionID = groupID.Guid; + msg.fromAgentName = im.fromAgentName; + msg.message = im.message; + msg.dialog = im.dialog; + msg.offline = im.offline; + msg.ParentEstateID = im.ParentEstateID; + msg.Position = im.Position; + msg.RegionID = im.RegionID; + msg.binaryBucket = im.binaryBucket; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + + msg.fromAgentID = im.fromAgentID; + msg.fromGroup = true; + + msg.toAgentID = member.AgentID.Guid; + + IClientAPI client = GetActiveClient(member.AgentID); + if (client == null) + { + // If they're not local, forward across the grid + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); + m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); + } + else + { + // Deliver locally, directly + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); + ProcessMessageFromGroupSession(msg); + } + } + } + #region SimGridEventHandlers + void OnClientLogin(IClientAPI client) + { + if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: OnInstantMessage registered for {0}", client.Name); + + + } + private void OnNewClient(IClientAPI client) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: OnInstantMessage registered for {0}", client.Name); @@ -236,42 +305,46 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Session message from {0} going to agent {1}", msg.fromAgentName, msg.toAgentID); + UUID AgentID = new UUID(msg.fromAgentID); + UUID GroupID = new UUID(msg.imSessionID); + switch (msg.dialog) { case (byte)InstantMessageDialog.SessionAdd: - AddAgentToGroupSession(msg.fromAgentID, msg.imSessionID); + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); break; case (byte)InstantMessageDialog.SessionDrop: - RemoveAgentFromGroupSession(msg.fromAgentID, msg.imSessionID); + m_groupData.AgentDroppedFromGroupChatSession(AgentID, GroupID); break; case (byte)InstantMessageDialog.SessionSend: - if (!m_agentsInGroupSession.ContainsKey(msg.toAgentID) - && !m_agentsDroppedSession.ContainsKey(msg.toAgentID)) + if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID) + && !m_groupData.hasAgentBeenInvitedToGroupChatSession(AgentID, GroupID) + ) { // Agent not in session and hasn't dropped from session // Add them to the session for now, and Invite them - AddAgentToGroupSession(msg.toAgentID, msg.imSessionID); + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); UUID toAgentID = new UUID(msg.toAgentID); IClientAPI activeClient = GetActiveClient(toAgentID); if (activeClient != null) { - UUID groupID = new UUID(msg.fromAgentID); - - GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID); + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); if (groupInfo != null) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Sending chatterbox invite instant message"); // Force? open the group session dialog??? + // and simultanously deliver the message, so we don't need to do a seperate client.SendInstantMessage(msg); IEventQueue eq = activeClient.Scene.RequestModuleInterface(); eq.ChatterboxInvitation( - groupID + GroupID , groupInfo.GroupName , new UUID(msg.fromAgentID) - , msg.message, new UUID(msg.toAgentID) + , msg.message + , new UUID(msg.toAgentID) , msg.fromAgentName , msg.dialog , msg.timestamp @@ -285,7 +358,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ); eq.ChatterBoxSessionAgentListUpdates( - new UUID(groupID) + new UUID(GroupID) , new UUID(msg.fromAgentID) , new UUID(msg.toAgentID) , false //canVoiceChat @@ -295,7 +368,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } } - else if (!m_agentsDroppedSession.ContainsKey(msg.toAgentID)) + else if (!m_groupData.hasAgentDroppedGroupChatSession(AgentID, GroupID)) { // User hasn't dropped, so they're in the session, // maybe we should deliver it. @@ -321,56 +394,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups #endregion - #region ClientEvents - - private void RemoveAgentFromGroupSession(Guid agentID, Guid sessionID) - { - if (m_agentsInGroupSession.ContainsKey(sessionID)) - { - // If in session remove - if (m_agentsInGroupSession[sessionID].Contains(agentID)) - { - m_agentsInGroupSession[sessionID].Remove(agentID); - } - - // If not in dropped list, add - if (!m_agentsDroppedSession[sessionID].Contains(agentID)) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Dropped {1} from session {0}", sessionID, agentID); - m_agentsDroppedSession[sessionID].Add(agentID); - } - } - } - - private void AddAgentToGroupSession(Guid agentID, Guid sessionID) - { - // Add Session Status if it doesn't exist for this session - CreateGroupSessionTracking(sessionID); - - // If nessesary, remove from dropped list - if (m_agentsDroppedSession[sessionID].Contains(agentID)) - { - m_agentsDroppedSession[sessionID].Remove(agentID); - } - - // If nessesary, add to in session list - if (!m_agentsInGroupSession[sessionID].Contains(agentID)) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Added {1} to session {0}", sessionID, agentID); - m_agentsInGroupSession[sessionID].Add(agentID); - } - } - - private void CreateGroupSessionTracking(Guid sessionID) - { - if (!m_agentsInGroupSession.ContainsKey(sessionID)) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Creating session tracking for : {0}", sessionID); - m_agentsInGroupSession.Add(sessionID, new List()); - m_agentsDroppedSession.Add(sessionID, new List()); - } - } + #region ClientEvents private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { if (m_debugEnabled) @@ -383,21 +408,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Start group IM session if ((im.dialog == (byte)InstantMessageDialog.SessionGroupStart)) { - UUID groupID = new UUID(im.toAgentID); + if (m_debugEnabled) m_log.InfoFormat("[GROUPS-MESSAGING]: imSessionID({0}) toAgentID({1})", im.imSessionID, im.toAgentID); - GroupRecord groupInfo = m_groupsModule.GetGroupRecord(groupID); + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); + + GroupRecord groupInfo = m_groupData.GetGroupRecord(UUID.Zero, GroupID, null); + if (groupInfo != null) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Start Group Session for {0}", groupInfo.GroupName); - - AddAgentToGroupSession(im.fromAgentID, im.imSessionID); + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); - ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, groupID); + ChatterBoxSessionStartReplyViaCaps(remoteClient, groupInfo.GroupName, GroupID); IEventQueue queue = remoteClient.Scene.RequestModuleInterface(); queue.ChatterBoxSessionAgentListUpdates( - new UUID(groupID) - , new UUID(im.fromAgentID) + GroupID + , AgentID , new UUID(im.toAgentID) , false //canVoiceChat , false //isModerator @@ -409,64 +436,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups // Send a message from locally connected client to a group if ((im.dialog == (byte)InstantMessageDialog.SessionSend)) { - UUID groupID = new UUID(im.toAgentID); + UUID GroupID = new UUID(im.imSessionID); + UUID AgentID = new UUID(im.fromAgentID); + + if (m_debugEnabled) + m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", GroupID, im.imSessionID.ToString()); - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Send message to session for group {0} with session ID {1}", groupID, im.imSessionID.ToString()); + //If this agent is sending a message, then they want to be in the session + m_groupData.AgentInvitedToGroupChatSession(AgentID, GroupID); - SendMessageToGroup(im, groupID); + SendMessageToGroup(im, GroupID); } } #endregion - private void SendMessageToGroup(GridInstantMessage im, UUID groupID) - { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); - - foreach (GroupMembersData member in m_groupsModule.GroupMembersRequest(null, groupID)) - { - if (!m_agentsDroppedSession.ContainsKey(im.imSessionID) || m_agentsDroppedSession[im.imSessionID].Contains(member.AgentID.Guid)) - { - // Don't deliver messages to people who have dropped this session - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} has dropped session, not delivering to them", member.AgentID); - continue; - } - - // Copy Message - GridInstantMessage msg = new GridInstantMessage(); - msg.imSessionID = im.imSessionID; - msg.fromAgentName = im.fromAgentName; - msg.message = im.message; - msg.dialog = im.dialog; - msg.offline = im.offline; - msg.ParentEstateID = im.ParentEstateID; - msg.Position = im.Position; - msg.RegionID = im.RegionID; - msg.binaryBucket = im.binaryBucket; - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - - // Updat Pertinate fields to make it a "group message" - msg.fromAgentID = groupID.Guid; - msg.fromGroup = true; - - msg.toAgentID = member.AgentID.Guid; - - IClientAPI client = GetActiveClient(member.AgentID); - if (client == null) - { - // If they're not local, forward across the grid - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Delivering to {0} via Grid", member.AgentID); - m_msgTransferModule.SendInstantMessage(msg, delegate(bool success) { }); - } - else - { - // Deliver locally, directly - if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: Passing to ProcessMessageFromGroupSession to deliver to {0} locally", client.Name); - ProcessMessageFromGroupSession(msg); - } - } - } - void ChatterBoxSessionStartReplyViaCaps(IClientAPI remoteClient, string groupName, UUID groupID) { if (m_debugEnabled) m_log.DebugFormat("[GROUPS-MESSAGING]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); @@ -518,6 +502,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private IClientAPI GetActiveClient(UUID agentID) { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Looking for local client {0}", agentID); + IClientAPI child = null; // Try root avatar first @@ -529,16 +515,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ScenePresence user = (ScenePresence)scene.Entities[agentID]; if (!user.IsChildAgent) { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found root agent for client : {0}", user.ControllingClient.Name); return user.ControllingClient; } else { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Found child agent for client : {0}", user.ControllingClient.Name); child = user.ControllingClient; } } } // If we didn't find a root, then just return whichever child we found, or null if none + if (child == null) + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Could not find local client for agent : {0}", agentID); + } + else + { + if (m_debugEnabled) m_log.WarnFormat("[GROUPS-MESSAGING]: Returning child agent for client : {0}", child.Name); + } return child; } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index b2b8110..56c0d98 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -176,7 +176,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups scene.EventManager.OnNewClient += OnNewClient; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; - // The InstantMessageModule itself doesn't do this, // so lets see if things explode if we don't do it // scene.EventManager.OnClientClosed += OnClientClosed; @@ -510,7 +509,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups IClientAPI ejectee = GetActiveClient(ejecteeID); if (ejectee != null) { - UUID groupID = new UUID(im.fromAgentID); + UUID groupID = new UUID(im.imSessionID); ejectee.SendAgentDropGroup(groupID); } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs index 6487967..a046e09 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs @@ -71,6 +71,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups void AddGroupNotice(UUID RequestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket); GroupNoticeInfo GetGroupNotice(UUID RequestingAgentID, UUID noticeID); List GetGroupNotices(UUID RequestingAgentID, UUID GroupID); + + void ResetAgentGroupChatSessions(UUID agentID); + bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID); + bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID); + void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID); + void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID); } public class GroupInviteInfo diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs index bc05b0f..9363205 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/SimianGroupsServicesConnectorModule.cs @@ -55,6 +55,9 @@ using OpenSim.Services.Interfaces; * UserID -> Group -> ActiveGroup * + GroupID * + * UserID -> GroupSessionDropped -> GroupID + * UserID -> GroupSessionInvited -> GroupID + * * UserID -> GroupMember -> GroupID * + SelectedRoleID [UUID] * + AcceptNotices [bool] @@ -63,6 +66,7 @@ using OpenSim.Services.Interfaces; * * UserID -> GroupRole[GroupID] -> RoleID * + * * GroupID -> Group -> GroupName * + Charter * + ShowInList @@ -159,10 +163,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_connectorEnabled = false; - private string m_serviceURL = string.Empty; + private string m_groupsServerURI = string.Empty; private bool m_debugEnabled = false; + private ExpiringCache m_memoryCache; + private int m_cacheTimeout = 30; + // private IUserAccountService m_accountService = null; @@ -199,17 +206,33 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); + m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Initializing {0}", this.Name); - m_serviceURL = groupsConfig.GetString("XmlRpcServiceURL", string.Empty); - if ((m_serviceURL == null) || - (m_serviceURL == string.Empty)) + m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); + if ((m_groupsServerURI == null) || + (m_groupsServerURI == string.Empty)) { - m_log.ErrorFormat("Please specify a valid Simian Server URL for XmlRpcServiceURL in OpenSim.ini, [Groups]"); + m_log.ErrorFormat("Please specify a valid Simian Server for GroupsServerURI in OpenSim.ini, [Groups]"); m_connectorEnabled = false; return; } + + m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30); + if (m_cacheTimeout == 0) + { + m_log.WarnFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Disabled."); + } + else + { + m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR] Groups Cache Timeout set to {0}.", m_cacheTimeout); + } + + + + m_memoryCache = new ExpiringCache(); + + // If we got all the config options we need, lets start'er'up m_connectorEnabled = true; @@ -220,7 +243,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void Close() { - m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); + m_log.InfoFormat("[SIMIAN-GROUPS-CONNECTOR]: Closing {0}", this.Name); } public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) @@ -653,7 +676,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); + OSDMap response = CachedPostRequest(requestArgs); if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) { OSDArray entryArray = (OSDArray)response["Entries"]; @@ -998,6 +1021,52 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } #endregion + #region GroupSessionTracking + + public void ResetAgentGroupChatSessions(UUID agentID) + { + Dictionary agentSessions; + + if (SimianGetGenericEntries(agentID, "GroupSessionDropped", out agentSessions)) + { + foreach (string GroupID in agentSessions.Keys) + { + SimianRemoveGenericEntry(agentID, "GroupSessionDropped", GroupID); + } + } + + if (SimianGetGenericEntries(agentID, "GroupSessionInvited", out agentSessions)) + { + foreach (string GroupID in agentSessions.Keys) + { + SimianRemoveGenericEntry(agentID, "GroupSessionInvited", GroupID); + } + } + } + + public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) + { + OSDMap session; + return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); + } + + public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) + { + SimianAddGeneric(agentID, "GroupSessionDropped", groupID.ToString(), new OSDMap()); + } + + public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + SimianAddGeneric(agentID, "GroupSessionInvited", groupID.ToString(), new OSDMap()); + } + + public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + OSDMap session; + return SimianGetGenericEntry(agentID, "GroupSessionDropped", groupID.ToString(), out session); + } + + #endregion private void EnsureRoleNotSelectedByMember(UUID groupID, UUID roleID, UUID userID) { @@ -1036,7 +1105,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); + OSDMap Response = CachedPostRequest(RequestArgs); if (Response["Success"].AsBoolean()) { return true; @@ -1063,7 +1132,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); + OSDMap Response = CachedPostRequest(RequestArgs); if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) { OSDArray entryArray = (OSDArray)Response["Entries"]; @@ -1103,7 +1172,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); + OSDMap Response = CachedPostRequest(RequestArgs); if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) { OSDArray entryArray = (OSDArray)Response["Entries"]; @@ -1144,7 +1213,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap Response = WebUtil.PostToService(m_serviceURL, RequestArgs); + OSDMap Response = CachedPostRequest(RequestArgs); if (Response["Success"].AsBoolean() && Response["Entries"] is OSDArray) { OSDArray entryArray = (OSDArray)Response["Entries"]; @@ -1184,7 +1253,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); + OSDMap response = CachedPostRequest(requestArgs); if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) { maps = new Dictionary(); @@ -1222,7 +1291,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups - OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); + OSDMap response = CachedPostRequest(requestArgs); if (response["Success"].AsBoolean() && response["Entries"] is OSDArray) { maps = new Dictionary(); @@ -1260,7 +1329,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups }; - OSDMap response = WebUtil.PostToService(m_serviceURL, requestArgs); + OSDMap response = CachedPostRequest(requestArgs); if (response["Success"].AsBoolean()) { return true; @@ -1272,6 +1341,49 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups } } #endregion + + #region CheesyCache + OSDMap CachedPostRequest(NameValueCollection requestArgs) + { + // Immediately forward the request if the cache is disabled. + if (m_cacheTimeout == 0) + { + return WebUtil.PostToService(m_groupsServerURI, requestArgs); + } + + // Check if this is an update or a request + if ( requestArgs["RequestMethod"] == "RemoveGeneric" + || requestArgs["RequestMethod"] == "AddGeneric" + ) + + { + // Any and all updates cause the cache to clear + m_memoryCache.Clear(); + + // Send update to server, return the response without caching it + return WebUtil.PostToService(m_groupsServerURI, requestArgs); + + } + + // If we're not doing an update, we must be requesting data + + // Create the cache key for the request and see if we have it cached + string CacheKey = WebUtil.BuildQueryString(requestArgs); + OSDMap response = null; + if (!m_memoryCache.TryGetValue(CacheKey, out response)) + { + // if it wasn't in the cache, pass the request to the Simian Grid Services + response = WebUtil.PostToService(m_groupsServerURI, requestArgs); + + // and cache the response + m_memoryCache.AddOrUpdate(CacheKey, response, TimeSpan.FromSeconds(m_cacheTimeout)); + } + + // return cached response + return response; + } + #endregion + } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index ab343c8..79b9a16 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -29,6 +29,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Reflection; +using System.Text; using Nwc.XmlRpc; @@ -61,7 +62,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_connectorEnabled = false; - private string m_serviceURL = string.Empty; + private string m_groupsServerURI = string.Empty; private bool m_disableKeepAlive = false; @@ -69,7 +70,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private string m_groupWriteKey = string.Empty; private IUserAccountService m_accountService = null; - + + private ExpiringCache m_memoryCache; + private int m_cacheTimeout = 30; + + // Used to track which agents are have dropped from a group chat session + // Should be reset per agent, on logon + // TODO: move this to Flotsam XmlRpc Service + // SessionID, List + private Dictionary> m_groupsAgentsDroppedFromChatSession = new Dictionary>(); + private Dictionary> m_groupsAgentsInvitedToChatSession = new Dictionary>(); + #region IRegionModuleBase Members @@ -104,13 +115,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Initializing {0}", this.Name); - m_serviceURL = groupsConfig.GetString("XmlRpcServiceURL", string.Empty); - if ((m_serviceURL == null) || - (m_serviceURL == string.Empty)) + m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); + if ((m_groupsServerURI == null) || + (m_groupsServerURI == string.Empty)) { - m_log.ErrorFormat("Please specify a valid URL for XmlRpcServiceURL in OpenSim.ini, [Groups]"); + m_log.ErrorFormat("Please specify a valid URL for GroupsServerURI in OpenSim.ini, [Groups]"); m_connectorEnabled = false; return; } @@ -120,17 +131,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty); m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty); - + m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30); + if (m_cacheTimeout == 0) + { + m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Disabled."); + } + else + { + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Timeout set to {0}.", m_cacheTimeout); + } // If we got all the config options we need, lets start'er'up + m_memoryCache = new ExpiringCache(); m_connectorEnabled = true; } } public void Close() { - m_log.InfoFormat("[GROUPS-CONNECTOR]: Closing {0}", this.Name); + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Closing {0}", this.Name); } public void AddRegion(OpenSim.Region.Framework.Scenes.Scene scene) @@ -756,6 +776,69 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param); } + + + + #endregion + + #region GroupSessionTracking + + public void ResetAgentGroupChatSessions(UUID agentID) + { + foreach (List agentList in m_groupsAgentsDroppedFromChatSession.Values) + { + agentList.Remove(agentID); + } + } + + public bool hasAgentBeenInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + // If we're tracking this group, and we can find them in the tracking, then they've been invited + return m_groupsAgentsInvitedToChatSession.ContainsKey(groupID) + && m_groupsAgentsInvitedToChatSession[groupID].Contains(agentID); + } + + public bool hasAgentDroppedGroupChatSession(UUID agentID, UUID groupID) + { + // If we're tracking drops for this group, + // and we find them, well... then they've dropped + return m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID) + && m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID); + } + + public void AgentDroppedFromGroupChatSession(UUID agentID, UUID groupID) + { + if (m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + // If not in dropped list, add + if (!m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Add(agentID); + } + } + } + + public void AgentInvitedToGroupChatSession(UUID agentID, UUID groupID) + { + // Add Session Status if it doesn't exist for this session + CreateGroupChatSessionTracking(groupID); + + // If nessesary, remove from dropped list + if (m_groupsAgentsDroppedFromChatSession[groupID].Contains(agentID)) + { + m_groupsAgentsDroppedFromChatSession[groupID].Remove(agentID); + } + } + + private void CreateGroupChatSessionTracking(UUID groupID) + { + if (!m_groupsAgentsDroppedFromChatSession.ContainsKey(groupID)) + { + m_groupsAgentsDroppedFromChatSession.Add(groupID, new List()); + m_groupsAgentsInvitedToChatSession.Add(groupID, new List()); + } + + } #endregion #region XmlRpcHashtableMarshalling @@ -849,50 +932,84 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param) { - string UserService; - UUID SessionID; - GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); - param.Add("requestingAgentID", requestingAgentID.ToString()); - param.Add("RequestingAgentUserService", UserService); - param.Add("RequestingSessionID", SessionID.ToString()); - + XmlRpcResponse resp = null; + string CacheKey = null; + + // Only bother with the cache if it isn't disabled. + if (m_cacheTimeout > 0) + { + if (!function.StartsWith("groups.get")) + { + // Any and all updates cause the cache to clear + m_memoryCache.Clear(); + } + else + { + StringBuilder sb = new StringBuilder(requestingAgentID + function); + foreach (object key in param.Keys) + { + if (param[key] != null) + { + sb.AppendFormat(",{0}:{1}", key.ToString(), param[key].ToString()); + } + } + + CacheKey = sb.ToString(); + m_memoryCache.TryGetValue(CacheKey, out resp); + } - param.Add("ReadKey", m_groupReadKey); - param.Add("WriteKey", m_groupWriteKey); + } + + if( resp == null ) + { + string UserService; + UUID SessionID; + GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); + param.Add("requestingAgentID", requestingAgentID.ToString()); + param.Add("RequestingAgentUserService", UserService); + param.Add("RequestingSessionID", SessionID.ToString()); - IList parameters = new ArrayList(); - parameters.Add(param); + param.Add("ReadKey", m_groupReadKey); + param.Add("WriteKey", m_groupWriteKey); - ConfigurableKeepAliveXmlRpcRequest req; - req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive); - XmlRpcResponse resp = null; + IList parameters = new ArrayList(); + parameters.Add(param); - try - { - resp = req.Send(m_serviceURL, 10000); - } - catch (Exception e) - { - + ConfigurableKeepAliveXmlRpcRequest req; + req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive); - m_log.ErrorFormat("[XMLRPCGROUPDATA]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function); - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", e.ToString()); - foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine },StringSplitOptions.None)) + try { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", ResponseLine); - } + resp = req.Send(m_groupsServerURI, 10000); - foreach (string key in param.Keys) + if ((m_cacheTimeout > 0) && (CacheKey != null)) + { + m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(m_cacheTimeout)); + } + + } + catch (Exception e) { - m_log.WarnFormat("[XMLRPCGROUPDATA]: {0} :: {1}", key, param[key].ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", e.ToString()); + + foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) + { + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} ", ResponseLine); + } + + foreach (string key in param.Keys) + { + m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", key, param[key].ToString()); + } + + Hashtable respData = new Hashtable(); + respData.Add("error", e.ToString()); + return respData; } - - Hashtable respData = new Hashtable(); - respData.Add("error", e.ToString()); - return respData; } if (resp.Value is Hashtable) @@ -906,21 +1023,21 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return respData; } - m_log.ErrorFormat("[XMLRPCGROUPDATA]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: The XmlRpc server returned a {1} instead of a hashtable for {0}", function, resp.Value.GetType().ToString()); if (resp.Value is ArrayList) { ArrayList al = (ArrayList)resp.Value; - m_log.ErrorFormat("[XMLRPCGROUPDATA]: Contains {0} elements", al.Count); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Contains {0} elements", al.Count); foreach (object o in al) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} :: {1}", o.GetType().ToString(), o.ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0} :: {1}", o.GetType().ToString(), o.ToString()); } } else { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: Function returned: {0}", resp.Value.ToString()); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Function returned: {0}", resp.Value.ToString()); } Hashtable error = new Hashtable(); @@ -930,16 +1047,16 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private void LogRespDataToConsoleError(Hashtable respData) { - m_log.Error("[XMLRPCGROUPDATA]: Error:"); + m_log.Error("[XMLRPC-GROUPS-CONNECTOR]: Error:"); foreach (string key in respData.Keys) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: Key: {0}", key); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: Key: {0}", key); string[] lines = respData[key].ToString().Split(new char[] { '\n' }); foreach (string line in lines) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0}", line); + m_log.ErrorFormat("[XMLRPC-GROUPS-CONNECTOR]: {0}", line); } } @@ -948,8 +1065,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// /// Group Request Tokens are an attempt to allow the groups service to authenticate - /// requests. Currently uses UserService, AgentID, and SessionID - /// TODO: Find a better way to do this. + /// requests. + /// TODO: This broke after the big grid refactor, either find a better way, or discard this /// /// /// -- cgit v1.1 From add7abc1de2fce8db4c6d01cc4b5305bafa4bd87 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Fri, 7 May 2010 14:12:07 -0400 Subject: Fix Mouse+WASD makes Av rise; Fix PREJUMP. --- .../Scenes/Animation/ScenePresenceAnimator.cs | 13 +++------- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 23 +++++++++++------ OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs | 30 +++++++++++++++------- 4 files changed, 40 insertions(+), 28 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index be0e985..b43caf2 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -56,7 +56,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist! protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init. private int m_animTickFall; - private int m_animTickJump; +// private int m_animTickJump; + public int m_animTickJump; // ScenePresence has to see this to control +Z force /// /// The scene presence that this animator applies to @@ -123,22 +124,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation /// public void TrySetMovementAnimation(string anim) { -//Console.WriteLine("Updating movement animation to {0}", anim); - if (!m_scenePresence.IsChildAgent) { if (m_animations.TrySetDefaultAnimation( anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) { -//Console.WriteLine("TSMA {0} success.", anim); // 16384 is CHANGED_ANIMATION m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 }); SendAnimPack(); } - else - { -//Console.WriteLine("TSMA {0} fail.", anim); - } } } @@ -267,7 +261,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation m_animTickJump = Environment.TickCount; return "PREJUMP"; } - else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) + else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f) { // Start actual jump if (m_animTickJump == -1) @@ -317,7 +311,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation public void UpdateMovementAnimations() { m_movementAnimation = GetMovementAnimation(); -//Console.WriteLine("UMA got {0}", m_movementAnimation); if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) { // This was the previous behavior before PREJUMP diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index db073e8..665fb4c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -613,7 +613,7 @@ namespace OpenSim.Region.Framework.Scenes m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); // TODO: Change default to true once the feature is supported m_usePreJump = startupConfig.GetBoolean("enableprejump", false); - + m_usePreJump = true; // Above line fails!? m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); if (RegionInfo.NonphysPrimMax > 0) { diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 2603fe1..565438d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -665,7 +665,7 @@ namespace OpenSim.Region.Framework.Scenes CreateSceneViewer(); m_animator = new ScenePresenceAnimator(this); } - + private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() { m_rootRegionHandle = reginfo.RegionHandle; @@ -1459,7 +1459,6 @@ namespace OpenSim.Region.Framework.Scenes } i++; } - //Paupaw:Do Proper PID for Autopilot here if (bResetMoveToPosition) { @@ -2433,10 +2432,11 @@ namespace OpenSim.Region.Framework.Scenes Rotation = rotation; Vector3 direc = vec * rotation; direc.Normalize(); + PhysicsActor actor = m_physicsActor; + if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up. direc *= 0.03f * 128f * m_speedModifier; - PhysicsActor actor = m_physicsActor; if (actor != null) { if (actor.Flying) @@ -2458,11 +2458,18 @@ namespace OpenSim.Region.Framework.Scenes { if (direc.Z > 2.0f) { - direc.Z *= 3.0f; - - // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. - Animator.TrySetMovementAnimation("PREJUMP"); - Animator.TrySetMovementAnimation("JUMP"); + if(m_animator.m_animTickJump == -1) + { + direc.Z *= 3.0f; // jump + } + else + { + direc.Z *= 0.1f; // prejump + } + /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs + Animator.TrySetMovementAnimation("PREJUMP"); + Animator.TrySetMovementAnimation("JUMP"); + */ } } } diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index 7a5093b..38c38b6 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -142,7 +142,7 @@ namespace OpenSim.Region.Physics.OdePlugin // unique UUID of this character object public UUID m_uuid; public bool bad = false; - + public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, CollisionLocker dode, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor) { m_uuid = UUID.Random(); @@ -892,7 +892,7 @@ namespace OpenSim.Region.Physics.OdePlugin // If the PID Controller isn't active then we set our force // calculating base velocity to the current position - + if (Body == IntPtr.Zero) return; @@ -972,8 +972,17 @@ namespace OpenSim.Region.Physics.OdePlugin // Prim to avatar collisions d.Vector3 pos = d.BodyGetPosition(Body); - vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); - vec.Y = (_target_velocity.Y - vel.Y)*(PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2); + float errX = _zeroPosition.X - pos.X; + float errY = _zeroPosition.Y - pos.Y; + if( (Math.Abs(errX) > 0.1f) || (Math.Abs(errY) > 0.1f) ) + { + vec.X = (_target_velocity.X - vel.X) * (PID_D) + (errX) * (PID_P * 2); + vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (errY) * (PID_P * 2); + } + else + { // close, jump to lateral destination + d.BodySetPosition(Body, _zeroPosition.X, _zeroPosition.Y, pos.Z); + } if (flying) { vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; @@ -1056,11 +1065,14 @@ namespace OpenSim.Region.Physics.OdePlugin } if (vec.IsFinite()) { - doForce(vec); - if (!_zeroFlag) - { - AlignAvatarTiltWithCurrentDirectionOfMovement(vec); - } + if (!vec.ApproxEquals(Vector3.Zero, 0.01f)) + { + doForce(vec); + if (!_zeroFlag) + { + AlignAvatarTiltWithCurrentDirectionOfMovement(vec); + } + } } else { -- cgit v1.1 From 2fe669448f8cfefe2ef6e046faec3c0e709a41e4 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 10 May 2010 05:43:16 -0700 Subject: Greatly improve login time for users with large friends lists by requesting all unknown UUID's in one go rather than individually --- .../CoreModules/Avatar/Friends/FriendsModule.cs | 45 +++++++++++++++++++--- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index febd4ca..57dde76 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -67,7 +67,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return false; } } - + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected List m_Scenes = new List(); @@ -234,7 +234,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends newFriends.RegionID = UUID.Zero; m_Friends.Add(client.AgentId, newFriends); - + //StatusChange(client.AgentId, true); } @@ -289,7 +289,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Inform the friends that this user is online StatusChange(agentID, true); - + // Register that we need to send the list of online friends to this user lock (m_NeedsListOfFriends) if (!m_NeedsListOfFriends.Contains(agentID)) @@ -442,11 +442,44 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1)) friendList.Add(fi); } + /* foreach (FriendInfo fi in friendList) { // Notify about this user status StatusNotify(fi, agentID, online); } + */ + + StatusNotifyMass(friendList, agentID, online); + } + } + + private void StatusNotifyMass(List friendList, UUID userID, bool online) + { + string[] friendIDs = new string[friendList.Count]; + int notlocal = 0; + for (int x = 0; x < friendList.Count; x++) + { + UUID friendID = UUID.Zero; + if (UUID.TryParse(friendList[x].Friend, out friendID)) + { + if (!LocalStatusNotification(userID, friendID, online)) + { + friendIDs[notlocal++] = friendID.ToString(); + } + } + } + + PresenceInfo[] friendSessions = PresenceService.GetAgents(friendIDs); + + for (int x = 0; x < friendSessions.GetLength(0); x++) + { + PresenceInfo friendSession = PresenceInfo.GetOnlinePresence(friendSessions); + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + m_FriendsSimConnector.StatusNotify(region, userID, new UUID(friendIDs[x]), online); + } } } @@ -459,7 +492,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Try local if (LocalStatusNotification(userID, friendID, online)) return; - + // The friend is not here [as root]. Let's forward. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); PresenceInfo friendSession = PresenceInfo.GetOnlinePresence(friendSessions); @@ -476,7 +509,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnInstantMessage(IClientAPI client, GridInstantMessage im) { if (im.dialog == (byte)OpenMetaverse.InstantMessageDialog.FriendshipOffered) - { + { // we got a friendship offer UUID principalID = new UUID(im.fromAgentID); UUID friendID = new UUID(im.toAgentID); @@ -688,7 +721,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // we're done return true; } - + return false; } -- cgit v1.1 From ab716125d7aa80efe2b3904490f10fd045da94c7 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 10 May 2010 05:51:49 -0700 Subject: Correct an odd merge anomaly --- OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 8f84d81..5dc9c44 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -471,7 +471,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends for (int x = 0; x < friendSessions.GetLength(0); x++) { - PresenceInfo friendSession = PresenceInfo.GetOnlinePresence(friendSessions); + PresenceInfo friendSession = friendSessions[x]; if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); -- cgit v1.1 From 3cda854ef312a71f3ceab6cb8339a0d2d2fce803 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 10 May 2010 08:47:41 -0700 Subject: Fix overlooked readLock which was left open --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ff471e0..35134d6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -123,7 +123,7 @@ namespace OpenSim.Region.Framework.Scenes } if (m_partsLock.RecursiveWriteCount > 0) { - m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed."); + m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed."); m_partsLock.ExitWriteLock(); } @@ -1667,6 +1667,7 @@ namespace OpenSim.Region.Framework.Scenes remoteClient, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, part.UUID)); } } + lockPartsForRead(false); } #region Copying -- cgit v1.1 From 14a86de115934e981e5c3e413821861434ccf5e8 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 10 May 2010 12:45:33 -0700 Subject: Fix another ReaderWriterLockSlim issue --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 62b44bd..c4cff12 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -840,12 +840,12 @@ namespace OpenSim.Region.Framework.Scenes } else { + m_items.LockItemsForRead(false); m_log.ErrorFormat( "[PRIM INVENTORY]: " + "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", itemID, m_part.Name, m_part.UUID); } - m_items.LockItemsForWrite(false); return -1; } -- cgit v1.1 From 40e05f41098bdedac7296d84c9aa8d915c5c9ede Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 11 May 2010 09:28:46 -0700 Subject: Spin the AddNewClient process off into a new thread to avoid locking up the LLUDPServer (and therefore the entire scene) --- OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 41e41e4..d9aecd8 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -909,7 +909,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP client.OnLogout += LogoutHandler; // Start the IClientAPI - client.Start(); + // Spin it off so that it doesn't clog up the LLUDPServer + Util.FireAndForget(delegate(object o) { client.Start(); }); } else { -- cgit v1.1 From 98bd3e1f3498600e9299252723a8365ce8fd77fd Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 12 May 2010 07:14:06 -0700 Subject: Don't convert UUID -> ToString for every friend (Minor optimisation based on profiler feedback) --- OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 5dc9c44..5339dee 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -201,9 +201,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends UserFriendData data = m_Friends[principalID]; + string searchFor = friendID.ToString(); foreach (FriendInfo fi in data.Friends) { - if (fi.Friend == friendID.ToString()) + if (fi.Friend == searchFor) return (uint)fi.TheirFlags; } return 0; -- cgit v1.1 From 7705012ee7b016f8e163c5e9586fef724b233932 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 12 May 2010 08:25:40 -0700 Subject: Optimise the heavily used GetScenePresences; eliminate the array->list conversion on every call and transition from hard locks to ReaderWriter locks. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 56 +++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index f43de20..c16ba12 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -70,6 +70,9 @@ namespace OpenSim.Region.Framework.Scenes protected Dictionary m_scenePresences = new Dictionary(); protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0]; + protected List m_scenePresenceList = new List(); + + protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); // SceneObjects is not currently populated or used. //public Dictionary SceneObjects; @@ -132,10 +135,16 @@ namespace OpenSim.Region.Framework.Scenes protected internal void Close() { - lock (m_scenePresences) + m_scenePresencesLock.EnterWriteLock(); + try { m_scenePresences.Clear(); m_scenePresenceArray = new ScenePresence[0]; + m_scenePresenceList = new List(); + } + finally + { + m_scenePresencesLock.ExitWriteLock(); } lock (m_dictionary_lock) @@ -542,7 +551,8 @@ namespace OpenSim.Region.Framework.Scenes Entities[presence.UUID] = presence; - lock (m_scenePresences) + m_scenePresencesLock.EnterWriteLock(); + try { if (!m_scenePresences.ContainsKey(presence.UUID)) { @@ -554,11 +564,12 @@ namespace OpenSim.Region.Framework.Scenes Array.Copy(m_scenePresenceArray, newArray, oldLength); newArray[oldLength] = presence; m_scenePresenceArray = newArray; + m_scenePresenceList = new List(m_scenePresenceArray); } else { m_scenePresences[presence.UUID] = presence; - + // Do a linear search through the array of ScenePresence references // and update the modified entry for (int i = 0; i < m_scenePresenceArray.Length; i++) @@ -569,8 +580,13 @@ namespace OpenSim.Region.Framework.Scenes break; } } + m_scenePresenceList = new List(m_scenePresenceArray); } } + finally + { + m_scenePresencesLock.ExitWriteLock(); + } } /// @@ -585,7 +601,8 @@ namespace OpenSim.Region.Framework.Scenes agentID); } - lock (m_scenePresences) + m_scenePresencesLock.EnterWriteLock(); + try { if (m_scenePresences.Remove(agentID)) { @@ -604,12 +621,17 @@ namespace OpenSim.Region.Framework.Scenes } } m_scenePresenceArray = newArray; + m_scenePresenceList = new List(m_scenePresenceArray); } else { m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); } } + finally + { + m_scenePresencesLock.ExitWriteLock(); + } } protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) @@ -730,8 +752,15 @@ namespace OpenSim.Region.Framework.Scenes /// private List GetScenePresences() { - lock (m_scenePresences) - return new List(m_scenePresenceArray); + m_scenePresencesLock.EnterReadLock(); + try + { + return m_scenePresenceList; + } + finally + { + m_scenePresencesLock.ExitReadLock(); + } } /// @@ -742,10 +771,15 @@ namespace OpenSim.Region.Framework.Scenes protected internal ScenePresence GetScenePresence(UUID agentID) { ScenePresence sp; - lock (m_scenePresences) + m_scenePresencesLock.EnterReadLock(); + try { m_scenePresences.TryGetValue(agentID, out sp); } + finally + { + m_scenePresencesLock.ExitReadLock(); + } return sp; } @@ -780,10 +814,15 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) { - lock (m_scenePresences) + m_scenePresencesLock.EnterReadLock(); + try { m_scenePresences.TryGetValue(agentID, out avatar); } + finally + { + m_scenePresencesLock.ExitReadLock(); + } return (avatar != null); } @@ -1061,6 +1100,7 @@ namespace OpenSim.Region.Framework.Scenes Parallel.ForEach(GetScenePresences(), protectedAction); */ // For now, perform actiona serially + foreach (ScenePresence sp in GetScenePresences()) { try -- cgit v1.1 From fd37a21b59836143f50fdf994c691d65bd641d52 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 12 May 2010 08:34:47 -0700 Subject: Kill some locks that have crept into SOG --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 35134d6..a4b8944 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3651,7 +3651,8 @@ namespace OpenSim.Region.Framework.Scenes if (atRotTargets.Count > 0) { uint[] localids = new uint[0]; - lock (m_parts) + lockPartsForRead(true); + try { localids = new uint[m_parts.Count]; int cntr = 0; @@ -3661,6 +3662,10 @@ namespace OpenSim.Region.Framework.Scenes cntr++; } } + finally + { + lockPartsForRead(false); + } for (int ctr = 0; ctr < localids.Length; ctr++) { @@ -3679,7 +3684,8 @@ namespace OpenSim.Region.Framework.Scenes { //trigger not_at_target uint[] localids = new uint[0]; - lock (m_parts) + lockPartsForRead(true); + try { localids = new uint[m_parts.Count]; int cntr = 0; @@ -3689,6 +3695,10 @@ namespace OpenSim.Region.Framework.Scenes cntr++; } } + finally + { + lockPartsForRead(false); + } for (int ctr = 0; ctr < localids.Length; ctr++) { -- cgit v1.1 From 9079ad5ceb3cfb9ddb0c255289b288be40f6567e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 13 May 2010 12:40:18 -0700 Subject: Add some debug output to GetAgent to try and track down our presence problems --- OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs index 41ebeaf..9f86078 100644 --- a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs @@ -300,6 +300,14 @@ namespace OpenSim.Services.Connectors { pinfo = new PresenceInfo((Dictionary)replyData["result"]); } + else + { + m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply (result not dictionary) received from presence server when querying for sessionID {0}", sessionID.ToString()); + } + } + else + { + m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply received from presence server when querying for sessionID {0}", sessionID.ToString()); } return pinfo; -- cgit v1.1 From 547e0278990208e52a35ac92add22f756d8674f2 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 30 Apr 2010 22:35:07 +0200 Subject: Fix linking issue introduced in my earlier commit --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 8716e0a..4f2b446 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2594,8 +2594,17 @@ namespace OpenSim.Region.Framework.Scenes List children = new List(); SceneObjectPart root = GetSceneObjectPart(parentPrimId); - if (Permissions.CanLinkObject(client.AgentId, root.ParentGroup.RootPart.UUID)) + if (root == null) + { + m_log.DebugFormat("[LINK]: Can't find linkset root prim {0{", parentPrimId); + return; + } + + if (!Permissions.CanLinkObject(client.AgentId, root.ParentGroup.RootPart.UUID)) + { + m_log.DebugFormat("[LINK]: Refusing link. No permissions on root prim"); return; + } foreach (uint localID in childPrimIds) { @@ -2614,7 +2623,16 @@ namespace OpenSim.Region.Framework.Scenes // Must be all one owner // if (owners.Count > 1) + { + m_log.DebugFormat("[LINK]: Refusing link. Too many owners"); + return; + } + + if (children.Count == 0) + { + m_log.DebugFormat("[LINK]: Refusing link. No permissions to link any of the children"); return; + } m_sceneGraph.LinkObjects(root, children); } -- cgit v1.1 From 9209657f93fdebe1df0e18e3807ce996bae99e06 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey Date: Fri, 14 May 2010 21:22:53 +0100 Subject: Apply patch from http://opensimulator.org/mantis/bug_view_page.php?bug_id=4671 Fixes a bug where the viewer didn't recieve the uuid of a chat broadcasting object Thanks crystalsgalicia! --- OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 6dacbba..02f0968 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -264,6 +264,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat fromName = avatar.Name; sourceType = ChatSourceType.Agent; } + else if (c.SenderUUID != UUID.Zero) + { + fromID = c.SenderUUID; + } // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); -- cgit v1.1 From 2f6bb013701b45421b906625560d8b417ad78689 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey Date: Fri, 14 May 2010 21:22:53 +0100 Subject: Apply patch from http://opensimulator.org/mantis/bug_view_page.php?bug_id=4671 Fixes a bug where the viewer didn't recieve the uuid of a chat broadcasting object Thanks crystalsgalicia! --- OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 6dacbba..02f0968 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -264,6 +264,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat fromName = avatar.Name; sourceType = ChatSourceType.Agent; } + else if (c.SenderUUID != UUID.Zero) + { + fromID = c.SenderUUID; + } // m_log.DebugFormat("[CHAT] Broadcast: fromID {0} fromName {1}, cType {2}, sType {3}", fromID, fromName, cType, sourceType); -- cgit v1.1 From e79eac238ed54d1e0d41ad1ff970473226cede50 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 14 May 2010 21:30:53 +0100 Subject: switch 0.6.9 flavour to release --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index f8ed5ae..1ae493d 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -30,7 +30,7 @@ namespace OpenSim public class VersionInfo { private const string VERSION_NUMBER = "0.6.9"; - private const Flavour VERSION_FLAVOUR = Flavour.RC1; + private const Flavour VERSION_FLAVOUR = Flavour.Release; public enum Flavour { -- cgit v1.1 From 12ee3a3c93c99752730bf17f354f17660911010f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 14 May 2010 21:40:37 +0100 Subject: change 0.6.9 flavour to post-fixes --- OpenSim/Framework/Servers/VersionInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index f8ed5ae..fb41ef3 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -30,7 +30,7 @@ namespace OpenSim public class VersionInfo { private const string VERSION_NUMBER = "0.6.9"; - private const Flavour VERSION_FLAVOUR = Flavour.RC1; + private const Flavour VERSION_FLAVOUR = Flavour.Post_Fixes; public enum Flavour { -- cgit v1.1 From 2c8d25a11029429aa7b146e3c2be57093046dd15 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 14 May 2010 15:06:13 -0700 Subject: * Allows both old and new OpenSim.ini params for the XmlRpc Groups Service Connector * Fix problem with RequestingAgentID not being sent correctly to server resulting in failed xmlrpc calls * Improved debug output --- .../Avatar/XmlRpcGroups/GroupsModule.cs | 24 +++++- .../XmlRpcGroupsServicesConnectorModule.cs | 87 +++++++++++++++------- 2 files changed, 80 insertions(+), 31 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index edd5af7..3e05732 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -342,7 +342,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private void OnInstantMessage(IClientAPI remoteClient, GridInstantMessage im) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + if (m_debugEnabled) + { + m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + m_log.DebugFormat("[GROUPS]: remoteClient ({0}) im ({1})", remoteClient, im); + + } + // Group invitations if ((im.dialog == (byte)InstantMessageDialog.GroupInvitationAccept) || (im.dialog == (byte)InstantMessageDialog.GroupInvitationDecline)) @@ -481,7 +487,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (member.AcceptNotices) { // Build notice IIM - GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); + GridInstantMessage msg = CreateGroupNoticeIM(GetRequestingAgentID(remoteClient), NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); msg.toAgentID = member.AgentID.Guid; OutgoingInstantMessage(msg, member.AgentID); @@ -1024,12 +1030,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void InviteGroupRequest(IClientAPI remoteClient, UUID groupID, UUID invitedAgentID, UUID roleID) { - if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + if (m_debugEnabled) + { + m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); + m_log.DebugFormat("[GROUPS]: remoteClient({0}) groupID({0}) invitedAgentID({0}) roleID({0})", remoteClient, groupID, invitedAgentID, roleID); + } + // Todo: Security check, probably also want to send some kind of notification UUID InviteID = UUID.Random(); - m_groupData.AddAgentToGroupInvite(GetRequestingAgentID(remoteClient), InviteID, groupID, roleID, invitedAgentID); + UUID requestingAgentID = GetRequestingAgentID(remoteClient); + if (requestingAgentID == UUID.Zero) + { + m_log.Error("[GROUPS] Group Invite Requires a valid requesting agent to be specified"); + } + m_groupData.AddAgentToGroupInvite(requestingAgentID, InviteID, groupID, roleID, invitedAgentID); // Check to see if the invite went through, if it did not then it's possible // the remoteClient did not validate or did not have permission to invite. diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 2a60b00..861731c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -40,6 +40,7 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; +using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups @@ -66,6 +67,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private string m_groupReadKey = string.Empty; private string m_groupWriteKey = string.Empty; + private IUserService m_userService = null; + private CommunicationsManager m_commManager = null; + + private bool m_debugEnabled = false; + // Used to track which agents are have dropped from a group chat session // Should be reset per agent, on logon @@ -110,7 +116,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.InfoFormat("[GROUPS-CONNECTOR]: Initializing {0}", this.Name); - m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", string.Empty); + m_groupsServerURI = groupsConfig.GetString("GroupsServerURI", groupsConfig.GetString("XmlRpcServiceURL", string.Empty)); if ((m_groupsServerURI == null) || (m_groupsServerURI == string.Empty)) { @@ -124,7 +130,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_groupReadKey = groupsConfig.GetString("XmlRpcServiceReadKey", string.Empty); m_groupWriteKey = groupsConfig.GetString("XmlRpcServiceWriteKey", string.Empty); - + m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); // If we got all the config options we need, lets start'er'up @@ -142,6 +148,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_connectorEnabled) { scene.RegisterModuleInterface(this); + + if (m_userService == null) + { + m_userService = scene.CommsManager.UserService; + m_commManager = scene.CommsManager; + } } } @@ -912,7 +924,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups string UserService; UUID SessionID; GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); - param.Add("requestingAgentID", requestingAgentID.ToString()); + param.Add("RequestingAgentID", requestingAgentID.ToString()); param.Add("RequestingAgentUserService", UserService); param.Add("RequestingSessionID", SessionID.ToString()); @@ -920,6 +932,14 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups param.Add("ReadKey", m_groupReadKey); param.Add("WriteKey", m_groupWriteKey); + if (m_debugEnabled) + { + m_log.Debug("[XMLRPCGROUPDATA] XmlRpcCall Params:"); + foreach (string key in param.Keys) + { + m_log.DebugFormat("[XMLRPCGROUPDATA] {0} : {1}", key, param[key]); + } + } IList parameters = new ArrayList(); parameters.Add(param); @@ -940,10 +960,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_log.ErrorFormat("[XMLRPCGROUPDATA]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function); m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", e.ToString()); - foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine },StringSplitOptions.None)) + if ((req != null) && (req.RequestResponse != null)) + { + foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) { m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", ResponseLine); } + } foreach (string key in param.Keys) { @@ -955,12 +978,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return respData; } + if (resp.Value is Hashtable) { Hashtable respData = (Hashtable)resp.Value; if (respData.Contains("error") && !respData.Contains("succeed")) { - LogRespDataToConsoleError(respData); + LogRespDataToConsoleError(function, respData); } return respData; @@ -988,18 +1012,26 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return error; } - private void LogRespDataToConsoleError(Hashtable respData) + private void LogRespDataToConsoleError(string function, Hashtable respData) { + m_log.ErrorFormat("[XMLRPCGROUPDATA]: Error data from XmlRpcGroups server method: {0}", function); m_log.Error("[XMLRPCGROUPDATA]: Error:"); foreach (string key in respData.Keys) { m_log.ErrorFormat("[XMLRPCGROUPDATA]: Key: {0}", key); - string[] lines = respData[key].ToString().Split(new char[] { '\n' }); - foreach (string line in lines) + if ((respData != null) && (respData.ContainsKey(key)) && (respData[key]!=null)) + { + string[] lines = respData[key].ToString().Split(new char[] { '\n' }); + foreach (string line in lines) + { + m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0}", line); + } + } + else { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0}", line); + m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} : Empty/NULL", key); } } @@ -1015,23 +1047,17 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private void GetClientGroupRequestID(UUID AgentID, out string UserServiceURL, out UUID SessionID) { - UserServiceURL = ""; - SessionID = UUID.Zero; - + // Default to local grid user service + UserServiceURL = m_commManager.NetworkServersInfo.UserURL; ; - // Need to rework this based on changes to User Services - /* - UserAccount userAccount = m_accountService.GetUserAccount(UUID.Zero,AgentID); - if (userAccount == null) - { - // This should be impossible. If I've been passed a reference to a client - // that client should be registered with the UserService. So something - // is horribly wrong somewhere. + // if AgentID == UUID, there will be no SessionID. This will be true when + // the region is requesting information for region use (object permissions for example) + SessionID = UUID.Zero; - m_log.WarnFormat("[GROUPS]: Could not find a UserServiceURL for {0}", AgentID); + // Attempt to get User Profile, for SessionID + UserProfileData userProfile = m_userService.GetUserProfile(AgentID); - } - else if (userProfile is ForeignUserProfileData) + if ((userProfile != null) && (userProfile is ForeignUserProfileData)) { // They aren't from around here ForeignUserProfileData fupd = (ForeignUserProfileData)userProfile; @@ -1039,13 +1065,20 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups SessionID = fupd.CurrentAgent.SessionID; } - else + else if (userProfile != null) { - // They're a local user, use this: - UserServiceURL = m_commManager.NetworkServersInfo.UserURL; + // Local, just use the local SessionID SessionID = userProfile.CurrentAgent.SessionID; } - */ + else if (AgentID != UUID.Zero) + { + // This should be impossible. If I've been passed a reference to a client + // that client should be registered with the UserService. So something + // is horribly wrong somewhere. + + // m_log.WarnFormat("[XMLRPCGROUPDATA]: Could not find a UserServiceURL for {0}", AgentID); + + } } } -- cgit v1.1 From 25bb80da7704ae84d0081e927134aa7ae3c4663a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 15 May 2010 00:33:05 +0100 Subject: remove unrequired [Groups] section from GridCommon.ini.example, as per Nebadon --- bin/config-include/GridCommon.ini.example | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index 8fc2425..cc86501 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -15,16 +15,12 @@ ; InventoryServerURI = "http://myinventoryserver.com:8003" + [GridService] ; ; change this to your grid-wide grid server ; GridServerURI = "http://mygridserver.com:8003" -[Groups] - ; - ; change this to your grid-wide groups server - ; - GroupsServerURI = "http://mygridserver.com:82/Grid/" [Modules] -- cgit v1.1 From dd1b99cd0d83342cece72be6b39cf0c29527224f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 3 May 2010 21:34:38 +0100 Subject: Address symptom of Mantis 4588 (though not the cause) by moving the avatar dereference inside the exception catch --- OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs index 1a6cd6c..4bcfaac 100644 --- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs @@ -146,10 +146,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule } private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) - { - ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + { try { + ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); + if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) { avatar.Invulnerable = false; -- cgit v1.1 From 009b15c43652e112acb111ddc49afb1ecb2bc37a Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey Date: Sat, 15 May 2010 02:07:07 +0100 Subject: Make "nant distbin" remove BUILDING.txt --- .nant/local.include | 1 + 1 file changed, 1 insertion(+) diff --git a/.nant/local.include b/.nant/local.include index 1e8bedc..14fd3c0 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -20,6 +20,7 @@ + -- cgit v1.1 From 8f838c722da978da646fcef59a5af767840832bb Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 17 May 2010 14:14:19 -0700 Subject: When killing a zombie session, don't send the stop packet since it often has the effect of killing a newly connected client. --- OpenSim/Client/MXP/ClientStack/MXPClientView.cs | 10 +++++++++- .../Client/Sirikata/ClientStack/SirikataClientView.cs | 5 +++++ OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs | 5 +++++ OpenSim/Framework/IClientAPI.cs | 1 + OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 18 +++++++++++++++--- OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs | 5 +++++ OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- .../InternetRelayClientView/Server/IRCClientView.cs | 5 +++++ OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs | 5 +++++ OpenSim/Tests/Common/Mock/TestClient.cs | 4 ++++ 10 files changed, 55 insertions(+), 5 deletions(-) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 1d6d4c1..12989f5 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -835,10 +835,18 @@ namespace OpenSim.Client.MXP.ClientStack public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { m_log.Info("[MXP ClientStack] Close Called"); // Tell the client to go - SendLogoutPacket(); + if (sendStop == true) + { + SendLogoutPacket(); + } // Let MXPPacketServer clean it up if (Session.SessionState != SessionState.Disconnected) diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index 43c64e9..c4b5c87 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -446,6 +446,11 @@ namespace OpenSim.Client.Sirikata.ClientStack public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { throw new System.NotImplementedException(); } diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 864b4f1..39a16bc 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -452,6 +452,11 @@ namespace OpenSim.Client.VWoHTTP.ClientStack public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { throw new System.NotImplementedException(); } diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 01daeb1..c597d62 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1114,6 +1114,7 @@ namespace OpenSim.Framework void InPacket(object NewPack); void ProcessInPacket(Packet NewPack); void Close(); + void Close(bool sendStop); void Kick(string message); /// diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index d5fda9d..5670a78 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -502,18 +502,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Client Methods + /// /// Shut down the client view /// public void Close() { + Close(true); + } + + /// + /// Shut down the client view + /// + public void Close(bool sendStop) + { m_log.DebugFormat( "[CLIENT]: Close has been called for {0} attached to scene {1}", Name, m_scene.RegionInfo.RegionName); - // Send the STOP packet - DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); - OutPacket(disable, ThrottleOutPacketType.Unknown); + if (sendStop) + { + // Send the STOP packet + DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); + OutPacket(disable, ThrottleOutPacketType.Unknown); + } IsActive = false; diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 09611af..84385ad 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -831,6 +831,11 @@ namespace OpenSim.Region.Examples.SimpleModule public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { } public void Start() diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 3d59615..1b08c50 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3489,7 +3489,7 @@ namespace OpenSim.Region.Framework.Scenes { // We have a zombie from a crashed session. Kill it. m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName); - sp.ControllingClient.Close(); + sp.ControllingClient.Close(false); } } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 69e78b3..7c0fe4c 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -885,6 +885,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { Disconnect(); } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 6360c99..4323c94 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -845,6 +845,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { } public void Start() diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index b07a072..05a8ff0 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -888,6 +888,10 @@ namespace OpenSim.Tests.Common.Mock public void Close() { + Close(true); + } + public void Close(bool sendStop) + { m_scene.RemoveClient(AgentId); } -- cgit v1.1 From 6bc7e3429f9ac6cb57fbaa695223c3d76c189f77 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 17 May 2010 14:14:19 -0700 Subject: Provide interface to prevent the client close function from sending the stop packet --- OpenSim/Client/MXP/ClientStack/MXPClientView.cs | 10 +++++++++- .../Client/Sirikata/ClientStack/SirikataClientView.cs | 5 +++++ OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs | 5 +++++ OpenSim/Framework/IClientAPI.cs | 1 + OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 18 +++++++++++++++--- OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs | 5 +++++ .../InternetRelayClientView/Server/IRCClientView.cs | 5 +++++ OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs | 5 +++++ OpenSim/Tests/Common/Mock/TestClient.cs | 4 ++++ 9 files changed, 54 insertions(+), 4 deletions(-) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 33017d6..658ddf0 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -827,10 +827,18 @@ namespace OpenSim.Client.MXP.ClientStack public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { m_log.Info("[MXP ClientStack] Close Called"); // Tell the client to go - SendLogoutPacket(); + if (sendStop == true) + { + SendLogoutPacket(); + } // Let MXPPacketServer clean it up if (Session.SessionState != SessionState.Disconnected) diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index 1bdc4f8..c2ddd36 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -439,6 +439,11 @@ namespace OpenSim.Client.Sirikata.ClientStack public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { throw new System.NotImplementedException(); } diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index f45cb44..df07807 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -446,6 +446,11 @@ namespace OpenSim.Client.VWoHTTP.ClientStack public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { throw new System.NotImplementedException(); } diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index bcbc957..bc8ce1a 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1101,6 +1101,7 @@ namespace OpenSim.Framework void InPacket(object NewPack); void ProcessInPacket(Packet NewPack); void Close(); + void Close(bool sendStop); void Kick(string message); /// diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 5c774b5..960e0a2 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -470,18 +470,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Client Methods + /// /// Shut down the client view /// public void Close() { + Close(true); + } + + /// + /// Shut down the client view + /// + public void Close(bool sendStop) + { m_log.DebugFormat( "[CLIENT]: Close has been called for {0} attached to scene {1}", Name, m_scene.RegionInfo.RegionName); - // Send the STOP packet - DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); - OutPacket(disable, ThrottleOutPacketType.Unknown); + if (sendStop) + { + // Send the STOP packet + DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); + OutPacket(disable, ThrottleOutPacketType.Unknown); + } IsActive = false; diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index d2b0161..b074313 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -825,6 +825,11 @@ namespace OpenSim.Region.Examples.SimpleModule public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { } public void Start() diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 85e3fb3..0b6647d 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -877,6 +877,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { Disconnect(); } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index cf2076f..938293f 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -838,6 +838,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC public void Close() { + Close(true); + } + + public void Close(bool sendStop) + { } public void Start() diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 68ac96a..752e9e1 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -882,6 +882,10 @@ namespace OpenSim.Tests.Common.Mock public void Close() { + Close(true); + } + public void Close(bool sendStop) + { m_scene.RemoveClient(AgentId); } -- cgit v1.1 From c25c40a3f913f623cbcb3c7dcea0cdbf65f3c2c2 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 17 May 2010 15:24:28 -0700 Subject: Following on from the last commit, the stop/disconnect packet should NOT be sent when the user logs out. This eliminates the annoying "crash on log out" bug, and allows the client to commit important information at the last moment (attachment data!) --- OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index d9aecd8..d708055 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -926,7 +926,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (m_scene.TryGetClient(udpClient.AgentID, out client)) { client.IsLoggingOut = true; - client.Close(); + client.Close(false); } } -- cgit v1.1 From eb5a95d26bca4840f5a082156c0a37afed166fb1 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 18 May 2010 03:02:36 +0200 Subject: Prevent an "index out of range" error on login --- OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 5339dee..30eb9b8 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -454,9 +454,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void StatusNotifyMass(List friendList, UUID userID, bool online) { - string[] friendIDs = new string[friendList.Count]; + int fct = friendList.Count; + string[] friendIDs = new string[fct]; int notlocal = 0; - for (int x = 0; x < friendList.Count; x++) + for (int x = 0 ; x < fct ; x++) { UUID friendID = UUID.Zero; if (UUID.TryParse(friendList[x].Friend, out friendID)) @@ -472,6 +473,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends for (int x = 0; x < friendSessions.GetLength(0); x++) { + if (friendIDs.Length <= x) + continue; PresenceInfo friendSession = friendSessions[x]; if (friendSession != null) { -- cgit v1.1 From ae7c30a0f38b2b99ceef0a31968b13a76c164211 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 18 May 2010 00:07:17 -0700 Subject: While examining our 10,10,10 issue I discovered that several threads were locked with each other in an unusual place; I've moved the piece of code inside a lock[] context and so far it's looking promising. --- ThirdParty/SmartThreadPool/SmartThreadPool.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/ThirdParty/SmartThreadPool/SmartThreadPool.cs b/ThirdParty/SmartThreadPool/SmartThreadPool.cs index bd52f62..8c9d38b 100644 --- a/ThirdParty/SmartThreadPool/SmartThreadPool.cs +++ b/ThirdParty/SmartThreadPool/SmartThreadPool.cs @@ -535,17 +535,10 @@ namespace Amib.Threading // Process until shutdown. while(!_shutdown) { - // Update the last time this thread was seen alive. - // It's good for debugging. - _workerThreads[Thread.CurrentThread] = DateTime.Now; - + // Wait for a work item, shutdown, or timeout WorkItem workItem = Dequeue(); - // Update the last time this thread was seen alive. - // It's good for debugging. - _workerThreads[Thread.CurrentThread] = DateTime.Now; - // On timeout or shut down. if (null == workItem) { @@ -554,6 +547,10 @@ namespace Amib.Threading { lock(_workerThreads.SyncRoot) { + // Update the last time this thread was seen alive. + // It's good for debugging. + _workerThreads[Thread.CurrentThread] = DateTime.Now; + if (_workerThreads.Count > _stpStartInfo.MinWorkerThreads) { // Inform that the thread is quiting and then quit. -- cgit v1.1 From 91b1d17e5bd3ff6ed006744bc529b53a67af1a64 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 18 May 2010 01:09:47 -0700 Subject: Fix for hanging on "Connecting to region".. caused by packets being processed before the presence has bound to receive events. Fixed this by adding packets to a queue and then processing them when the presence is ready. --- OpenSim/Client/MXP/ClientStack/MXPClientView.cs | 4 + .../Sirikata/ClientStack/SirikataClientView.cs | 4 + .../Client/VWoHTTP/ClientStack/VWHClientView.cs | 4 + OpenSim/Framework/IClientAPI.cs | 1 + .../Region/ClientStack/LindenUDP/LLClientView.cs | 37 +++++++- .../Region/Examples/SimpleModule/MyNpcCharacter.cs | 4 + OpenSim/Region/Framework/Scenes/ScenePresence.cs | 102 +++++++++++---------- .../Server/IRCClientView.cs | 4 + .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 4 + OpenSim/Tests/Common/Mock/TestClient.cs | 4 + 10 files changed, 114 insertions(+), 54 deletions(-) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 12989f5..39923cb 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -819,6 +819,10 @@ namespace OpenSim.Client.MXP.ClientStack //throw new System.NotImplementedException(); } + public void ProcessPendingPackets() + { + } + public void ProcessInPacket(Packet NewPack) { //throw new System.NotImplementedException(); diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index c4b5c87..7c8a979 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -439,6 +439,10 @@ namespace OpenSim.Client.Sirikata.ClientStack throw new System.NotImplementedException(); } + public void ProcessPendingPackets() + { + } + public void ProcessInPacket(Packet NewPack) { throw new System.NotImplementedException(); diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 39a16bc..5ad1643 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -445,6 +445,10 @@ namespace OpenSim.Client.VWoHTTP.ClientStack throw new System.NotImplementedException(); } + public void ProcessPendingPackets() + { + } + public void ProcessInPacket(Packet NewPack) { throw new System.NotImplementedException(); diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index c597d62..ae2a80c 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1112,6 +1112,7 @@ namespace OpenSim.Framework void SetDebugPacketLevel(int newDebug); void InPacket(object NewPack); + void ProcessPendingPackets(); void ProcessInPacket(Packet NewPack); void Close(); void Close(bool sendStop); diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 5670a78..df6a767 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -376,6 +376,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private AgentUpdateArgs lastarg; private bool m_IsActive = true; private bool m_IsLoggingOut = false; + private bool m_IsPresenceReady = false; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -399,6 +400,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private Timer m_propertiesPacketTimer; private List m_propertiesBlocks = new List(); + private List m_pendingPackets; #endregion Class Members @@ -439,6 +441,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP get { return m_IsActive; } set { m_IsActive = value; } } + public bool IsLoggingOut { get { return m_IsLoggingOut; } @@ -11196,18 +11199,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP } /// + /// This processes packets which have accumulated while the presence was still in the process of initialising. + /// + public void ProcessPendingPackets() + { + m_IsPresenceReady = true; + foreach (Packet p in m_pendingPackets) + { + ProcessInPacket(p); + } + m_pendingPackets.Clear(); + } + + /// /// Entryway from the client to the simulator. All UDP packets from the client will end up here /// /// OpenMetaverse.packet public void ProcessInPacket(Packet Pack) { - if (m_debugPacketLevel >= 255) - m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type); + if (!m_IsPresenceReady) + { + if (m_pendingPackets == null) + { + m_pendingPackets = new List(); + } + m_pendingPackets.Add(Pack); + } + else + { + if (m_debugPacketLevel >= 255) + m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type); - if (!ProcessPacketMethod(Pack)) - m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type); + if (!ProcessPacketMethod(Pack)) + m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type); - PacketPool.Instance.ReturnPacket(Pack); + PacketPool.Instance.ReturnPacket(Pack); + } } private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 84385ad..c454d1f 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -825,6 +825,10 @@ namespace OpenSim.Region.Examples.SimpleModule { } + public void ProcessPendingPackets() + { + } + public void ProcessInPacket(Packet NewPack) { } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index d76f029..0b644b9 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -129,7 +129,7 @@ namespace OpenSim.Region.Framework.Scenes private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation private Vector3 m_avUnscriptedSitPos; // for non-scripted prims - private Vector3 m_lastPosition; + private Vector3 m_lastPosition; private Vector3 m_lastWorldPosition; private Quaternion m_lastRotation; private Vector3 m_lastVelocity; @@ -715,8 +715,11 @@ namespace OpenSim.Region.Framework.Scenes // Request info about all the (root) agents in this region // Note: This won't send data *to* other clients in that region (children don't send) SendInitialFullUpdateToAllClients(); - RegisterToEvents(); + if (m_controllingClient != null) + { + m_controllingClient.ProcessPendingPackets(); + } SetDirectionVectors(); } @@ -858,7 +861,6 @@ namespace OpenSim.Region.Framework.Scenes m_grouptitle = gm.GetGroupTitle(m_uuid); m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; - m_scene.SetRootAgentScene(m_uuid); // Moved this from SendInitialData to ensure that m_appearance is initialized @@ -875,22 +877,22 @@ namespace OpenSim.Region.Framework.Scenes { Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); pos.Y = crossedBorder.BorderLine.Z - 1; - } - - //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet. - //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent, - //they'll bypass the landing point. But I can't think of any decent way of fixing this. - if (KnownChildRegionHandles.Count == 0) - { - ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); - if (land != null) - { - //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. - if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) - { - pos = land.LandData.UserLocation; - } - } + } + + //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet. + //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent, + //they'll bypass the landing point. But I can't think of any decent way of fixing this. + if (KnownChildRegionHandles.Count == 0) + { + ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); + if (land != null) + { + //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. + if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) + { + pos = land.LandData.UserLocation; + } + } } if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) @@ -1027,8 +1029,8 @@ namespace OpenSim.Region.Framework.Scenes bool isFlying = false; if (m_physicsActor != null) - isFlying = m_physicsActor.Flying; - + isFlying = m_physicsActor.Flying; + RemoveFromPhysicalScene(); Velocity = Vector3.Zero; AbsolutePosition = pos; @@ -1039,7 +1041,7 @@ namespace OpenSim.Region.Framework.Scenes SetHeight(m_appearance.AvatarHeight); } - SendTerseUpdateToAllClients(); + SendTerseUpdateToAllClients(); } @@ -1173,7 +1175,6 @@ namespace OpenSim.Region.Framework.Scenes pos.Z = ground + 1.5f; AbsolutePosition = pos; } - m_isChildAgent = false; bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); MakeRootAgent(AbsolutePosition, m_flying); @@ -1745,14 +1746,14 @@ namespace OpenSim.Region.Framework.Scenes // else // { // single or child prim -// } - if (part == null) //CW: Part may be gone. llDie() for example. - { - partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - } - else - { - partRot = part.GetWorldRotation(); +// } + if (part == null) //CW: Part may be gone. llDie() for example. + { + partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + else + { + partRot = part.GetWorldRotation(); } Quaternion partIRot = Quaternion.Inverse(partRot); @@ -1760,22 +1761,22 @@ namespace OpenSim.Region.Framework.Scenes Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av - - if (m_physicsActor == null) - { - AddToPhysicalScene(false); + + if (m_physicsActor == null) + { + AddToPhysicalScene(false); + } + //CW: If the part isn't null then we can set the current position + if (part != null) + { + Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset! + AbsolutePosition = avWorldStandUp; //KF: Fix stand up. + part.IsOccupied = false; } - //CW: If the part isn't null then we can set the current position - if (part != null) - { - Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset! - AbsolutePosition = avWorldStandUp; //KF: Fix stand up. - part.IsOccupied = false; - } - else - { - //CW: Since the part doesn't exist, a coarse standup position isn't an issue - AbsolutePosition = m_lastWorldPosition; + else + { + //CW: Since the part doesn't exist, a coarse standup position isn't an issue + AbsolutePosition = m_lastWorldPosition; } m_parentPosition = Vector3.Zero; @@ -1930,7 +1931,7 @@ namespace OpenSim.Region.Framework.Scenes // if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) ) { - autopilot = false; // close enough + autopilot = false; // close enough m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup. Not using the part's position because returning the AV to the last known standing position is likely to be more friendly, isn't it? */ @@ -1939,7 +1940,7 @@ namespace OpenSim.Region.Framework.Scenes } // else the autopilot will get us close } else - { // its a scripted sit + { // its a scripted sit m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup. I *am* using the part's position this time because we have no real idea how far away the avatar is from the sit target. */ @@ -3744,7 +3745,10 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); m_scene = scene; RegisterToEvents(); - + if (m_controllingClient != null) + { + m_controllingClient.ProcessPendingPackets(); + } /* AbsolutePosition = client.StartPos; diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 7c0fe4c..cab640b 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -878,6 +878,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } + public void ProcessPendingPackets() + { + } + public void ProcessInPacket(Packet NewPack) { diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 4323c94..b828357 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -839,6 +839,10 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } + public void ProcessPendingPackets() + { + } + public void ProcessInPacket(Packet NewPack) { } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 05a8ff0..815816a 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -882,6 +882,10 @@ namespace OpenSim.Tests.Common.Mock { } + public void ProcessPendingPackets() + { + } + public void ProcessInPacket(Packet NewPack) { } -- cgit v1.1 From ed1cfb52454410e5d03b11966fdff54d9950a28c Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 18 May 2010 02:33:41 -0700 Subject: Missed a nullref in the previous commit --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index df6a767..5b1aa86 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -11204,6 +11204,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void ProcessPendingPackets() { m_IsPresenceReady = true; + if (m_pendingPackets == null) + return; foreach (Packet p in m_pendingPackets) { ProcessInPacket(p); -- cgit v1.1 From 1c040d8c1ed5ee1ba1e80aa1d248a9b06d1790a5 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 18 May 2010 03:24:43 -0700 Subject: Fix to the scenario where we send an agent to a neighbouring sim (via teleport), then tell our neighbours to close the agents.. thereby disconnecting the user. Added a new CloseChildAgent method in lieu of CloseAgent. This has been a long standing problem - with any luck this will cure it. --- .../Simulation/LocalSimulationConnector.cs | 17 ++++++++++++++++ .../Simulation/RemoteSimulationConnector.cs | 15 ++++++++++++++ .../Framework/Interfaces/IInterregionComms.cs | 8 ++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 23 +++++++++++++++++----- .../Framework/Scenes/SceneCommunicationService.cs | 2 +- .../Server/Handlers/Simulation/AgentHandlers.cs | 23 ++++++++++++++++++++++ .../Simulation/SimulationServiceConnector.cs | 14 ++++++++++++- OpenSim/Services/Interfaces/ISimulationService.cs | 8 ++++++++ 8 files changed, 103 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index e32dbb3..329a259 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -290,6 +290,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; } + public bool CloseChildAgent(GridRegion destination, UUID id) + { + if (destination == null) + return false; + + foreach (Scene s in m_sceneList) + { + if (s.RegionInfo.RegionID == destination.RegionID) + { + //m_log.Debug("[LOCAL COMMS]: Found region to SendCloseAgent"); + return s.IncomingCloseChildAgent(id); + } + } + //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); + return false; + } + /** * Object-related communications */ diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index 9e8454f..377c868 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -253,6 +253,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation return false; } + public bool CloseChildAgent(GridRegion destination, UUID id) + { + if (destination == null) + return false; + + // Try local first + if (m_localBackend.CloseChildAgent(destination, id)) + return true; + + // else do the remote thing + if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) + return m_remoteConnector.CloseChildAgent(destination, id); + + return false; + } public bool CloseAgent(GridRegion destination, UUID id) { diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs index 2d6287f..67a500f 100644 --- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs @@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); /// + /// Close chid agent. + /// + /// + /// + /// + bool SendCloseChildAgent(ulong regionHandle, UUID id); + + /// /// Close agent. /// /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 1b08c50..f331984 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3914,12 +3914,22 @@ namespace OpenSim.Region.Framework.Scenes return false; } + public bool IncomingCloseAgent(UUID agentID) + { + return IncomingCloseAgent(agentID, false); + } + + public bool IncomingCloseChildAgent(UUID agentID) + { + return IncomingCloseAgent(agentID, true); + } + /// /// Tell a single agent to disconnect from the region. /// - /// /// - public bool IncomingCloseAgent(UUID agentID) + /// + public bool IncomingCloseAgent(UUID agentID, bool childOnly) { //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); @@ -3931,7 +3941,7 @@ namespace OpenSim.Region.Framework.Scenes { m_sceneGraph.removeUserCount(false); } - else + else if (!childOnly) { m_sceneGraph.removeUserCount(true); } @@ -3947,9 +3957,12 @@ namespace OpenSim.Region.Framework.Scenes } else presence.ControllingClient.SendShutdownConnectionNotice(); + presence.ControllingClient.Close(); + } + else if (!childOnly) + { + presence.ControllingClient.Close(); } - - presence.ControllingClient.Close(); return true; } diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 9d0e6f4..6309cd9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -281,7 +281,7 @@ namespace OpenSim.Region.Framework.Scenes uint x = 0, y = 0; Utils.LongToUInts(regionHandle, out x, out y); GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); - m_scene.SimulationService.CloseAgent(destination, agentID); + m_scene.SimulationService.CloseChildAgent(destination, agentID); } private void SendCloseChildAgentCompleted(IAsyncResult iar) diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index ab3250d..b648e12 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -108,6 +108,11 @@ namespace OpenSim.Server.Handlers.Simulation DoAgentDelete(request, responsedata, agentID, action, regionID); return responsedata; } + else if (method.Equals("DELETECHILD")) + { + DoChildAgentDelete(request, responsedata, agentID, action, regionID); + return responsedata; + } else { m_log.InfoFormat("[AGENT HANDLER]: method {0} not supported in agent message", method); @@ -320,6 +325,24 @@ namespace OpenSim.Server.Handlers.Simulation } } + protected void DoChildAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID) + { + m_log.Debug(" >>> DoChildAgentDelete action:" + action + "; RegionID:" + regionID); + + GridRegion destination = new GridRegion(); + destination.RegionID = regionID; + + if (action.Equals("release")) + ReleaseAgent(regionID, id); + else + m_SimulationService.CloseChildAgent(destination, id); + + responsedata["int_response_code"] = HttpStatusCode.OK; + responsedata["str_response_string"] = "OpenSim agent " + id.ToString(); + + m_log.Debug("[AGENT HANDLER]: Child Agent Released/Deleted."); + } + protected void DoAgentDelete(Hashtable request, Hashtable responsedata, UUID id, string action, UUID regionID) { m_log.Debug(" >>> DoDelete action:" + action + "; RegionID:" + regionID); diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index ff0dd7e..8e0063b 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -442,7 +442,7 @@ namespace OpenSim.Services.Connectors.Simulation return true; } - public bool CloseAgent(GridRegion destination, UUID id) + private bool CloseAgent(GridRegion destination, UUID id, bool ChildOnly) { string uri = string.Empty; try @@ -459,6 +459,8 @@ namespace OpenSim.Services.Connectors.Simulation WebRequest request = WebRequest.Create(uri); request.Method = "DELETE"; + if (ChildOnly) + request.Method += "CHILD"; request.Timeout = 10000; StreamReader sr = null; @@ -491,6 +493,16 @@ namespace OpenSim.Services.Connectors.Simulation return true; } + public bool CloseChildAgent(GridRegion destination, UUID id) + { + return CloseAgent(destination, id, true); + } + + public bool CloseAgent(GridRegion destination, UUID id) + { + return CloseAgent(destination, id, false); + } + #endregion Agents #region Objects diff --git a/OpenSim/Services/Interfaces/ISimulationService.cs b/OpenSim/Services/Interfaces/ISimulationService.cs index 67d7cbe..33d6fde 100644 --- a/OpenSim/Services/Interfaces/ISimulationService.cs +++ b/OpenSim/Services/Interfaces/ISimulationService.cs @@ -71,6 +71,14 @@ namespace OpenSim.Services.Interfaces bool ReleaseAgent(UUID originRegion, UUID id, string uri); /// + /// Close child agent. + /// + /// + /// + /// + bool CloseChildAgent(GridRegion destination, UUID id); + + /// /// Close agent. /// /// -- cgit v1.1 From bb0806c61e545b6509843ed0258475e47d4bb273 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 18 May 2010 03:44:09 -0700 Subject: Don't send kill packets to child agents as we close them --- OpenSim/Region/Framework/Scenes/Scene.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f331984..377abe3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3957,11 +3957,11 @@ namespace OpenSim.Region.Framework.Scenes } else presence.ControllingClient.SendShutdownConnectionNotice(); - presence.ControllingClient.Close(); + presence.ControllingClient.Close(false); } else if (!childOnly) { - presence.ControllingClient.Close(); + presence.ControllingClient.Close(true); } return true; } -- cgit v1.1 From 55f124745ffe743a2d93c2ef93cb5c2f4fe06178 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 18 May 2010 19:25:40 +0200 Subject: Allow remote admin to be used on a different port from the main region port --- OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs | 5 +++-- bin/OpenSim.ini.example | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index d7904a6..ed43363 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -63,7 +63,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController private static Object SOLock = new Object(); private OpenSimBase m_app; - private BaseHttpServer m_httpd; + private IHttpServer m_httpd; private IConfig m_config; private IConfigSource m_configSource; private string m_requiredPassword = String.Empty; @@ -113,9 +113,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController m_config = m_configSource.Configs["RemoteAdmin"]; m_log.Info("[RADMIN]: Remote Admin Plugin Enabled"); m_requiredPassword = m_config.GetString("access_password", String.Empty); + int port = m_config.GetInt("port", 0); m_app = openSim; - m_httpd = openSim.HttpServer; + m_httpd = MainServer.GetHttpServer((uint)port); Dictionary availableMethods = new Dictionary(); availableMethods["admin_create_region"] = XmlRpcCreateRegionMethod; diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 6d5ee14..f318a2d 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -594,6 +594,10 @@ [RemoteAdmin] enabled = false + + ; Set this to a nonzero value to have remote admin use a different port + port = 0 + access_password = unknown ; set this variable to true if you want the create_region XmlRpc -- cgit v1.1 From ba36c62caad0fb88f89863c9e0afdefc4f2897cc Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 19 May 2010 00:20:51 -0700 Subject: Fix a null reference issue in cmGetAvatarList() --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 07cba60..3e62c1a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -121,7 +121,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_List result = new LSL_List(); World.ForEachScenePresence(delegate (ScenePresence avatar) { - if (avatar.UUID != m_host.OwnerID) + if (avatar != null && avatar.UUID != m_host.OwnerID) { if (avatar.IsChildAgent == false) { -- cgit v1.1 From fc76b5f58950b747cfabec19a4349216a48c9c13 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 19 May 2010 00:24:54 -0700 Subject: Fix a null reference issue in cmGetAvatarList() --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 9f829da..4f1e9f7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_List result = new LSL_List(); foreach (ScenePresence avatar in World.GetAvatars()) { - if (avatar.UUID != m_host.OwnerID) + if (avatar != null && avatar.UUID != m_host.OwnerID) { if (avatar.IsChildAgent == false) { -- cgit v1.1 From f77f9ecd8f3f94ccc6d69c7625fd1eacfa9250d7 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 19 May 2010 13:44:59 -0700 Subject: Fix a nullref issue in SitAltitudeCallback --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 103 ++++++++++++----------- 1 file changed, 53 insertions(+), 50 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 565438d..68acabe 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -128,7 +128,7 @@ namespace OpenSim.Region.Framework.Scenes private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation private Vector3 m_avUnscriptedSitPos; // for non-scripted prims - private Vector3 m_lastPosition; + private Vector3 m_lastPosition; private Vector3 m_lastWorldPosition; private Quaternion m_lastRotation; private Vector3 m_lastVelocity; @@ -857,22 +857,22 @@ namespace OpenSim.Region.Framework.Scenes { Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); pos.Y = crossedBorder.BorderLine.Z - 1; - } - - //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet. - //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent, - //they'll bypass the landing point. But I can't think of any decent way of fixing this. - if (KnownChildRegionHandles.Count == 0) - { - ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); - if (land != null) - { - //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. - if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godlevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) - { - pos = land.LandData.UserLocation; - } - } + } + + //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet. + //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent, + //they'll bypass the landing point. But I can't think of any decent way of fixing this. + if (KnownChildRegionHandles.Count == 0) + { + ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); + if (land != null) + { + //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. + if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godlevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) + { + pos = land.LandData.UserLocation; + } + } } if (pos.X < 0 || pos.Y < 0 || pos.Z < 0) @@ -1036,8 +1036,8 @@ namespace OpenSim.Region.Framework.Scenes bool isFlying = false; if (m_physicsActor != null) - isFlying = m_physicsActor.Flying; - + isFlying = m_physicsActor.Flying; + RemoveFromPhysicalScene(); Velocity = Vector3.Zero; AbsolutePosition = pos; @@ -1048,7 +1048,7 @@ namespace OpenSim.Region.Framework.Scenes SetHeight(m_appearance.AvatarHeight); } - SendTerseUpdateToAllClients(); + SendTerseUpdateToAllClients(); } @@ -1736,14 +1736,14 @@ namespace OpenSim.Region.Framework.Scenes // else // { // single or child prim -// } - if (part == null) //CW: Part may be gone. llDie() for example. - { - partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - } - else - { - partRot = part.GetWorldRotation(); +// } + if (part == null) //CW: Part may be gone. llDie() for example. + { + partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + else + { + partRot = part.GetWorldRotation(); } Quaternion partIRot = Quaternion.Inverse(partRot); @@ -1751,22 +1751,22 @@ namespace OpenSim.Region.Framework.Scenes Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av - - if (m_physicsActor == null) - { - AddToPhysicalScene(false); + + if (m_physicsActor == null) + { + AddToPhysicalScene(false); } - //CW: If the part isn't null then we can set the current position - if (part != null) - { - Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset! - AbsolutePosition = avWorldStandUp; //KF: Fix stand up. - part.IsOccupied = false; - } - else - { - //CW: Since the part doesn't exist, a coarse standup position isn't an issue - AbsolutePosition = m_lastWorldPosition; + //CW: If the part isn't null then we can set the current position + if (part != null) + { + Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset! + AbsolutePosition = avWorldStandUp; //KF: Fix stand up. + part.IsOccupied = false; + } + else + { + //CW: Since the part doesn't exist, a coarse standup position isn't an issue + AbsolutePosition = m_lastWorldPosition; } m_parentPosition = Vector3.Zero; @@ -1920,7 +1920,7 @@ namespace OpenSim.Region.Framework.Scenes // if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) ) { - autopilot = false; // close enough + autopilot = false; // close enough m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup. Not using the part's position because returning the AV to the last known standing position is likely to be more friendly, isn't it? */ @@ -1929,7 +1929,7 @@ namespace OpenSim.Region.Framework.Scenes } // else the autopilot will get us close } else - { // its a scripted sit + { // its a scripted sit m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup. I *am* using the part's position this time because we have no real idea how far away the avatar is from the sit target. */ @@ -2357,11 +2357,14 @@ namespace OpenSim.Region.Framework.Scenes // { // single or child prim partIRot = Quaternion.Inverse(part.GetWorldRotation()); // } - float offZ = collisionPoint.Z - m_initialSitTarget.Z; - Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction -//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); - m_pos += offset; -// ControllingClient.SendClearFollowCamProperties(part.UUID); + if (m_initialSitTarget != null) + { + float offZ = collisionPoint.Z - m_initialSitTarget.Z; + Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction + //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); + m_pos += offset; + // ControllingClient.SendClearFollowCamProperties(part.UUID); + } } } // End SitAltitudeCallback KF. -- cgit v1.1 From 6933b48a7e94511f1de969b28a61d834888fd2f5 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 19 May 2010 13:49:34 -0700 Subject: Fix a nullref issue in SitAltitudeCallback --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 0b644b9..b6081de 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2368,12 +2368,15 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); // else // { // single or child prim partIRot = Quaternion.Inverse(part.GetWorldRotation()); -// } - float offZ = collisionPoint.Z - m_initialSitTarget.Z; - Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction -//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); - m_pos += offset; -// ControllingClient.SendClearFollowCamProperties(part.UUID); +// } + if (m_initialSitTarget != null) + { + float offZ = collisionPoint.Z - m_initialSitTarget.Z; + Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction + //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); + m_pos += offset; + // ControllingClient.SendClearFollowCamProperties(part.UUID); + } } } // End SitAltitudeCallback KF. -- cgit v1.1 From 5532341bf9e477a007e81bdbcc6477923703e2a2 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 19 May 2010 14:04:44 -0700 Subject: Initialise m_initialSitTarget to ZERO_VACTOR for safety's sake as per convo with kitto --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b6081de..c89f656 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -213,7 +213,7 @@ namespace OpenSim.Region.Framework.Scenes private bool m_autopilotMoving; private Vector3 m_autoPilotTarget; private bool m_sitAtAutoTarget; - private Vector3 m_initialSitTarget; //KF: First estimate of where to sit + private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit private string m_nextSitAnimation = String.Empty; -- cgit v1.1 From 76238715e3c8f4ba22cdd6dd09a282a0b52bad4d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 4 Mar 2010 20:08:25 +0000 Subject: move linden notecard parsing from LSL_Api.cs to SLUtil so that region modules can use it backport from master --- OpenSim/Framework/SLUtil.cs | 282 +++++++++++++++++++++ OpenSim/Region/Application/ConfigurationLoader.cs | 19 +- OpenSim/Region/Framework/Scenes/EventManager.cs | 30 +-- .../Framework/Scenes/SceneObjectPartInventory.cs | 1 - .../Shared/Api/Implementation/LSL_Api.cs | 83 +----- 5 files changed, 307 insertions(+), 108 deletions(-) create mode 100644 OpenSim/Framework/SLUtil.cs diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs new file mode 100644 index 0000000..ff5f8b9 --- /dev/null +++ b/OpenSim/Framework/SLUtil.cs @@ -0,0 +1,282 @@ +using System; +using System.Collections.Generic; +using OpenMetaverse; + +namespace OpenSim.Framework +{ + public static class SLUtil + { + #region SL / file extension / content-type conversions + + public static string SLAssetTypeToContentType(int assetType) + { + switch ((AssetType)assetType) + { + case AssetType.Texture: + return "image/x-j2c"; + case AssetType.Sound: + return "application/ogg"; + case AssetType.CallingCard: + return "application/vnd.ll.callingcard"; + case AssetType.Landmark: + return "application/vnd.ll.landmark"; + case AssetType.Clothing: + return "application/vnd.ll.clothing"; + case AssetType.Object: + return "application/vnd.ll.primitive"; + case AssetType.Notecard: + return "application/vnd.ll.notecard"; + case AssetType.Folder: + return "application/vnd.ll.folder"; + case AssetType.RootFolder: + return "application/vnd.ll.rootfolder"; + case AssetType.LSLText: + return "application/vnd.ll.lsltext"; + case AssetType.LSLBytecode: + return "application/vnd.ll.lslbyte"; + case AssetType.TextureTGA: + case AssetType.ImageTGA: + return "image/tga"; + case AssetType.Bodypart: + return "application/vnd.ll.bodypart"; + case AssetType.TrashFolder: + return "application/vnd.ll.trashfolder"; + case AssetType.SnapshotFolder: + return "application/vnd.ll.snapshotfolder"; + case AssetType.LostAndFoundFolder: + return "application/vnd.ll.lostandfoundfolder"; + case AssetType.SoundWAV: + return "audio/x-wav"; + case AssetType.ImageJPEG: + return "image/jpeg"; + case AssetType.Animation: + return "application/vnd.ll.animation"; + case AssetType.Gesture: + return "application/vnd.ll.gesture"; + case AssetType.Simstate: + return "application/x-metaverse-simstate"; + case AssetType.Unknown: + default: + return "application/octet-stream"; + } + } + + public static sbyte ContentTypeToSLAssetType(string contentType) + { + switch (contentType) + { + case "image/x-j2c": + case "image/jp2": + return (sbyte)AssetType.Texture; + case "application/ogg": + return (sbyte)AssetType.Sound; + case "application/vnd.ll.callingcard": + case "application/x-metaverse-callingcard": + return (sbyte)AssetType.CallingCard; + case "application/vnd.ll.landmark": + case "application/x-metaverse-landmark": + return (sbyte)AssetType.Landmark; + case "application/vnd.ll.clothing": + case "application/x-metaverse-clothing": + return (sbyte)AssetType.Clothing; + case "application/vnd.ll.primitive": + case "application/x-metaverse-primitive": + return (sbyte)AssetType.Object; + case "application/vnd.ll.notecard": + case "application/x-metaverse-notecard": + return (sbyte)AssetType.Notecard; + case "application/vnd.ll.folder": + return (sbyte)AssetType.Folder; + case "application/vnd.ll.rootfolder": + return (sbyte)AssetType.RootFolder; + case "application/vnd.ll.lsltext": + case "application/x-metaverse-lsl": + return (sbyte)AssetType.LSLText; + case "application/vnd.ll.lslbyte": + case "application/x-metaverse-lso": + return (sbyte)AssetType.LSLBytecode; + case "image/tga": + // Note that AssetType.TextureTGA will be converted to AssetType.ImageTGA + return (sbyte)AssetType.ImageTGA; + case "application/vnd.ll.bodypart": + case "application/x-metaverse-bodypart": + return (sbyte)AssetType.Bodypart; + case "application/vnd.ll.trashfolder": + return (sbyte)AssetType.TrashFolder; + case "application/vnd.ll.snapshotfolder": + return (sbyte)AssetType.SnapshotFolder; + case "application/vnd.ll.lostandfoundfolder": + return (sbyte)AssetType.LostAndFoundFolder; + case "audio/x-wav": + return (sbyte)AssetType.SoundWAV; + case "image/jpeg": + return (sbyte)AssetType.ImageJPEG; + case "application/vnd.ll.animation": + case "application/x-metaverse-animation": + return (sbyte)AssetType.Animation; + case "application/vnd.ll.gesture": + case "application/x-metaverse-gesture": + return (sbyte)AssetType.Gesture; + case "application/x-metaverse-simstate": + return (sbyte)AssetType.Simstate; + case "application/octet-stream": + default: + return (sbyte)AssetType.Unknown; + } + } + + public static sbyte ContentTypeToSLInvType(string contentType) + { + switch (contentType) + { + case "image/x-j2c": + case "image/jp2": + case "image/tga": + case "image/jpeg": + return (sbyte)InventoryType.Texture; + case "application/ogg": + case "audio/x-wav": + return (sbyte)InventoryType.Sound; + case "application/vnd.ll.callingcard": + case "application/x-metaverse-callingcard": + return (sbyte)InventoryType.CallingCard; + case "application/vnd.ll.landmark": + case "application/x-metaverse-landmark": + return (sbyte)InventoryType.Landmark; + case "application/vnd.ll.clothing": + case "application/x-metaverse-clothing": + case "application/vnd.ll.bodypart": + case "application/x-metaverse-bodypart": + return (sbyte)InventoryType.Wearable; + case "application/vnd.ll.primitive": + case "application/x-metaverse-primitive": + return (sbyte)InventoryType.Object; + case "application/vnd.ll.notecard": + case "application/x-metaverse-notecard": + return (sbyte)InventoryType.Notecard; + case "application/vnd.ll.folder": + return (sbyte)InventoryType.Folder; + case "application/vnd.ll.rootfolder": + return (sbyte)InventoryType.RootCategory; + case "application/vnd.ll.lsltext": + case "application/x-metaverse-lsl": + case "application/vnd.ll.lslbyte": + case "application/x-metaverse-lso": + return (sbyte)InventoryType.LSL; + case "application/vnd.ll.trashfolder": + case "application/vnd.ll.snapshotfolder": + case "application/vnd.ll.lostandfoundfolder": + return (sbyte)InventoryType.Folder; + case "application/vnd.ll.animation": + case "application/x-metaverse-animation": + return (sbyte)InventoryType.Animation; + case "application/vnd.ll.gesture": + case "application/x-metaverse-gesture": + return (sbyte)InventoryType.Gesture; + case "application/x-metaverse-simstate": + return (sbyte)InventoryType.Snapshot; + case "application/octet-stream": + default: + return (sbyte)InventoryType.Unknown; + } + } + + #endregion SL / file extension / content-type conversions + + /// + /// Parse a notecard in Linden format to a string of ordinary text. + /// + /// + /// + public static string ParseNotecardToString(string rawInput) + { + return string.Join("\n", ParseNotecardToList(rawInput).ToArray()); + } + + /// + /// Parse a notecard in Linden format to a list of ordinary lines. + /// + /// + /// + public static List ParseNotecardToList(string rawInput) + { + string[] input = rawInput.Replace("\r", "").Split('\n'); + int idx = 0; + int level = 0; + List output = new List(); + string[] words; + + while (idx < input.Length) + { + if (input[idx] == "{") + { + level++; + idx++; + continue; + } + + if (input[idx]== "}") + { + level--; + idx++; + continue; + } + + switch (level) + { + case 0: + words = input[idx].Split(' '); // Linden text ver + // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard) + if (words.Length < 3) + return output; + + int version = int.Parse(words[3]); + if (version != 2) + return output; + break; + case 1: + words = input[idx].Split(' '); + if (words[0] == "LLEmbeddedItems") + break; + if (words[0] == "Text") + { + int len = int.Parse(words[2]); + idx++; + + int count = -1; + + while (count < len) + { + // int l = input[idx].Length; + string ln = input[idx]; + + int need = len-count-1; + if (ln.Length > need) + ln = ln.Substring(0, need); + + output.Add(ln); + count += ln.Length + 1; + idx++; + } + + return output; + } + break; + case 2: + words = input[idx].Split(' '); // count + if (words[0] == "count") + { + int c = int.Parse(words[1]); + if (c > 0) + return output; + break; + } + break; + } + idx++; + } + + return output; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index 21edcc5..da77a2b 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -164,12 +164,12 @@ namespace OpenSim m_config.Source = new IniConfigSource(); m_config.Source.Merge(DefaultConfig()); - m_log.Info("[CONFIG] Reading configuration settings"); + m_log.Info("[CONFIG]: Reading configuration settings"); if (sources.Count == 0) { - m_log.FatalFormat("[CONFIG] Could not load any configuration"); - m_log.FatalFormat("[CONFIG] Did you copy the OpenSim.ini.example file to OpenSim.ini?"); + m_log.FatalFormat("[CONFIG]: Could not load any configuration"); + m_log.FatalFormat("[CONFIG]: Did you copy the OpenSim.ini.example file to OpenSim.ini?"); Environment.Exit(1); } @@ -182,8 +182,8 @@ namespace OpenSim if (!iniFileExists) { - m_log.FatalFormat("[CONFIG] Could not load any configuration"); - m_log.FatalFormat("[CONFIG] Configuration exists, but there was an error loading it!"); + m_log.FatalFormat("[CONFIG]: Could not load any configuration"); + m_log.FatalFormat("[CONFIG]: Configuration exists, but there was an error loading it!"); Environment.Exit(1); } @@ -257,20 +257,17 @@ namespace OpenSim if (!IsUri(iniPath)) { - m_log.InfoFormat("[CONFIG] Reading configuration file {0}", - Path.GetFullPath(iniPath)); + m_log.InfoFormat("[CONFIG]: Reading configuration file {0}", Path.GetFullPath(iniPath)); m_config.Source.Merge(new IniConfigSource(iniPath)); success = true; } else { - m_log.InfoFormat("[CONFIG] {0} is a http:// URI, fetching ...", - iniPath); + m_log.InfoFormat("[CONFIG]: {0} is a http:// URI, fetching ...", iniPath); // The ini file path is a http URI // Try to read it - // try { XmlReader r = XmlReader.Create(iniPath); @@ -281,7 +278,7 @@ namespace OpenSim } catch (Exception e) { - m_log.FatalFormat("[CONFIG] Exception reading config from URI {0}\n" + e.ToString(), iniPath); + m_log.FatalFormat("[CONFIG]: Exception reading config from URI {0}\n" + e.ToString(), iniPath); Environment.Exit(1); } } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 57e1c37..4365ece 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -107,21 +107,24 @@ namespace OpenSim.Region.Framework.Scenes public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; /// - /// Called when an object is touched/grabbed. + /// Fired when an object is touched/grabbed. /// /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of - /// the root part. - public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); + /// the root part. public event ObjectGrabDelegate OnObjectGrab; + public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); public event ObjectGrabDelegate OnObjectGrabbing; public event ObjectDeGrabDelegate OnObjectDeGrab; public event ScriptResetDelegate OnScriptReset; - public event OnPermissionErrorDelegate OnPermissionError; + public event OnPermissionErrorDelegate OnPermissionError; - public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); + /// + /// Fired when a new script is created. + /// public event NewRezScript OnRezScript; + public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); public delegate void RemoveScript(uint localID, UUID itemID); public event RemoveScript OnRemoveScript; @@ -163,38 +166,35 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ClientClosed(UUID clientID, Scene scene); - public event ClientClosed OnClientClosed; - - public delegate void ScriptChangedEvent(uint localID, uint change); + public event ClientClosed OnClientClosed; + /// + /// This is fired when a scene object property that a script might be interested in (such as color, scale or + /// inventory) changes. Only enough information is sent for the LSL changed event + /// (see http://lslwiki.net/lslwiki/wakka.php?wakka=changed) + /// public event ScriptChangedEvent OnScriptChangedEvent; + public delegate void ScriptChangedEvent(uint localID, uint change); public delegate void ScriptControlEvent(uint localID, UUID item, UUID avatarID, uint held, uint changed); - public event ScriptControlEvent OnScriptControlEvent; public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); - public event ScriptAtTargetEvent OnScriptAtTargetEvent; public delegate void ScriptNotAtTargetEvent(uint localID); - public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); - public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; public delegate void ScriptNotAtRotTargetEvent(uint localID); - public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; public delegate void ScriptColliding(uint localID, ColliderArgs colliders); - public event ScriptColliding OnScriptColliderStart; public event ScriptColliding OnScriptColliding; public event ScriptColliding OnScriptCollidingEnd; - public event ScriptColliding OnScriptLandColliderStart; public event ScriptColliding OnScriptLandColliding; public event ScriptColliding OnScriptLandColliderEnd; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index a555eae..21ca1de 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -638,7 +638,6 @@ namespace OpenSim.Region.Framework.Scenes m_items[item.ItemID] = item; m_inventorySerial++; m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3b2c9b1..e4e087f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9784,90 +9784,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Notecard nc = new Notecard(); nc.lastRef = DateTime.Now; - nc.text = ParseText(text.Replace("\r", "").Split('\n')); + nc.text = SLUtil.ParseNotecardToList(text).ToArray(); m_Notecards[assetID] = nc; } } - protected static string[] ParseText(string[] input) - { - int idx = 0; - int level = 0; - List output = new List(); - string[] words; - - while (idx < input.Length) - { - if (input[idx] == "{") - { - level++; - idx++; - continue; - } - - if (input[idx]== "}") - { - level--; - idx++; - continue; - } - - switch (level) - { - case 0: - words = input[idx].Split(' '); // Linden text ver - // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard) - if (words.Length < 3) - return new String[0]; - - int version = int.Parse(words[3]); - if (version != 2) - return new String[0]; - break; - case 1: - words = input[idx].Split(' '); - if (words[0] == "LLEmbeddedItems") - break; - if (words[0] == "Text") - { - int len = int.Parse(words[2]); - idx++; - - int count = -1; - - while (count < len) - { - // int l = input[idx].Length; - string ln = input[idx]; - - int need = len-count-1; - if (ln.Length > need) - ln = ln.Substring(0, need); - - output.Add(ln); - count += ln.Length + 1; - idx++; - } - - return output.ToArray(); - } - break; - case 2: - words = input[idx].Split(' '); // count - if (words[0] == "count") - { - int c = int.Parse(words[1]); - if (c > 0) - return new String[0]; - break; - } - break; - } - idx++; - } - return output.ToArray(); - } - public static bool IsCached(UUID assetID) { lock (m_Notecards) @@ -9923,4 +9844,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } -} +} \ No newline at end of file -- cgit v1.1 From 1ed7b591b2f49f9fb5def956d0af896cbdaef750 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 5 Mar 2010 22:38:03 +0000 Subject: automatically delete %temp% directory after running tests this prevents a huge cruft buildup --- .nant/local.include | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.nant/local.include b/.nant/local.include index 14fd3c0..94398a2 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -142,6 +142,8 @@ + + -- cgit v1.1 From 8d832e32317466a9acf046671ca73eb72606117e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 11 Mar 2010 21:04:56 +0000 Subject: Upgrade Newtonsoft.Json.dll from 1.3 to 3.5r6 Actually using the one built against Net 2.0 (labelled Newtonsoft.Json.Net20.dll) since the 3.5 build is not compatible with Mono 2.4 (though it is with Mono 2.6) --- CONTRIBUTORS.txt | 1 + bin/Newtonsoft.Json.XML | 6817 ++++++++++++++++++++++++++++++++++++++++------- bin/Newtonsoft.Json.dll | Bin 73728 -> 356352 bytes bin/Newtonsoft.Json.pdb | Bin 192000 -> 742912 bytes 4 files changed, 5828 insertions(+), 990 deletions(-) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 5b4959a..e5c8cb9 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -164,6 +164,7 @@ This software uses components from the following developers: * log4net (http://logging.apache.org/log4net/) * GlynnTucker.Cache (http://gtcache.sourceforge.net/) * NDesk.Options 0.2.1 (http://www.ndesk.org/Options) +* Json.NET 3.5 Release 6. The binary used is actually Newtonsoft.Json.Net20.dll for Mono 2.4 compatability (http://james.newtonking.com/projects/json-net.aspx) Some plugins are based on Cable Beach Cable Beach is Copyright (c) 2008 Intel Corporation diff --git a/bin/Newtonsoft.Json.XML b/bin/Newtonsoft.Json.XML index b84e336..5af3593 100644 --- a/bin/Newtonsoft.Json.XML +++ b/bin/Newtonsoft.Json.XML @@ -1,990 +1,5827 @@ - - - - Newtonsoft.Json - - - - - Determines whether the string contains white space. - - The string to test for white space. - - true if the string contains white space; otherwise, false. - - - - - Determines whether the string is all white space. Empty string will return false. - - The string to test whether it is all white space. - - true if the string is all white space; otherwise, false. - - - - - Ensures the target string ends with the specified string. - - The target. - The value. - The target string with the value string at the end. - - - - Determines whether the SqlString is null or empty. - - The string. - - true if the SqlString is null or empty; otherwise, false. - - - - - Perform an action if the string is not null or empty. - - The value. - The action to perform. - - - - Indents the specified string. - - The string to indent. - The number of characters to indent by. - - - - - Indents the specified string. - - The string to indent. - The number of characters to indent by. - The indent character. - - - - - Numbers the lines. - - The string to number. - - - - - Nulls an empty string. - - The string. - Null if the string was null, otherwise the string unchanged. - - - - The exception thrown when an error occurs while reading Json text. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class - with a specified error message. - - The error message that explains the reason for the exception. - - - - Initializes a new instance of the class - with a specified error message and a reference to the inner exception that is the cause of this exception. - - The error message that explains the reason for the exception. - The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - - - - Gets the type of the typed list's items. - - The type. - The type of the typed list's items. - - - - Tests whether the list's items are their unitialized value. - - The list. - Whether the list's items are their unitialized value - - - - Gets the member's underlying type. - - The member. - The underlying type of the member. - - - - Determines whether the member is an indexed property. - - The member. - - true if the member is an indexed property; otherwise, false. - - - - - Determines whether the property is an indexed property. - - The property. - - true if the property is an indexed property; otherwise, false. - - - - - Gets the member's value on the object. - - The member. - The target object. - The member's value on the object. - - - - Sets the member's value on the target object. - - The member. - The target. - The value. - - - - Determines whether the specified MemberInfo can be read. - - The MemberInfo to determine whether can be read. - - true if the specified MemberInfo can be read; otherwise, false. - - - - - Determines whether the specified MemberInfo can be set. - - The MemberInfo to determine whether can be set. - - true if the specified MemberInfo can be set; otherwise, false. - - - - - Specifies reference loop handling options for the . - - - - - Throw a when a loop is encountered. - - - - - Ignore loop references and do not serialize. - - - - - Serialize loop references. - - - - - Serializes and deserializes objects into and from the Json format. - The enables you to control how objects are encoded into Json. - - - - - Initializes a new instance of the class. - - - - - Deserializes the Json structure contained by the specified . - - The that contains the Json structure to deserialize. - The being deserialized. - - - - Deserializes the Json structure contained by the specified - into an instance of the specified type. - - The type of object to create. - The of object being deserialized. - The instance of being deserialized. - - - - Serializes the specified and writes the Json structure - to a Stream using the specified . - - The used to write the Json structure. - The to serialize. - - - - Serializes the specified and writes the Json structure - to a Stream using the specified . - - The used to write the Json structure. - The to serialize. - - - - Get or set how reference loops (e.g. a class referencing itself) is handled. - - - - - Represents a JavaScript array. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class that - contains elements copied from the specified collection. - - The collection whose elements are copied to the new array. - - - - Initializes a new instance of the class that - is empty and has the specified initial capacity. - - The number of elements that the new array can initially store. - - - - Provides methods for converting between common language runtime types and JavaScript types. - - - - - Represents JavaScript's boolean value true as a string. This field is read-only. - - - - - Represents JavaScript's boolean value false as a string. This field is read-only. - - - - - Represents JavaScript's null as a string. This field is read-only. - - - - - Represents JavaScript's undefined as a string. This field is read-only. - - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - The string delimiter character. - A Json string representation of the . - - - - Converts the to it's JavaScript string representation. - - The value to convert. - A Json string representation of the . - - - - Serializes the specified object to a Json object. - - The object to serialize. - A Json string representation of the object. - - - - Deserializes the specified object to a Json object. - - The object to deserialize. - The deserialized object from the Json string. - - - - Deserializes the specified object to a Json object. - - The object to deserialize. - The of object being deserialized. - The deserialized object from the Json string. - - - - Deserializes the specified object to a Json object. - - The type of the object to deserialize. - The object to deserialize. - The deserialized object from the Json string. - - - - Deserializes the specified object to a Json object. - - The type of the object to deserialize. - The object to deserialize. - Converters to use while deserializing. - The deserialized object from the Json string. - - - - The exception thrown when an error occurs during Json serialization or deserialization. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class - with a specified error message. - - The error message that explains the reason for the exception. - - - - Initializes a new instance of the class - with a specified error message and a reference to the inner exception that is the cause of this exception. - - The error message that explains the reason for the exception. - The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - - - - The exception thrown when an error occurs while reading Json text. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class - with a specified error message. - - The error message that explains the reason for the exception. - - - - Initializes a new instance of the class - with a specified error message and a reference to the inner exception that is the cause of this exception. - - The error message that explains the reason for the exception. - The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. - - - - Represents a JavaScript constructor. - - - - - Determines whether the collection is null or empty. - - The collection. - - true if the collection is null or empty; otherwise, false. - - - - - Determines whether the collection is null or empty. - - The collection. - - true if the collection is null or empty; otherwise, false. - - - - - Determines whether the collection is null, empty or its contents are uninitialized values. - - The list. - - true if the collection is null or empty or its contents are uninitialized values; otherwise, false. - - - - - Makes a slice of the specified list in between the start and end indexes. - - The list. - The start index. - The end index. - A slice of the list. - - - - Makes a slice of the specified list in between the start and end indexes, - getting every so many items based upon the step. - - The list. - The start index. - The end index. - The step. - A slice of the list. - - - - Group the collection using a function which returns the key. - - The source collection to group. - The key selector. - A Dictionary with each key relating to a list of objects in a list grouped under it. - - - - Adds the elements of the specified collection to the specified generic IList. - - The list to add to. - The collection of elements to add. - - - - Builds a string. Unlike StringBuilder this class lets you reuse it's internal buffer. - - - - - Represents a JavaScript object. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class that - contains values copied from the specified . - - The whose elements are copied to the new object. - - - - Specifies the type of Json token. - - - - - This is returned by the if a method has not been called. - - - - - An object start token. - - - - - An array start token. - - - - - An object property name. - - - - - A comment. - - - - - An interger. - - - - - A float. - - - - - A string. - - - - - A boolean. - - - - - A null token. - - - - - An undefined token. - - - - - An object end token. - - - - - An array end token. - - - - - A JavaScript object constructor. - - - - - A Date. - - - - - Checks if the attributeName is a namespace attribute. - - Attribute name to test. - The attribute name prefix if it has one, otherwise an empty string. - True if attribute name is for a namespace attribute, otherwise false. - - - - Specifies the state of the . - - - - - An exception has been thrown, which has left the in an invalid state. - You may call the method to put the in the Closed state. - Any other method calls results in an being thrown. - - - - - The method has been called. - - - - - An object is being written. - - - - - A array is being written. - - - - - A property is being written. - - - - - A write method has not been called. - - - - - Specifies formatting options for the . - - - - - No special formatting is applied. This is the default. - - - - - Causes child objects to be indented according to the and settings. - - - - - Represents a writer that provides a fast, non-cached, forward-only way of generating Json data. - - - - - Creates an instance of the JsonWriter class using the specified . - - The TextWriter to write to. - - - - Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream. - - - - - Closes this stream and the underlying stream. - - - - - Writes the beginning of a Json object. - - - - - Writes the end of a Json object. - - - - - Writes the beginning of a Json array. - - - - - Writes the end of an array. - - - - - Writes the property name of a name/value pair on a Json object. - - - - - - Writes the end of the current Json object or array. - - - - - Writes a null value. - - - - - Writes an undefined value. - - - - - Writes raw JavaScript manually. - - The raw JavaScript to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes a value. - - The value to write. - - - - Writes out a comment /*...*/ containing the specified text. - - Text to place inside the comment. - - - - Writes out the given white space. - - The string of white space characters. - - - - Gets the state of the writer. - - - - - Indicates how the output is formatted. - - - - - Gets or sets how many IndentChars to write for each level in the hierarchy when is set to Formatting.Indented. - - - - - Gets or sets which character to use to quote attribute values. - - - - - Gets or sets which character to use for indenting when is set to Formatting.Indented. - - - - - Gets or sets a value indicating whether object names will be surrounded with quotes. - - - - - Represents a reader that provides fast, non-cached, forward-only access to serialized Json data. - - - - - Initializes a new instance of the class with the specified . - - The TextReader containing the XML data to read. - - - - Reads the next Json token from the stream. - - - - - - Changes the to Closed. - - - - - Gets the quotation mark character used to enclose the value of a string. - - - - - Gets the type of the current Json token. - - - - - Gets the text value of the current Json token. - - - - - Gets The Common Language Runtime (CLR) type for the current Json token. - - - - + + + + Newtonsoft.Json.Net20 + + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized Json data. + + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized Json data. + + + + + Initializes a new instance of the class with the specified . + + + + + Reads the next JSON token from the stream. + + true if the next token was read successfully; false if there are no more tokens to read. + + + + Reads the next JSON token from the stream as a . + + A or a null reference if the next JSON token is null. + + + + Skips the children of the current token. + + + + + Sets the current token. + + The new token. + + + + Sets the current token and value. + + The new token. + The value. + + + + Sets the state based on current token type. + + + + + Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + + + + + Releases unmanaged and - optionally - managed resources + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Changes the to Closed. + + + + + Gets the current reader state. + + The current reader state. + + + + Gets the quotation mark character used to enclose the value of a string. + + + + + Gets the type of the current Json token. + + + + + Gets the text value of the current Json token. + + + + + Gets The Common Language Runtime (CLR) type for the current Json token. + + + + + Gets the depth of the current token in the JSON document. + + The depth of the current token in the JSON document. + + + + Specifies the state of the reader. + + + + + The Read method has not been called. + + + + + The end of the file has been reached successfully. + + + + + Reader is at a property. + + + + + Reader is at the start of an object. + + + + + Reader is in an object. + + + + + Reader is at the start of an array. + + + + + Reader is in an array. + + + + + The Close method has been called. + + + + + Reader has just read a value. + + + + + Reader is at the start of a constructor. + + + + + Reader in a constructor. + + + + + An error occurred that prevents the read operation from continuing. + + + + + The end of the file has been reached successfully. + + + + + Initializes a new instance of the class. + + The stream. + + + + Initializes a new instance of the class. + + The stream. + if set to true the root object will be read as a JSON array. + The used when reading values from BSON. + + + + Reads the next JSON token from the stream as a . + + + A or a null reference if the next JSON token is null. + + + + + Reads the next JSON token from the stream. + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Gets or sets a value indicating whether the root object will be read as a JSON array. + + + true if the root object will be read as a JSON array; otherwise, false. + + + + + Gets or sets the used when reading values from BSON. + + The used when reading values from BSON. + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating Json data. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating Json data. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating Json data. + + + + + Creates an instance of the JsonWriter class. + + + + + Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream. + + + + + Closes this stream and the underlying stream. + + + + + Writes the beginning of a Json object. + + + + + Writes the end of a Json object. + + + + + Writes the beginning of a Json array. + + + + + Writes the end of an array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the end constructor. + + + + + Writes the property name of a name/value pair on a Json object. + + The name of the property. + + + + Writes the end of the current Json object or array. + + + + + Writes the current token. + + The to read the token from. + + + + Writes the specified end token. + + The end token to write. + + + + Writes indent characters. + + + + + Writes the JSON value delimiter. + + + + + Writes an indent space. + + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON without changing the writer's state. + + The raw JSON to write. + + + + Writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes out a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes out the given white space. + + The string of white space characters. + + + + Gets the top. + + The top. + + + + Gets the state of the writer. + + + + + Indicates how the output is formatted. + + + + + Initializes a new instance of the class writing to the given . + + The container being written to. + + + + Initializes a new instance of the class. + + + + + Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream. + + + + + Closes this stream and the underlying stream. + + + + + Writes the beginning of a Json object. + + + + + Writes the beginning of a Json array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the end. + + The token. + + + + Writes the property name of a name/value pair on a Json object. + + The name of the property. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes out a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Gets the token being writen. + + The token being writen. + + + + Initializes a new instance of the class. + + The stream. + + + + Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream. + + + + + Writes the end. + + The token. + + + + Writes out a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + + + + Specifies how constructors are used when initializing objects during deserialization by the . + + + + + First attempt to use the public default constructor then fall back to single paramatized constructor. + + + + + Allow Json.NET to use a non-public default constructor. + + + + + Converts a binary value to and from a base 64 string value. + + + + + Converts an object to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Create a custom object + + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Creates an object which will then be populated by the serializer. + + Type of the object. + + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Provides a base class for converting a to and from JSON. + + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an to and from its name string value. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Represents a view of a . + + + + + Initializes a new instance of the class. + + The name. + Type of the property. + + + + When overridden in a derived class, returns whether resetting an object changes its value. + + + true if resetting the component changes its value; otherwise, false. + + The component to test for reset capability. + + + + + When overridden in a derived class, gets the current value of the property on a component. + + + The value of a property for a given component. + + The component with the property for which to retrieve the value. + + + + + When overridden in a derived class, resets the value for this property of the component to the default value. + + The component with the property value that is to be reset to the default value. + + + + + When overridden in a derived class, sets the value of the component to a different value. + + The component with the property value that is to be set. + The new value. + + + + + When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted. + + + true if the property should be persisted; otherwise, false. + + The component with the property to be examined for persistence. + + + + + When overridden in a derived class, gets the type of the component this property is bound to. + + + A that represents the type of component this property is bound to. When the or methods are invoked, the object specified might be an instance of this type. + + + + + When overridden in a derived class, gets a value indicating whether this property is read-only. + + + true if the property is read-only; otherwise, false. + + + + + When overridden in a derived class, gets the type of the property. + + + A that represents the type of the property. + + + + + Gets the hash code for the name of the member. + + + + The hash code for the name of the member. + + + + + Represents a view of a . + + + + + Initializes a new instance of the class. + + The value. + + + + Returns the properties for this instance of a component. + + + A that represents the properties for this component instance. + + + + + Returns the properties for this instance of a component using the attribute array as a filter. + + An array of type that is used as a filter. + + A that represents the filtered properties for this component instance. + + + + + Returns a collection of custom attributes for this instance of a component. + + + An containing the attributes for this object. + + + + + Returns the class name of this instance of a component. + + + The class name of the object, or null if the class does not have a name. + + + + + Returns the name of this instance of a component. + + + The name of the object, or null if the object does not have a name. + + + + + Returns a type converter for this instance of a component. + + + A that is the converter for this object, or null if there is no for this object. + + + + + Returns the default event for this instance of a component. + + + An that represents the default event for this object, or null if this object does not have events. + + + + + Returns the default property for this instance of a component. + + + A that represents the default property for this object, or null if this object does not have properties. + + + + + Returns an editor of the specified type for this instance of a component. + + A that represents the editor for this object. + + An of the specified type that is the editor for this object, or null if the editor cannot be found. + + + + + Returns the events for this instance of a component using the specified attribute array as a filter. + + An array of type that is used as a filter. + + An that represents the filtered events for this component instance. + + + + + Returns the events for this instance of a component. + + + An that represents the events for this component instance. + + + + + Returns an object that contains the property described by the specified property descriptor. + + A that represents the property whose owner is to be found. + + An that represents the owner of the specified property. + + + + + Represents a raw JSON string. + + + + + Represents a value in JSON (string, integer, date, etc). + + + + + Represents an abstract JSON token. + + + + + Represents a collection of objects. + + The type of token + + + + Gets the with the specified key. + + + + + + Provides an interface to enable a class to return line and position information. + + + + + Gets a value indicating whether the class can return line information. + + + true if LineNumber and LinePosition can be provided; otherwise, false. + + + + + Gets the current line number. + + The current line number or 0 if no line information is available (for example, HasLineInfo returns false). + + + + Gets the current line position. + + The current line position or 0 if no line information is available (for example, HasLineInfo returns false). + + + + Compares the values of two tokens, including the values of all descendant tokens. + + The first to compare. + The second to compare. + true if the tokens are equal; otherwise false. + + + + Adds the specified content immediately after this token. + + A content object that contains simple content or a collection of content objects to be added after this token. + + + + Adds the specified content immediately before this token. + + A content object that contains simple content or a collection of content objects to be added before this token. + + + + Returns a collection of the ancestor tokens of this token. + + A collection of the ancestor tokens of this token. + + + + Returns a collection of the sibling tokens after this token, in document order. + + A collection of the sibling tokens after this tokens, in document order. + + + + Returns a collection of the sibling tokens before this token, in document order. + + A collection of the sibling tokens before this token, in document order. + + + + Gets the with the specified key converted to the specified type. + + The type to convert the token to. + The token key. + The converted token value. + + + + Returns a collection of the child tokens of this token, in document order. + + An of containing the child tokens of this , in document order. + + + + Returns a collection of the child tokens of this token, in document order, filtered by the specified type. + + The type to filter the child tokens on. + A containing the child tokens of this , in document order. + + + + Returns a collection of the child values of this token, in document order. + + The type to convert the values to. + A containing the child values of this , in document order. + + + + Removes this token from its parent. + + + + + Replaces this token with the specified token. + + The value. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Returns the indented JSON for this token. + + + The indented JSON for this token. + + + + + Returns the JSON for this token using the given formatting and converters. + + Indicates how the output is formatted. + A collection of which will be used when writing the token. + The JSON for this token using the given formatting and converters. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Creates an for this token. + + An that can be used to read this token and its descendants. + + + + Creates a from an object. + + The object that will be used to create . + A with the value of the specified object + + + + Creates a from an object using the specified . + + The object that will be used to create . + The that will be used when reading the object. + A with the value of the specified object + + + + Creates a from a . + + An positioned at the token to read into this . + + An that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Selects the token that matches the object path. + + + The object path from the current to the + to be returned. This must be a string of property names or array indexes separated + by periods, such as Tables[0].DefaultView[0].Price in C# or + Tables(0).DefaultView(0).Price in Visual Basic. + + The that matches the object path or a null reference if no matching token is found. + + + + Selects the token that matches the object path. + + + The object path from the current to the + to be returned. This must be a string of property names or array indexes separated + by periods, such as Tables[0].DefaultView[0].Price in C# or + Tables(0).DefaultView(0).Price in Visual Basic. + + A flag to indicate whether an error should be thrown if no token is found. + The that matches the object path. + + + + Gets a comparer that can compare two tokens for value equality. + + A that can compare two nodes for value equality. + + + + Gets or sets the parent. + + The parent. + + + + Gets the root of this . + + The root of this . + + + + Gets the node type for this . + + The type. + + + + Gets a value indicating whether this token has childen tokens. + + + true if this token has child values; otherwise, false. + + + + + Gets the next sibling token of this node. + + The that contains the next sibling token. + + + + Gets the previous sibling token of this node. + + The that contains the previous sibling token. + + + + Gets the with the specified key. + + The with the specified key. + + + + Get the first child token of this token. + + A containing the first child token of the . + + + + Get the last child token of this token. + + A containing the last child token of the . + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Creates a comment with the given value. + + The value. + A comment with the given value. + + + + Creates a string with the given value. + + The value. + A string with the given value. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Indicates whether the current object is equal to another object of the same type. + + + true if the current object is equal to the parameter; otherwise, false. + + An object to compare with this object. + + + + Determines whether the specified is equal to the current . + + The to compare with the current . + + true if the specified is equal to the current ; otherwise, false. + + + The parameter is null. + + + + + Serves as a hash function for a particular type. + + + A hash code for the current . + + + + + Gets a value indicating whether this token has childen tokens. + + + true if this token has child values; otherwise, false. + + + + + Gets the node type for this . + + The type. + + + + Gets or sets the underlying token value. + + The underlying token value. + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class. + + The raw json. + + + + Creates an instance of with the content of the reader's current token. + + The reader. + An instance of with the content of the reader's current token. + + + + Indicating whether a property is required. + + + + + The property is not required. The default state. + + + + + The property must be defined in JSON but can be a null value. + + + + + The property must be defined in JSON and cannot be a null value. + + + + + Used to resolve references when serializing and deserializing JSON by the . + + + + + Resolves a reference to its object. + + The reference to resolve. + The object that + + + + Gets the reference for the sepecified object. + + The object to get a reference for. + The reference to the object. + + + + Determines whether the specified object is referenced. + + The object to test for a reference. + + true if the specified object is referenced; otherwise, false. + + + + + Adds a reference to the specified object. + + The reference. + The object to reference. + + + + Specifies reference handling options for the . + + + + + Do not preserve references when serializing types. + + + + + Preserve references when serializing into a JSON object structure. + + + + + Preserve references when serializing into a JSON array structure. + + + + + Preserve references when serializing. + + + + + Instructs the how to serialize the collection. + + + + + Instructs the how to serialize the object. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Gets or sets the id. + + The id. + + + + Gets or sets the title. + + The title. + + + + Gets or sets the description. + + The description. + + + + Gets or sets a value that indicates whether to preserve object reference data. + + + true to keep object reference; otherwise, false. The default is false. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with a flag indicating whether the array can contain null items + + A flag indicating whether the array can contain null items. + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Gets or sets a value indicating whether null items are allowed in the collection. + + true if null items are allowed in the collection; otherwise, false. + + + + Specifies default value handling options for the . + + + + + Include null values when serializing and deserializing objects. + + + + + Ignore null values when serializing and deserializing objects. + + + + + Instructs the to use the specified when serializing the member or class. + + + + + Initializes a new instance of the class. + + Type of the converter. + + + + Gets the type of the converter. + + The type of the converter. + + + + Instructs the how to serialize the object. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified member serialization. + + The member serialization. + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Gets or sets the member serialization. + + The member serialization. + + + + Specifies the settings on a object. + + + + + Initializes a new instance of the class. + + + + + Gets or sets how reference loops (e.g. a class referencing itself) is handled. + + Reference loop handling. + + + + Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization. + + Missing member handling. + + + + Gets or sets how objects are created during deserialization. + + The object creation handling. + + + + Gets or sets how null values are handled during serialization and deserialization. + + Null value handling. + + + + Gets or sets how null default are handled during serialization and deserialization. + + The default value handling. + + + + Gets or sets a collection that will be used during serialization. + + The converters. + + + + Gets or sets how object references are preserved by the serializer. + + The preserve references handling. + + + + Gets or sets how type name writing and reading is handled by the serializer. + + The type name handling. + + + + Gets or sets how constructors are used during deserialization. + + The constructor handling. + + + + Gets or sets the contract resolver used by the serializer when + serializing .NET objects to JSON and vice versa. + + The contract resolver. + + + + Gets or sets the used by the serializer when resolving references. + + The reference resolver. + + + + Gets or sets the used by the serializer when resolving type names. + + The binder. + + + + Gets or sets the error handler called during serialization and deserialization. + + The error handler called during serialization and deserialization. + + + + Gets or sets the used by the serializer when invoking serialization callback methods. + + The context. + + + + Represents a reader that provides validation. + + + + + Initializes a new instance of the class that + validates the content returned from the given . + + The to read from while validating. + + + + Reads the next JSON token from the stream as a . + + + A or a null reference if the next JSON token is null. + + + + + Reads the next JSON token from the stream. + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Sets an event handler for receiving schema validation errors. + + + + + Gets the text value of the current Json token. + + + + + + Gets the depth of the current token in the JSON document. + + The depth of the current token in the JSON document. + + + + Gets the quotation mark character used to enclose the value of a string. + + + + + + Gets the type of the current Json token. + + + + + + Gets The Common Language Runtime (CLR) type for the current Json token. + + + + + + Gets or sets the schema. + + The schema. + + + + Gets the used to construct this . + + The specified in the constructor. + + + + Compares tokens to determine whether they are equal. + + + + + Determines whether the specified objects are equal. + + The first object of type to compare. + The second object of type to compare. + + true if the specified objects are equal; otherwise, false. + + + + + Returns a hash code for the specified object. + + The for which a hash code is to be returned. + A hash code for the specified object. + The type of is a reference type and is null. + + + + Specifies the member serialization options for the . + + + + + All members are serialized by default. Members can be excluded using the . + + + + + Only members must be marked with the are serialized. + + + + + Specifies how object creation is handled by the . + + + + + Reuse existing objects, create new objects when needed. + + + + + Only reuse existing objects. + + + + + Always create new objects. + + + + + Converts a to and from the ISO 8601 date format (e.g. 2008-04-12T12:53Z). + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Gets or sets the date time styles used when converting a date to and from JSON. + + The date time styles used when converting a date to and from JSON. + + + + Gets or sets the date time format used when converting a date to and from JSON. + + The date time format used when converting a date to and from JSON. + + + + Gets or sets the culture used when converting a date to and from JSON. + + The culture used when converting a date to and from JSON. + + + + Converts a to and from a JavaScript date constructor (e.g. new Date(52231943)). + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Specifies whether a DateTime object represents a local time, a Coordinated Universal Time (UTC), or is not specified as either local time or UTC. + + + + + The time represented is local time. + + + + + The time represented is UTC. + + + + + The time represented is not specified as either local time or Coordinated Universal Time (UTC). + + + + + Preserves the DateTimeKind field of a date when a DateTime object is converted to a string and the string is then converted back to a DateTime object. + + + + + Converts an to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The calling serializer. + The value. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Checks if the attributeName is a namespace attribute. + + Attribute name to test. + The attribute name prefix if it has one, otherwise an empty string. + True if attribute name is for a namespace attribute, otherwise false. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produces multiple root elements. + + The name of the deserialize root element. + + + + Converts a object to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The calling serializer. + The value. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The calling serializer. + The object value. + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized Json data. + + + + + Initializes a new instance of the class with the specified . + + The TextReader containing the XML data to read. + + + + Reads the next JSON token from the stream. + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Reads the next JSON token from the stream as a . + + + A or a null reference if the next JSON token is null. + + + + + Changes the state to closed. + + + + + Gets a value indicating whether the class can return line information. + + + true if LineNumber and LinePosition can be provided; otherwise, false. + + + + + Gets the current line number. + + + The current line number or 0 if no line information is available (for example, HasLineInfo returns false). + + + + + Gets the current line position. + + + The current line position or 0 if no line information is available (for example, HasLineInfo returns false). + + + + + Instructs the to always serialize the member with the specified name. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified name. + + Name of the property. + + + + Gets or sets the null value handling used when serializing this property. + + The null value handling. + + + + Gets or sets the default value handling used when serializing this property. + + The default value handling. + + + + Gets or sets the reference loop handling used when serializing this property. + + The reference loop handling. + + + + Gets or sets the object creation handling used when deserializing this property. + + The object creation handling. + + + + Gets or sets whether this property's value is serialized as a reference. + + Whether this property's value is serialized as a reference. + + + + Gets or sets the name of the property. + + The name of the property. + + + + Gets or sets a value indicating whether this property is required. + + + A value indicating whether this property is required. + + + + + Instructs the not to serialize the public field or public read/write property value. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating Json data. + + + + + Creates an instance of the JsonWriter class using the specified . + + The TextWriter to write to. + + + + Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream. + + + + + Closes this stream and the underlying stream. + + + + + Writes the beginning of a Json object. + + + + + Writes the beginning of a Json array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the specified end token. + + The end token to write. + + + + Writes the property name of a name/value pair on a Json object. + + The name of the property. + + + + Writes indent characters. + + + + + Writes the JSON value delimiter. + + + + + Writes an indent space. + + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes out a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes out the given white space. + + The string of white space characters. + + + + Gets or sets how many IndentChars to write for each level in the hierarchy when is set to Formatting.Indented. + + + + + Gets or sets which character to use to quote attribute values. + + + + + Gets or sets which character to use for indenting when is set to Formatting.Indented. + + + + + Gets or sets a value indicating whether object names will be surrounded with quotes. + + + + + The exception thrown when an error occurs while reading Json text. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + + + + The exception thrown when an error occurs while reading Json text. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Represents a collection of . + + + + + Provides methods for converting between common language runtime types and JSON types. + + + + + Represents JavaScript's boolean value true as a string. This field is read-only. + + + + + Represents JavaScript's boolean value false as a string. This field is read-only. + + + + + Represents JavaScript's null as a string. This field is read-only. + + + + + Represents JavaScript's undefined as a string. This field is read-only. + + + + + Represents JavaScript's positive infinity as a string. This field is read-only. + + + + + Represents JavaScript's negative infinity as a string. This field is read-only. + + + + + Represents JavaScript's NaN as a string. This field is read-only. + + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + The string delimiter character. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Serializes the specified object to a JSON string. + + The object to serialize. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string. + + The object to serialize. + Indicates how the output is formatted. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a collection of . + + The object to serialize. + A collection converters used while serializing. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using a collection of . + + The object to serialize. + Indicates how the output is formatted. + A collection converters used while serializing. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using a collection of . + + The object to serialize. + Indicates how the output is formatted. + The used to serialize the object. + If this is null, default serialization settings will be is used. + + A JSON string representation of the object. + + + + + Deserializes the specified object to a Json object. + + The object to deserialize. + The deserialized object from the Json string. + + + + Deserializes the specified object to a Json object. + + The object to deserialize. + The of object being deserialized. + The deserialized object from the Json string. + + + + Deserializes the specified object to a Json object. + + The type of the object to deserialize. + The object to deserialize. + The deserialized object from the Json string. + + + + Deserializes the specified JSON to the given anonymous type. + + + The anonymous type to deserialize to. This can't be specified + traditionally and must be infered from the anonymous type passed + as a parameter. + + The object to deserialize. + The anonymous type object. + The deserialized anonymous type from the JSON string. + + + + Deserializes the JSON string to the specified type. + + The type of the object to deserialize. + The object to deserialize. + Converters to use while deserializing. + The deserialized object from the JSON string. + + + + Deserializes the JSON string to the specified type. + + The type of the object to deserialize. + The object to deserialize. + + The used to deserialize the object. + If this is null, default serialization settings will be is used. + + The deserialized object from the JSON string. + + + + Deserializes the JSON string to the specified type. + + The object to deserialize. + The type of the object to deserialize. + Converters to use while deserializing. + The deserialized object from the JSON string. + + + + Deserializes the JSON string to the specified type. + + The JSON to deserialize. + The type of the object to deserialize. + + The used to deserialize the object. + If this is null, default serialization settings will be is used. + + The deserialized object from the JSON string. + + + + Populates the object with values from the JSON string. + + The JSON to populate values from. + The target object to populate values onto. + + + + Populates the object with values from the JSON string. + + The JSON to populate values from. + The target object to populate values onto. + + The used to deserialize the object. + If this is null, default serialization settings will be is used. + + + + + Serializes the XML node to a JSON string. + + The node to serialize. + A JSON string of the XmlNode. + + + + Deserializes the XmlNode from a JSON string. + + The JSON string. + The deserialized XmlNode + + + + Deserializes the XmlNode from a JSON string nested in a root elment. + + The JSON string. + The name of the root element to append when deserializing. + The deserialized XmlNode + + + + The exception thrown when an error occurs during Json serialization or deserialization. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + + + + Serializes and deserializes objects into and from the JSON format. + The enables you to control how objects are encoded into JSON. + + + + + Initializes a new instance of the class. + + + + + Creates a new instance using the specified . + + The settings to be applied to the . + A new instance using the specified . + + + + Populates the JSON values onto the target object. + + The that contains the JSON structure to reader values from. + The target object to populate values onto. + + + + Populates the JSON values onto the target object. + + The that contains the JSON structure to reader values from. + The target object to populate values onto. + + + + Deserializes the Json structure contained by the specified . + + The that contains the JSON structure to deserialize. + The being deserialized. + + + + Deserializes the Json structure contained by the specified + into an instance of the specified type. + + The containing the object. + The of object being deserialized. + The instance of being deserialized. + + + + Deserializes the Json structure contained by the specified + into an instance of the specified type. + + The containing the object. + The type of the object to deserialize. + The instance of being deserialized. + + + + Deserializes the Json structure contained by the specified + into an instance of the specified type. + + The containing the object. + The of object being deserialized. + The instance of being deserialized. + + + + Serializes the specified and writes the Json structure + to a Stream using the specified . + + The used to write the Json structure. + The to serialize. + + + + Serializes the specified and writes the Json structure + to a Stream using the specified . + + The used to write the Json structure. + The to serialize. + + + + Occurs when the errors during serialization and deserialization. + + + + + Gets or sets the used by the serializer when resolving references. + + + + + Gets or sets the used by the serializer when resolving type names. + + + + + Gets or sets how type name writing and reading is handled by the serializer. + + + + + Gets or sets how object references are preserved by the serializer. + + + + + Get or set how reference loops (e.g. a class referencing itself) is handled. + + + + + Get or set how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization. + + + + + Get or set how null values are handled during serialization and deserialization. + + + + + Get or set how null default are handled during serialization and deserialization. + + + + + Gets or sets how objects are created during deserialization. + + The object creation handling. + + + + Gets or sets how constructors are used during deserialization. + + The constructor handling. + + + + Gets a collection that will be used during serialization. + + Collection that will be used during serialization. + + + + Gets or sets the contract resolver used by the serializer when + serializing .NET objects to JSON and vice versa. + + + + + Gets or sets the used by the serializer when invoking serialization callback methods. + + The context. + + + + Contains the LINQ to JSON extension methods. + + + + + Returns a collection of tokens that contains the ancestors of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains the ancestors of every node in the source collection. + + + + Returns a collection of tokens that contains the descendants of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains the descendants of every node in the source collection. + + + + Returns a collection of child properties of every object in the source collection. + + An of that contains the source collection. + An of that contains the properties of every object in the source collection. + + + + Returns a collection of child values of every object in the source collection with the given key. + + An of that contains the source collection. + The token key. + An of that contains the values of every node in the source collection with the given key. + + + + Returns a collection of child values of every object in the source collection. + + An of that contains the source collection. + An of that contains the values of every node in the source collection. + + + + Returns a collection of converted child values of every object in the source collection with the given key. + + The type to convert the values to. + An of that contains the source collection. + The token key. + An that contains the converted values of every node in the source collection with the given key. + + + + Returns a collection of converted child values of every object in the source collection. + + The type to convert the values to. + An of that contains the source collection. + An that contains the converted values of every node in the source collection. + + + + Converts the value. + + The type to convert the value to. + A cast as a of . + A converted value. + + + + Converts the value. + + The source collection type. + The type to convert the value to. + A cast as a of . + A converted value. + + + + Returns a collection of child tokens of every array in the source collection. + + The source collection type. + An of that contains the source collection. + An of that contains the values of every node in the source collection. + + + + Returns a collection of converted child tokens of every array in the source collection. + + An of that contains the source collection. + The type to convert the values to. + The source collection type. + An that contains the converted values of every node in the source collection. + + + + Returns the input typed as . + + An of that contains the source collection. + The input typed as . + + + + Returns the input typed as . + + The source collection type. + An of that contains the source collection. + The input typed as . + + + + Represents a JSON constructor. + + + + + Represents a token that can contain other tokens. + + + + + Raises the event. + + The instance containing the event data. + + + + Raises the event. + + The instance containing the event data. + + + + Returns a collection of the child tokens of this token, in document order. + + + An of containing the child tokens of this , in document order. + + + + + Returns a collection of the child values of this token, in document order. + + The type to convert the values to. + + A containing the child values of this , in document order. + + + + + Returns a collection of the descendant tokens for this token in document order. + + An containing the descendant tokens of the . + + + + Adds the specified content as children of this . + + The content to be added. + + + + Adds the specified content as the first children of this . + + The content to be added. + + + + Creates an that can be used to add tokens to the . + + An that is ready to have content written to it. + + + + Replaces the children nodes of this token with the specified content. + + The content. + + + + Removes the child nodes from this token. + + + + + Occurs when the list changes or an item in the list changes. + + + + + Occurs before an item is added to the collection. + + + + + Gets a value indicating whether this token has childen tokens. + + + true if this token has child values; otherwise, false. + + + + + Get the first child token of this token. + + + A containing the first child token of the . + + + + + Get the last child token of this token. + + + A containing the last child token of the . + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified name and content. + + The constructor name. + The contents of the constructor. + + + + Initializes a new instance of the class with the specified name and content. + + The constructor name. + The contents of the constructor. + + + + Initializes a new instance of the class with the specified name. + + The constructor name. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Gets or sets the name of this constructor. + + The constructor name. + + + + Gets the node type for this . + + The type. + + + + Gets the with the specified key. + + The with the specified key. + + + + Represents a collection of objects. + + The type of token + + + + An empty collection of objects. + + + + + Initializes a new instance of the struct. + + The enumerable. + + + + Returns an enumerator that iterates through the collection. + + + A that can be used to iterate through the collection. + + + + + Returns an enumerator that iterates through a collection. + + + An object that can be used to iterate through the collection. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Gets the with the specified key. + + + + + + Represents a JSON object. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified content. + + The contents of the object. + + + + Initializes a new instance of the class with the specified content. + + The contents of the object. + + + + Gets an of this object's properties. + + An of this object's properties. + + + + Gets a the specified name. + + The property name. + A with the specified name or null. + + + + Gets an of this object's property values. + + An of this object's property values. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + Creates a from an object. + + The object that will be used to create . + A with the values of the specified object + + + + Creates a from an object. + + The object that will be used to create . + The that will be used to read the object. + A with the values of the specified object + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Adds the specified property name. + + Name of the property. + The value. + + + + Removes the property with the specified name. + + Name of the property. + true if item was successfully removed; otherwise, false. + + + + Tries the get value. + + Name of the property. + The value. + true if a value was successfully retrieved; otherwise, false. + + + + Returns an enumerator that iterates through the collection. + + + A that can be used to iterate through the collection. + + + + + Raises the event with the provided arguments. + + Name of the property. + + + + Occurs when a property value changes. + + + + + Gets the node type for this . + + The type. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets or sets the with the specified property name. + + + + + + Gets the number of elements contained in the . + + + The number of elements contained in the . + + + + Represents a JSON array. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified content. + + The contents of the array. + + + + Initializes a new instance of the class with the specified content. + + The contents of the array. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + Creates a from an object. + + The object that will be used to create . + A with the values of the specified object + + + + Creates a from an object. + + The object that will be used to create . + The that will be used to read the object. + A with the values of the specified object + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Determines the index of a specific item in the . + + The object to locate in the . + + The index of if found in the list; otherwise, -1. + + + + + Inserts an item to the at the specified index. + + The zero-based index at which should be inserted. + The object to insert into the . + + is not a valid index in the . + The is read-only. + + + + Removes the item at the specified index. + + The zero-based index of the item to remove. + + is not a valid index in the . + The is read-only. + + + + Adds an item to the . + + The object to add to the . + The is read-only. + + + + Removes all items from the . + + The is read-only. + + + + Determines whether the contains a specific value. + + The object to locate in the . + + true if is found in the ; otherwise, false. + + + + + Removes the first occurrence of a specific object from the . + + The object to remove from the . + + true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . + + The is read-only. + + + + Gets the node type for this . + + The type. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets or sets the at the specified index. + + + + + + Gets the number of elements contained in the . + + + The number of elements contained in the . + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized Json data. + + + + + Initializes a new instance of the class. + + The token to read from. + + + + Reads the next JSON token from the stream as a . + + + A or a null reference if the next JSON token is null. + + + + + Reads the next JSON token from the stream. + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Represents a JSON property. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Returns a collection of the child tokens of this token, in document order. + + + An of containing the child tokens of this , in document order. + + + + + Initializes a new instance of the class. + + The property name. + The property content. + + + + Initializes a new instance of the class. + + The property name. + The property content. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Gets the property name. + + The property name. + + + + Gets or sets the property value. + + The property value. + + + + Gets the node type for this . + + The type. + + + + Specifies the type of token. + + + + + No token type has been set. + + + + + A JSON object. + + + + + A JSON array. + + + + + A JSON constructor. + + + + + A JSON object property. + + + + + A comment. + + + + + An integer value. + + + + + A float value. + + + + + A string value. + + + + + A boolean value. + + + + + A null value. + + + + + An undefined value. + + + + + A date value. + + + + + A raw JSON value. + + + + + A collection of bytes value. + + + + + Contains the JSON schema extension methods. + + + + + Determines whether the is valid. + + The source to test. + The schema to test with. + + true if the specified is valid; otherwise, false. + + + + + Validates the specified . + + The source to test. + The schema to test with. + + + + Validates the specified . + + The source to test. + The schema to test with. + The validation event handler. + + + + Returns detailed information about the schema exception. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Resolves from an id. + + + + + Initializes a new instance of the class. + + + + + Gets a for the specified id. + + The id. + A for the specified id. + + + + Gets or sets the loaded schemas. + + The loaded schemas. + + + + Specifies undefined schema Id handling options for the . + + + + + Do not infer a schema Id. + + + + + Use the .NET type name as the schema Id. + + + + + Use the assembly qualified .NET type name as the schema Id. + + + + + Returns detailed information related to the . + + + + + Gets the associated with the validation event. + + The JsonSchemaException associated with the validation event. + + + + Gets the text description corresponding to the validation event. + + The text description. + + + + Represents the callback method that will handle JSON schema validation events and the . + + + + + Resolves member mappings for a type, camel casing property names. + + + + + Used by to resolves a for a given . + + + + + Used by to resolves a for a given . + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Initializes a new instance of the class. + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Gets the serializable members for the type. + + The type to get serializable members for. + The serializable members for the type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Resolves the default for the contract. + + Type of the object. + + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates properties for the given . + + The contract to create properties for. + Properties for the given . + + + + Creates the used by the serializer to get and set values from a member. + + The member. + The used by the serializer to get and set values from a member. + + + + Creates a for the given . + + The member's declaring types . + The member to create a for. + A created for the given . + + + + Resolves the name of the property. + + Name of the property. + Name of the property. + + + + Gets or sets the default members search flags. + + The default members search flags. + + + + Resolves the name of the property. + + Name of the property. + The property name camel cased. + + + + The default serialization binder used when resolving and loading classes from type names. + + + + + When overridden in a derived class, controls the binding of a serialized object to a type. + + Specifies the name of the serialized object. + Specifies the name of the serialized object. + + The type of the object the formatter creates a new instance of. + + + + + Get and set values for a using dynamic methods. + + + + + Provides methods to get and set values. + + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + Initializes a new instance of the class. + + The member info. + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + Provides information surrounding an error. + + + + + Gets or sets the error. + + The error. + + + + Gets the original object that caused the error. + + The original object that caused the error. + + + + Gets the member that caused the error. + + The member that caused the error. + + + + Gets or sets a value indicating whether this is handled. + + true if handled; otherwise, false. + + + + Provides data for the Error event. + + + + + Initializes a new instance of the class. + + The current object. + The error context. + + + + Gets the current object the error event is being raised against. + + The current object the error event is being raised against. + + + + Gets the error context. + + The error context. + + + + Contract details for a used by the . + + + + + Contract details for a used by the . + + + + + Gets the underlying type for the contract. + + The underlying type for the contract. + + + + Gets or sets the type created during deserialization. + + The type created during deserialization. + + + + Gets or sets whether this type contract is serialized as a reference. + + Whether this type contract is serialized as a reference. + + + + Gets or sets the default for this contract. + + The converter. + + + + Gets or sets the method called immediately after deserialization of the object. + + The method called immediately after deserialization of the object. + + + + Gets or sets the method called during deserialization of the object. + + The method called during deserialization of the object. + + + + Gets or sets the method called after serialization of the object graph. + + The method called after serialization of the object graph. + + + + Gets or sets the method called before serialization of the object. + + The method called before serialization of the object. + + + + Gets or sets the default creator. + + The default creator. + + + + Gets or sets a value indicating whether [default creator non public]. + + true if the default object creator is non-public; otherwise, false. + + + + Gets or sets the method called when an error is thrown during the serialization of the object. + + The method called when an error is thrown during the serialization of the object. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Maps a JSON property to a .NET member. + + + + + Gets the name of the property. + + The name of the property. + + + + Gets the that will get and set the during serialization. + + The that will get and set the during serialization. + + + + Gets or sets the type of the property. + + The type of the property. + + + + Gets or sets the for the property. + If set this converter takes presidence over the contract converter for the property type. + + The converter. + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is readable. + + true if readable; otherwise, false. + + + + Gets a value indicating whether this is writable. + + true if writable; otherwise, false. + + + + Gets the member converter. + + The member converter. + + + + Gets the default value. + + The default value. + + + + Gets a value indicating whether this is required. + + A value indicating whether this is required. + + + + Gets a value indicating whether this property preserves object references. + + + true if this instance is reference; otherwise, false. + + + + + Gets the property null value handling. + + The null value handling. + + + + Gets the property default value handling. + + The default value handling. + + + + Gets the property reference loop handling. + + The reference loop handling. + + + + Gets the property object creation handling. + + The object creation handling. + + + + A collection of objects. + + + + + Initializes a new instance of the class. + + The contract. + + + + When implemented in a derived class, extracts the key from the specified element. + + The element from which to extract the key. + The key for the specified element. + + + + Adds a object. + + The property to add to the collection. + + + + Gets the closest matching object. + First attempts to get an exact case match of propertyName and then + a case insensitive match. + + Name of the property. + A matching property if found. + + + + Gets a property by property name. + + The name of the property to get. + Type property name string comparison. + A matching property if found. + + + + Specifies missing member handling options for the . + + + + + Ignore a missing member and do not attempt to deserialize it. + + + + + Throw a when a missing member is encountered during deserialization. + + + + + Specifies null value handling options for the . + + + + + Include null values when serializing and deserializing objects. + + + + + Ignore null values when serializing and deserializing objects. + + + + + Specifies reference loop handling options for the . + + + + + Throw a when a loop is encountered. + + + + + Ignore loop references and do not serialize. + + + + + Serialize loop references. + + + + + An in-memory representation of a JSON Schema. + + + + + Initializes a new instance of the class. + + + + + Reads a from the specified . + + The containing the JSON Schema to read. + The object representing the JSON Schema. + + + + Reads a from the specified . + + The containing the JSON Schema to read. + The to use when resolving schema references. + The object representing the JSON Schema. + + + + Load a from a string that contains schema JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + Parses the specified json. + + The json. + The resolver. + A populated from the string that contains JSON. + + + + Writes this schema to a . + + A into which this method will write. + + + + Writes this schema to a using the specified . + + A into which this method will write. + The resolver used. + + + + Returns a that represents the current . + + + A that represents the current . + + + + + Gets or sets the id. + + + + + Gets or sets the title. + + + + + Gets or sets whether the object is optional. + + + + + Gets or sets whether the object is read only. + + + + + Gets or sets whether the object is visible to users. + + + + + Gets or sets whether the object is transient. + + + + + Gets or sets the description of the object. + + + + + Gets or sets the types of values allowed by the object. + + The type. + + + + Gets or sets the pattern. + + The pattern. + + + + Gets or sets the minimum length. + + The minimum length. + + + + Gets or sets the maximum length. + + The maximum length. + + + + Gets or sets the maximum decimals. + + The maximum decimals. + + + + Gets or sets the minimum. + + The minimum. + + + + Gets or sets the maximum. + + The maximum. + + + + Gets or sets the minimum number of items. + + The minimum number of items. + + + + Gets or sets the maximum number of items. + + The maximum number of items. + + + + Gets or sets the of items. + + The of items. + + + + Gets or sets the of properties. + + The of properties. + + + + Gets or sets the of additional properties. + + The of additional properties. + + + + Gets or sets a value indicating whether additional properties are allowed. + + + true if additional properties are allowed; otherwise, false. + + + + + Gets or sets the required property if this property is present. + + The required property if this property is present. + + + + Gets or sets the identity. + + The identity. + + + + Gets or sets the a collection of valid enum values allowed. + + A collection of valid enum values allowed. + + + + Gets or sets a collection of options. + + A collection of options. + + + + Gets or sets disallowed types. + + The disallow types. + + + + Gets or sets the default value. + + The default value. + + + + Gets or sets the extend . + + The extended . + + + + Gets or sets the format. + + The format. + + + + Generates a from a specified . + + + + + Generate a from the specified type. + + The type to generate a from. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + The used to resolve schema references. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + Specify whether the generated root will be nullable. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + The used to resolve schema references. + Specify whether the generated root will be nullable. + A generated from the specified type. + + + + Gets or sets how undefined schemas are handled by the serializer. + + + + + Gets or sets the contract resolver. + + The contract resolver. + + + + The value types allowed by the . + + + + + No type specified. + + + + + String type. + + + + + Float type. + + + + + Integer type. + + + + + Boolean type. + + + + + Object type. + + + + + Array type. + + + + + Null type. + + + + + Any type. + + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Gets or sets the object member serialization. + + The member object serialization. + + + + Gets the object's properties. + + The object's properties. + + + + Gets or sets the parametrized constructor used to create the object. + + The parametrized constructor. + + + + When applied to a method, specifies that the method is called when an error occurs serializing an object. + + + + + Get and set values for a using reflection. + + + + + Initializes a new instance of the class. + + The member info. + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + Specifies type name handling options for the . + + + + + Do not include the .NET type name when serializing types. + + + + + Include the .NET type name when serializing into a JSON object structure. + + + + + Include the .NET type name when serializing into a JSON array structure. + + + + + Always include the .NET type name when serializing. + + + + + Converts the value to the specified type. + + The type to convert the value to. + The value to convert. + The converted type. + + + + Converts the value to the specified type. + + The type to convert the value to. + The value to convert. + The culture to use when converting. + The converted type. + + + + Converts the value to the specified type. + + The value to convert. + The culture to use when converting. + The type to convert the value to. + The converted type. + + + + Converts the value to the specified type. + + The type to convert the value to. + The value to convert. + The converted value if the conversion was successful or the default value of T if it failed. + + true if initialValue was converted successfully; otherwise, false. + + + + + Converts the value to the specified type. + + The type to convert the value to. + The value to convert. + The culture to use when converting. + The converted value if the conversion was successful or the default value of T if it failed. + + true if initialValue was converted successfully; otherwise, false. + + + + + Converts the value to the specified type. + + The value to convert. + The culture to use when converting. + The type to convert the value to. + The converted value if the conversion was successful or the default value of T if it failed. + + true if initialValue was converted successfully; otherwise, false. + + + + + Converts the value to the specified type. If the value is unable to be converted, the + value is checked whether it assignable to the specified type. + + The type to convert or cast the value to. + The value to convert. + The converted type. If conversion was unsuccessful, the initial value is returned if assignable to the target type + + + + Converts the value to the specified type. If the value is unable to be converted, the + value is checked whether it assignable to the specified type. + + The type to convert or cast the value to. + The value to convert. + The culture to use when converting. + The converted type. If conversion was unsuccessful, the initial value is returned if assignable to the target type + + + + Converts the value to the specified type. If the value is unable to be converted, the + value is checked whether it assignable to the specified type. + + The value to convert. + The culture to use when converting. + The type to convert or cast the value to. + + The converted type. If conversion was unsuccessful, the initial value + is returned if assignable to the target type. + + + + + Converts the value to the specified type. If the value is unable to be converted, the + value is checked whether it assignable to the specified type. + + The type to convert the value to. + The value to convert. + The converted value if the conversion was successful or the default value of T if it failed. + + true if initialValue was converted successfully or is assignable; otherwise, false. + + + + + Converts the value to the specified type. If the value is unable to be converted, the + value is checked whether it assignable to the specified type. + + The type to convert the value to. + The value to convert. + The culture to use when converting. + The converted value if the conversion was successful or the default value of T if it failed. + + true if initialValue was converted successfully or is assignable; otherwise, false. + + + + + Converts the value to the specified type. If the value is unable to be converted, the + value is checked whether it assignable to the specified type. + + The value to convert. + The culture to use when converting. + The type to convert the value to. + The converted value if the conversion was successful or the default value of T if it failed. + + true if initialValue was converted successfully or is assignable; otherwise, false. + + + + + Parses the specified enum member name, returning it's value. + + Name of the enum member. + + + + + Parses the specified enum member name, returning it's value. + + Name of the enum member. + If set to true ignore case. + + + + + Gets a dictionary of the names and values of an Enum type. + + + + + + Gets a dictionary of the names and values of an Enum type. + + + + + + Gets a dictionary of the names and values of an Enum type. + + The enum type to get names and values for. + + + + + Gets the maximum valid value of an Enum type. Flags enums are ORed. + + The type of the returned value. Must be assignable from the enum's underlying value type. + The enum type to get the maximum value for. + + + + + Specifies the type of Json token. + + + + + This is returned by the if a method has not been called. + + + + + An object start token. + + + + + An array start token. + + + + + A constructor start token. + + + + + An object property name. + + + + + A comment. + + + + + Raw JSON. + + + + + An interger. + + + + + A float. + + + + + A string. + + + + + A boolean. + + + + + A null token. + + + + + An undefined token. + + + + + An object end token. + + + + + An array end token. + + + + + A constructor end token. + + + + + A Date. + + + + + Byte data. + + + + + Specifies the state of the . + + + + + An exception has been thrown, which has left the in an invalid state. + You may call the method to put the in the Closed state. + Any other method calls results in an being thrown. + + + + + The method has been called. + + + + + An object is being written. + + + + + A array is being written. + + + + + A constructor is being written. + + + + + A property is being written. + + + + + A write method has not been called. + + + + + Specifies formatting options for the . + + + + + No special formatting is applied. This is the default. + + + + + Causes child objects to be indented according to the and settings. + + + + + Builds a string. Unlike StringBuilder this class lets you reuse it's internal buffer. + + + + + Determines whether the collection is null or empty. + + The collection. + + true if the collection is null or empty; otherwise, false. + + + + + Determines whether the collection is null or empty. + + The collection. + + true if the collection is null or empty; otherwise, false. + + + + + Determines whether the collection is null, empty or its contents are uninitialized values. + + The list. + + true if the collection is null or empty or its contents are uninitialized values; otherwise, false. + + + + + Makes a slice of the specified list in between the start and end indexes. + + The list. + The start index. + The end index. + A slice of the list. + + + + Makes a slice of the specified list in between the start and end indexes, + getting every so many items based upon the step. + + The list. + The start index. + The end index. + The step. + A slice of the list. + + + + Group the collection using a function which returns the key. + + The source collection to group. + The key selector. + A Dictionary with each key relating to a list of objects in a list grouped under it. + + + + Adds the elements of the specified collection to the specified generic IList. + + The list to add to. + The collection of elements to add. + + + + Gets the type of the typed collection's items. + + The type. + The type of the typed collection's items. + + + + Tests whether the list's items are their unitialized value. + + The list. + Whether the list's items are their unitialized value + + + + Gets the member's underlying type. + + The member. + The underlying type of the member. + + + + Determines whether the member is an indexed property. + + The member. + + true if the member is an indexed property; otherwise, false. + + + + + Determines whether the property is an indexed property. + + The property. + + true if the property is an indexed property; otherwise, false. + + + + + Gets the member's value on the object. + + The member. + The target object. + The member's value on the object. + + + + Sets the member's value on the target object. + + The member. + The target. + The value. + + + + Determines whether the specified MemberInfo can be read. + + The MemberInfo to determine whether can be read. + + true if the specified MemberInfo can be read; otherwise, false. + + + + + Determines whether the specified MemberInfo can be set. + + The MemberInfo to determine whether can be set. + + true if the specified MemberInfo can be set; otherwise, false. + + + + + Determines whether the string contains white space. + + The string to test for white space. + + true if the string contains white space; otherwise, false. + + + + + Determines whether the string is all white space. Empty string will return false. + + The string to test whether it is all white space. + + true if the string is all white space; otherwise, false. + + + + + Ensures the target string ends with the specified string. + + The target. + The value. + The target string with the value string at the end. + + + + Perform an action if the string is not null or empty. + + The value. + The action to perform. + + + + Indents the specified string. + + The string to indent. + The number of characters to indent by. + + + + + Indents the specified string. + + The string to indent. + The number of characters to indent by. + The indent character. + + + + + Numbers the lines. + + The string to number. + + + + + Nulls an empty string. + + The string. + Null if the string was null, otherwise the string unchanged. + + + diff --git a/bin/Newtonsoft.Json.dll b/bin/Newtonsoft.Json.dll index 3b14448..177d9b5 100644 Binary files a/bin/Newtonsoft.Json.dll and b/bin/Newtonsoft.Json.dll differ diff --git a/bin/Newtonsoft.Json.pdb b/bin/Newtonsoft.Json.pdb index a8b8b8f..892546a 100644 Binary files a/bin/Newtonsoft.Json.pdb and b/bin/Newtonsoft.Json.pdb differ -- cgit v1.1 From 5fc990d9e78498afe8221a97fdd1f0dd5e7e314f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Mar 2010 20:33:46 +0000 Subject: put out full exception stack if something reaches top of base http server OnRequest() on both mono and .net replace Newtonsoft.Json.XML since the updated copy got accidentally reverted by another commit --- OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 214f936..7c9e51e 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -311,7 +311,7 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (Exception e) { - m_log.ErrorFormat("[BASE HTTP SERVER]: OnRequest() failed with {0} {1}", e.Message, e.StackTrace); + m_log.Error(string.Format("[BASE HTTP SERVER]: OnRequest() failed with "), e); } } -- cgit v1.1 From fa8def5e709a5136722ca1ffa0e7b46aacaab8c5 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 25 Mar 2010 21:36:57 +0000 Subject: minor: Print out port that http servers are using do this in callers so that we know who is setting up these things --- OpenSim/Framework/MainServer.cs | 8 +++++++- OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | 2 -- OpenSim/Region/ClientStack/RegionApplicationBase.cs | 6 +++--- OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs | 12 ++++++------ OpenSim/Server/Base/HttpServerBase.cs | 3 +++ 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/OpenSim/Framework/MainServer.cs b/OpenSim/Framework/MainServer.cs index 84cc05e..1f5f208 100644 --- a/OpenSim/Framework/MainServer.cs +++ b/OpenSim/Framework/MainServer.cs @@ -25,13 +25,17 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using OpenSim.Framework.Servers.HttpServer; using System.Collections.Generic; +using System.Reflection; +using log4net; +using OpenSim.Framework.Servers.HttpServer; namespace OpenSim.Framework { public class MainServer { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static BaseHttpServer instance = null; private static Dictionary m_Servers = new Dictionary(); @@ -53,6 +57,8 @@ namespace OpenSim.Framework return m_Servers[port]; m_Servers[port] = new BaseHttpServer(port); + + m_log.InfoFormat("[MAIN HTTP SERVER]: Starting main http server on port {0}", port); m_Servers[port].Start(); return m_Servers[port]; diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 7c9e51e..297d047 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -1572,7 +1572,6 @@ namespace OpenSim.Framework.Servers.HttpServer public void Start() { - m_log.Info("[BASE HTTP SERVER]: Starting up HTTP Server"); StartHTTP(); } @@ -1580,7 +1579,6 @@ namespace OpenSim.Framework.Servers.HttpServer { try { - m_log.Debug("[BASE HTTP SERVER]: Spawned main thread OK"); //m_httpListener = new HttpListener(); NotSocketErrors = 0; if (!m_ssl) diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index c7aeca14..e57e298 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -105,10 +105,10 @@ namespace OpenSim.Region.ClientStack if (m_networkServersInfo.HttpUsesSSL && (m_networkServersInfo.HttpListenerPort == m_networkServersInfo.httpSSLPort)) { - m_log.Error("[HTTP]: HTTP Server config failed. HTTP Server and HTTPS server must be on different ports"); + m_log.Error("[REGION SERVER]: HTTP Server config failed. HTTP Server and HTTPS server must be on different ports"); } - m_log.Info("[REGION]: Starting HTTP server"); + m_log.InfoFormat("[REGION SERVER]: Starting HTTP server on port {0}", m_httpServerPort); m_httpServer.Start(); base.StartupSpecific(); @@ -134,4 +134,4 @@ namespace OpenSim.Region.ClientStack return physicsPluginManager.GetPhysicsScene(engine, meshEngine, config, osSceneIdentifier); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs index 27b64bf..40ffcb4 100644 --- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs @@ -131,8 +131,8 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC { // Start http server // Attach xmlrpc handlers - m_log.Info("[REMOTE_DATA]: " + - "Starting XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); + m_log.Info("[XML RPC MODULE]: " + + "Starting up XMLRPC Server on port " + m_remoteDataPort + " for llRemoteData commands."); BaseHttpServer httpServer = new BaseHttpServer((uint) m_remoteDataPort); httpServer.AddXmlRPCHandler("llRemoteData", XmlRpcRemoteData); httpServer.Start(); @@ -192,7 +192,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC // This should no longer happen, but the check is reasonable anyway if (null == m_openChannels) { - m_log.Warn("[RemoteDataReply] Attempt to open channel before initialization is complete"); + m_log.Warn("[XML RPC MODULE]: Attempt to open channel before initialization is complete"); return newChannel; } @@ -279,7 +279,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC } else { - m_log.Warn("[RemoteDataReply]: Channel or message_id not found"); + m_log.Warn("[XML RPC MODULE]: Channel or message_id not found"); } } @@ -340,7 +340,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC } else { - m_log.Error("UNABLE TO REMOVE COMPLETED REQUEST"); + m_log.Error("[XML RPC MODULE]: UNABLE TO REMOVE COMPLETED REQUEST"); } } } @@ -728,4 +728,4 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC return ReqID; } } -} +} \ No newline at end of file diff --git a/OpenSim/Server/Base/HttpServerBase.cs b/OpenSim/Server/Base/HttpServerBase.cs index 77184a4..9e4593e 100644 --- a/OpenSim/Server/Base/HttpServerBase.cs +++ b/OpenSim/Server/Base/HttpServerBase.cs @@ -71,6 +71,8 @@ namespace OpenSim.Server.Base return m_Servers[port]; m_Servers[port] = new BaseHttpServer(port); + + m_Log.InfoFormat("[SERVER]: Starting new HTTP server on port {0}", port); m_Servers[port].Start(); return m_Servers[port]; @@ -109,6 +111,7 @@ namespace OpenSim.Server.Base protected override void Initialise() { + m_Log.InfoFormat("[SERVER]: Starting HTTP server on port {0}", m_HttpServer.Port); m_HttpServer.Start(); if (MainConsole.Instance is RemoteConsole) -- cgit v1.1 From 8b5d0122007b2a78544b742c35c628c35cdea552 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 30 Mar 2010 17:04:26 +0100 Subject: Completely prevent full update packets being sent after kill object packets If a full update is sent after the kill, the object remains as in the linden viewer but in an undeletable and unowned state until relog This patch prevents this by recording kills in LLClientView --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 51 +++++++++++++++++++--- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 2ab713d..eda9caa 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -40,7 +40,10 @@ using OpenMetaverse.Packets; using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Client; +<<<<<<< HEAD:OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs using OpenSim.Framework.Communications.Cache; +======= +>>>>>>> 696d711... Completely prevent full update packets being sent after kill object packets:OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs using OpenSim.Framework.Statistics; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -348,6 +351,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected PriorityQueue m_avatarTerseUpdates; private PriorityQueue m_primTerseUpdates; private PriorityQueue m_primFullUpdates; + + /// + /// List used in construction of data blocks for an object update packet. This is to stop us having to + /// continually recreate it. + /// + protected List m_fullUpdateDataBlocksBuilder; + + /// + /// Maintain a record of all the objects killed. This allows us to stop an update being sent from the + /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an + /// ownerless phantom. + /// + /// All manipulation of this set has to occur under a m_primFullUpdate.SyncRoot lock + /// + /// + protected HashSet m_killRecord; + private int m_moneyBalance; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; @@ -437,6 +457,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_avatarTerseUpdates = new PriorityQueue(); m_primTerseUpdates = new PriorityQueue(); m_primFullUpdates = new PriorityQueue(m_scene.Entities.Count); + m_fullUpdateDataBlocksBuilder = new List(); + m_killRecord = new HashSet(); m_assetService = m_scene.RequestModuleInterface(); m_hyperAssets = m_scene.RequestModuleInterface(); @@ -1476,7 +1498,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP kill.ObjectData[0].ID = localID; kill.Header.Reliable = true; kill.Header.Zerocoded = true; - OutPacket(kill, ThrottleOutPacketType.State); + + lock (m_primFullUpdates.SyncRoot) + { + m_killRecord.Add(localID); + OutPacket(kill, ThrottleOutPacketType.State); + } } /// @@ -3518,21 +3545,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (count == 0) return; - outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count]; + m_fullUpdateDataBlocksBuilder.Clear(); + for (int i = 0; i < count; i++) { - outPacket.ObjectData[i] = m_primFullUpdates.Dequeue(); + ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue(); + //outPacket.ObjectData[i] = m_primFullUpdates.Dequeue(); + if (!m_killRecord.Contains(block.ID)) + { + m_fullUpdateDataBlocksBuilder.Add(block); + // string text = Util.FieldToString(outPacket.ObjectData[i].Text); // if (text.IndexOf("\n") >= 0) // text = text.Remove(text.IndexOf("\n")); // m_log.DebugFormat( // "[CLIENT]: Sending full info about prim {0} text {1} to client {2}", // outPacket.ObjectData[i].ID, text, Name); + } +// else +// { +// m_log.WarnFormat( +// "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name); +// } } - } - OutPacket(outPacket, ThrottleOutPacketType.State); + outPacket.ObjectData = m_fullUpdateDataBlocksBuilder.ToArray(); + + OutPacket(outPacket, ThrottleOutPacketType.State); + } } public void SendPrimTerseUpdate(SendPrimitiveTerseData data) -- cgit v1.1 From e9bac02fec9c789a6305b031f9ff5eb46f2076b4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 30 Mar 2010 17:04:26 +0100 Subject: Completely prevent full update packets being sent after kill object packets If a full update is sent after the kill, the object remains as in the linden viewer but in an undeletable and unowned state until relog This patch prevents this by recording kills in LLClientView Backport from master --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index eda9caa..8aa1b38 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -40,10 +40,7 @@ using OpenMetaverse.Packets; using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Client; -<<<<<<< HEAD:OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs using OpenSim.Framework.Communications.Cache; -======= ->>>>>>> 696d711... Completely prevent full update packets being sent after kill object packets:OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs using OpenSim.Framework.Statistics; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -- cgit v1.1 From d446b19e72ad2f6726094497295bf944873f8aad Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 30 Mar 2010 17:06:30 +0100 Subject: minor: commented out code removal --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 8aa1b38..724c8bc 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3547,7 +3547,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < count; i++) { ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue(); - //outPacket.ObjectData[i] = m_primFullUpdates.Dequeue(); if (!m_killRecord.Contains(block.ID)) { -- cgit v1.1 From 3b38cc10de9082a037f1aee81877a30b727eea81 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 31 Mar 2010 19:51:17 +0100 Subject: When saving an oar/iar, don't attempt to write out the data byte array if it's empty On Mono 2.6 (and probably before) this causes a non-obvious IOException --- OpenSim/Framework/Serialization/TarArchiveWriter.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/Serialization/TarArchiveWriter.cs b/OpenSim/Framework/Serialization/TarArchiveWriter.cs index 20d0f7e..0bd639f 100644 --- a/OpenSim/Framework/Serialization/TarArchiveWriter.cs +++ b/OpenSim/Framework/Serialization/TarArchiveWriter.cs @@ -208,7 +208,9 @@ namespace OpenSim.Framework.Serialization m_bw.Write(header); // Write out data - m_bw.Write(data); + // An IOException occurs if we try to write out an empty array in Mono 2.6 + if (data.Length > 0) + m_bw.Write(data); if (data.Length % 512 != 0) { -- cgit v1.1 From 1c63f6cd850a76b269df81aa89de17429c65ad60 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 2 Apr 2010 16:25:14 -0700 Subject: Don't append ACKs to zerocoded packets. Although this should fine in theory, I'm seeing the viewer ignore or fail to parse ACKs appended to our zerocoded packets. This should cut down on viewer->sim resend traffic --- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 35 ++++++++++++---------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 3c4fa72..5ed4cd7 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -513,6 +513,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte flags = buffer.Data[0]; bool isResend = (flags & Helpers.MSG_RESENT) != 0; bool isReliable = (flags & Helpers.MSG_RELIABLE) != 0; + bool isZerocoded = (flags & Helpers.MSG_ZEROCODED) != 0; LLUDPClient udpClient = outgoingPacket.Client; if (!udpClient.IsConnected) @@ -522,23 +523,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP int dataLength = buffer.DataLength; - // Keep appending ACKs until there is no room left in the buffer or there are - // no more ACKs to append - uint ackCount = 0; - uint ack; - while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack)) + // NOTE: I'm seeing problems with some viewers when ACKs are appended to zerocoded packets so I've disabled that here + if (!isZerocoded) { - Utils.UIntToBytesBig(ack, buffer.Data, dataLength); - dataLength += 4; - ++ackCount; - } + // Keep appending ACKs until there is no room left in the buffer or there are + // no more ACKs to append + uint ackCount = 0; + uint ack; + while (dataLength + 5 < buffer.Data.Length && udpClient.PendingAcks.Dequeue(out ack)) + { + Utils.UIntToBytesBig(ack, buffer.Data, dataLength); + dataLength += 4; + ++ackCount; + } - if (ackCount > 0) - { - // Set the last byte of the packet equal to the number of appended ACKs - buffer.Data[dataLength++] = (byte)ackCount; - // Set the appended ACKs flag on this packet - buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); + if (ackCount > 0) + { + // Set the last byte of the packet equal to the number of appended ACKs + buffer.Data[dataLength++] = (byte)ackCount; + // Set the appended ACKs flag on this packet + buffer.Data[0] = (byte)(buffer.Data[0] | Helpers.MSG_APPENDED_ACKS); + } } buffer.DataLength = dataLength; -- cgit v1.1 From 427ae1087fa67088afa23bcf533c63b52b62ae42 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 16 Apr 2010 22:57:44 +0100 Subject: minor: correctly print out missing item id when it can't be found rather than a NullReferenceException --- .../ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs | 5 ++++- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index 191e859..cabd51c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs @@ -314,10 +314,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory { // m_log.DebugFormat("[LOCAL INVENTORY SERVICES CONNECTOR]: Requesting inventory item {0}", item.ID); + UUID requestedItemId = item.ID; + item = m_InventoryService.GetItem(item); if (null == item) - m_log.ErrorFormat("[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find item with id {0}", item.ID); + m_log.ErrorFormat( + "[LOCAL INVENTORY SERVICES CONNECTOR]: Could not find item with id {0}", requestedItemId); return item; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 4f2b446..fcbeeb6 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -531,7 +531,6 @@ namespace OpenSim.Region.Framework.Scenes return null; } - if (recipientParentFolderId == UUID.Zero) { InventoryFolderBase recipientRootFolder = InventoryService.GetRootFolder(recipientId); -- cgit v1.1 From 147c2d6f80c6b911839e890cb42cb63020269afc Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 21 May 2010 02:31:14 +0100 Subject: Change the way the object perms are propagated to attempt to salvage some older content --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 44 +++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e031ebc..ba70ae5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -437,29 +437,31 @@ namespace OpenSim.Region.Framework.Scenes itemCopy.InvType = item.InvType; itemCopy.Folder = recipientFolderId; - if (Permissions.PropagatePermissions()) + if (Permissions.PropagatePermissions() && recipient != senderId) { + // First, make sore base is limited to the next perms + itemCopy.BasePermissions = item.BasePermissions & item.NextPermissions; + // By default, current equals base + itemCopy.CurrentPermissions = itemCopy.BasePermissions; + + // If this is an object, replace current perms + // with folded perms if (item.InvType == (int)InventoryType.Object) { - itemCopy.BasePermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); - itemCopy.BasePermissions |= (item.CurrentPermissions & 7) << 13; - } - else - { - itemCopy.BasePermissions = item.BasePermissions & item.NextPermissions; + itemCopy.CurrentPermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); + itemCopy.CurrentPermissions |= (item.CurrentPermissions & 7) << 13; } - itemCopy.CurrentPermissions = itemCopy.BasePermissions; - if ((item.CurrentPermissions & 8) != 0) // Propagate slam bit - { - itemCopy.BasePermissions &= item.NextPermissions; - itemCopy.CurrentPermissions = itemCopy.BasePermissions; - itemCopy.CurrentPermissions |= 8; - } + // Ensure there is no escalation + itemCopy.CurrentPermissions &= item.NextPermissions; + + // Need slam bit on xfer + itemCopy.CurrentPermissions |= 8; itemCopy.NextPermissions = item.NextPermissions; - itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; - itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; + + itemCopy.EveryOnePermissions = 0; + itemCopy.GroupPermissions = 0; } else { @@ -913,12 +915,12 @@ namespace OpenSim.Region.Framework.Scenes if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions()) { + agentItem.BasePermissions = taskItem.BasePermissions & taskItem.NextPermissions; if (taskItem.InvType == (int)InventoryType.Object) - agentItem.BasePermissions = taskItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13); - else - agentItem.BasePermissions = taskItem.BasePermissions; - agentItem.BasePermissions &= taskItem.NextPermissions; - agentItem.CurrentPermissions = agentItem.BasePermissions | 8; + agentItem.CurrentPermissions = agentItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13); + agentItem.CurrentPermissions = agentItem.BasePermissions ; + + agentItem.CurrentPermissions |= 8; agentItem.NextPermissions = taskItem.NextPermissions; agentItem.EveryOnePermissions = taskItem.EveryonePermissions & taskItem.NextPermissions; agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; -- cgit v1.1 From d28da5e5ce4e36c7a0b052fb5d2f04105d95176b Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 21 May 2010 03:41:32 +0100 Subject: Refactor scene presence list for lockless iteration. Lock contention will now only be for simultaneous add/removes of scene presences from the scene. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 131 ++++++++++---------------- 1 file changed, 49 insertions(+), 82 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index c16ba12..3c2203c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -68,11 +68,9 @@ namespace OpenSim.Region.Framework.Scenes #region Fields - protected Dictionary m_scenePresences = new Dictionary(); - protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0]; - protected List m_scenePresenceList = new List(); - protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim(); + protected Dictionary m_scenePresenceMap = new Dictionary(); + protected List m_scenePresenceArray = new List(); // SceneObjects is not currently populated or used. //public Dictionary SceneObjects; @@ -138,9 +136,10 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresencesLock.EnterWriteLock(); try { - m_scenePresences.Clear(); - m_scenePresenceArray = new ScenePresence[0]; - m_scenePresenceList = new List(); + Dictionary newmap = new Dictionary(); + List newlist = new List(); + m_scenePresenceMap = newmap; + m_scenePresenceArray = newlist; } finally { @@ -554,34 +553,27 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresencesLock.EnterWriteLock(); try { - if (!m_scenePresences.ContainsKey(presence.UUID)) + Dictionary newmap = new Dictionary(m_scenePresenceMap); + List newlist = new List(m_scenePresenceArray); + + if (!newmap.ContainsKey(presence.UUID)) { - m_scenePresences.Add(presence.UUID, presence); - - // Create a new array of ScenePresence references - int oldLength = m_scenePresenceArray.Length; - ScenePresence[] newArray = new ScenePresence[oldLength + 1]; - Array.Copy(m_scenePresenceArray, newArray, oldLength); - newArray[oldLength] = presence; - m_scenePresenceArray = newArray; - m_scenePresenceList = new List(m_scenePresenceArray); + newmap.Add(presence.UUID, presence); + newlist.Add(presence); } else { - m_scenePresences[presence.UUID] = presence; - - // Do a linear search through the array of ScenePresence references - // and update the modified entry - for (int i = 0; i < m_scenePresenceArray.Length; i++) - { - if (m_scenePresenceArray[i].UUID == presence.UUID) - { - m_scenePresenceArray[i] = presence; - break; - } - } - m_scenePresenceList = new List(m_scenePresenceArray); + // Remember the old presene reference from the dictionary + ScenePresence oldref = newmap[presence.UUID]; + // Replace the presence reference in the dictionary with the new value + newmap[presence.UUID] = presence; + // Find the index in the list where the old ref was stored and update the reference + newlist[newlist.IndexOf(oldref)] = presence; } + + // Swap out the dictionary and list with new references + m_scenePresenceMap = newmap; + m_scenePresenceArray = newlist; } finally { @@ -604,24 +596,19 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresencesLock.EnterWriteLock(); try { - if (m_scenePresences.Remove(agentID)) + Dictionary newmap = new Dictionary(m_scenePresenceMap); + List newlist = new List(m_scenePresenceArray); + + // Remember the old presene reference from the dictionary + ScenePresence oldref = newmap[agentID]; + // Remove the presence reference from the dictionary + if (newmap.Remove(agentID)) { - // Copy all of the elements from the previous array - // into the new array except the removed element - int oldLength = m_scenePresenceArray.Length; - ScenePresence[] newArray = new ScenePresence[oldLength - 1]; - int j = 0; - for (int i = 0; i < m_scenePresenceArray.Length; i++) - { - ScenePresence presence = m_scenePresenceArray[i]; - if (presence.UUID != agentID) - { - newArray[j] = presence; - ++j; - } - } - m_scenePresenceArray = newArray; - m_scenePresenceList = new List(m_scenePresenceArray); + // Find the index in the list where the old ref was stored and remove the reference + newlist.RemoveAt(newlist.IndexOf(oldref)); + // Swap out the dictionary and list with new references + m_scenePresenceMap = newmap; + m_scenePresenceArray = newlist; } else { @@ -744,7 +731,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Request a copy of m_scenePresences in this World + /// Get a reference to the scene presence list. Changes to the list will be done in a copy /// There is no guarantee that presences will remain in the scene after the list is returned. /// This list should remain private to SceneGraph. Callers wishing to iterate should instead /// pass a delegate to ForEachScenePresence. @@ -752,15 +739,7 @@ namespace OpenSim.Region.Framework.Scenes /// private List GetScenePresences() { - m_scenePresencesLock.EnterReadLock(); - try - { - return m_scenePresenceList; - } - finally - { - m_scenePresencesLock.ExitReadLock(); - } + return m_scenePresenceArray; } /// @@ -770,17 +749,10 @@ namespace OpenSim.Region.Framework.Scenes /// null if the presence was not found protected internal ScenePresence GetScenePresence(UUID agentID) { - ScenePresence sp; - m_scenePresencesLock.EnterReadLock(); - try - { - m_scenePresences.TryGetValue(agentID, out sp); - } - finally - { - m_scenePresencesLock.ExitReadLock(); - } - return sp; + Dictionary presences = m_scenePresenceMap; + ScenePresence presence; + presences.TryGetValue(agentID, out presence); + return presence; } /// @@ -791,7 +763,8 @@ namespace OpenSim.Region.Framework.Scenes /// null if the presence was not found protected internal ScenePresence GetScenePresence(string firstName, string lastName) { - foreach (ScenePresence presence in GetScenePresences()) + List presences = GetScenePresences(); + foreach (ScenePresence presence in presences) { if (presence.Firstname == firstName && presence.Lastname == lastName) return presence; @@ -806,7 +779,8 @@ namespace OpenSim.Region.Framework.Scenes /// null if the presence was not found protected internal ScenePresence GetScenePresence(uint localID) { - foreach (ScenePresence presence in GetScenePresences()) + List presences = GetScenePresences(); + foreach (ScenePresence presence in presences) if (presence.LocalId == localID) return presence; return null; @@ -814,15 +788,8 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) { - m_scenePresencesLock.EnterReadLock(); - try - { - m_scenePresences.TryGetValue(agentID, out avatar); - } - finally - { - m_scenePresencesLock.ExitReadLock(); - } + Dictionary presences = m_scenePresenceMap; + presences.TryGetValue(agentID, out avatar); return (avatar != null); } @@ -1099,9 +1066,9 @@ namespace OpenSim.Region.Framework.Scenes }); Parallel.ForEach(GetScenePresences(), protectedAction); */ - // For now, perform actiona serially - - foreach (ScenePresence sp in GetScenePresences()) + // For now, perform actions serially + List presences = GetScenePresences(); + foreach (ScenePresence sp in presences) { try { -- cgit v1.1 From af5eeab7cf86ec5b8a90aa435d7068ef954dc504 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 21 May 2010 07:37:55 +0200 Subject: Ensure that the first update sent out for any given prim is a full update --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index e29ae2a..cddc7b2 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -325,6 +325,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private int m_cachedTextureSerial; private PriorityQueue m_entityUpdates; + private Dictionary m_seenPrims = new Dictionary(); /// /// List used in construction of data blocks for an object update packet. This is to stop us having to @@ -3495,7 +3496,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Compressed object updates only make sense for LL primitives if (!(update.Entity is SceneObjectPart)) + { canUseCompressed = false; + } + else + { + if (!m_seenPrims.ContainsKey(((SceneObjectPart)update.Entity).LocalId)) + { + updateFlags = PrimUpdateFlags.FullUpdate; + m_seenPrims[((SceneObjectPart)update.Entity).LocalId] = true; + } + } if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) { -- cgit v1.1 From 59546a348a4a47e21c5d05e53e1a2b15da10ce7a Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 21 May 2010 02:31:14 +0100 Subject: Change the way the object perms are propagated to attempt to salvage some older content --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 44 +++++++++++----------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index fcbeeb6..af5742c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -438,29 +438,31 @@ namespace OpenSim.Region.Framework.Scenes itemCopy.InvType = item.InvType; itemCopy.Folder = recipientFolderId; - if (Permissions.PropagatePermissions()) + if (Permissions.PropagatePermissions() && recipient != senderId) { + // First, make sore base is limited to the next perms + itemCopy.BasePermissions = item.BasePermissions & item.NextPermissions; + // By default, current equals base + itemCopy.CurrentPermissions = itemCopy.BasePermissions; + + // If this is an object, replace current perms + // with folded perms if (item.InvType == (int)InventoryType.Object) { - itemCopy.BasePermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); - itemCopy.BasePermissions |= (item.CurrentPermissions & 7) << 13; - } - else - { - itemCopy.BasePermissions = item.BasePermissions & item.NextPermissions; + itemCopy.CurrentPermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); + itemCopy.CurrentPermissions |= (item.CurrentPermissions & 7) << 13; } - itemCopy.CurrentPermissions = itemCopy.BasePermissions; - if ((item.CurrentPermissions & 8) != 0) // Propagate slam bit - { - itemCopy.BasePermissions &= item.NextPermissions; - itemCopy.CurrentPermissions = itemCopy.BasePermissions; - itemCopy.CurrentPermissions |= 8; - } + // Ensure there is no escalation + itemCopy.CurrentPermissions &= item.NextPermissions; + + // Need slam bit on xfer + itemCopy.CurrentPermissions |= 8; itemCopy.NextPermissions = item.NextPermissions; - itemCopy.EveryOnePermissions = item.EveryOnePermissions & item.NextPermissions; - itemCopy.GroupPermissions = item.GroupPermissions & item.NextPermissions; + + itemCopy.EveryOnePermissions = 0; + itemCopy.GroupPermissions = 0; } else { @@ -909,12 +911,12 @@ namespace OpenSim.Region.Framework.Scenes if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions()) { + agentItem.BasePermissions = taskItem.BasePermissions & taskItem.NextPermissions; if (taskItem.InvType == (int)InventoryType.Object) - agentItem.BasePermissions = taskItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13); - else - agentItem.BasePermissions = taskItem.BasePermissions; - agentItem.BasePermissions &= taskItem.NextPermissions; - agentItem.CurrentPermissions = agentItem.BasePermissions | 8; + agentItem.CurrentPermissions = agentItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13); + agentItem.CurrentPermissions = agentItem.BasePermissions ; + + agentItem.CurrentPermissions |= 8; agentItem.NextPermissions = taskItem.NextPermissions; agentItem.EveryOnePermissions = taskItem.EveryonePermissions & taskItem.NextPermissions; agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; -- cgit v1.1 From e4114799c3b25cd54d409a686175f39d1ec5b25b Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 21 May 2010 15:26:04 +0100 Subject: Replace CSJ2K with fixed version (Mantis #3318) --- bin/CSJ2K.dll | Bin 491520 -> 502784 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/bin/CSJ2K.dll b/bin/CSJ2K.dll index 31e0d59..238291f 100644 Binary files a/bin/CSJ2K.dll and b/bin/CSJ2K.dll differ -- cgit v1.1 From e589a31bc4056ed5fe20abb917d6c1ec6d1db2c4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 21 May 2010 22:23:13 +0100 Subject: Only send dialogs and notices to root agents, not child agents Small change for backport Conflicts: OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs --- OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index 72ec869..6a9a962 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -79,7 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { ScenePresence sp = m_scene.GetScenePresence(agentID); - if (sp != null) + if (sp != null && !sp.IsChildAgent) sp.ControllingClient.SendAgentAlertMessage(message, modal); } @@ -91,7 +91,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { ScenePresence presence = presenceList[i]; - if (presence.Firstname == firstName && presence.Lastname == lastName) + if (!presence.IsChildAgent && presence.Firstname == firstName && presence.Lastname == lastName) { presence.ControllingClient.SendAgentAlertMessage(message, modal); break; @@ -130,7 +130,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog } ScenePresence sp = m_scene.GetScenePresence(avatarID); - if (sp != null) + if (sp != null && !sp.IsChildAgent) sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); } @@ -139,7 +139,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { ScenePresence sp = m_scene.GetScenePresence(avatarID); - if (sp != null) + if (sp != null && !sp.IsChildAgent) sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); } @@ -206,4 +206,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog return result; } } -} +} \ No newline at end of file -- cgit v1.1 From 3bd2ec7b2e9eeaaff62872c5a61b6cee358f51a1 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 21 May 2010 22:40:15 +0100 Subject: Apply http://opensimulator.org/mantis/view.php?id=4724 Tweak to update appearance calls Fix for deleting inventory items from a folder. Thanks StrawberryFride! --- OpenSim/Data/MSSQL/MSSQLInventoryData.cs | 4 ++-- OpenSim/Data/MSSQL/MSSQLUserData.cs | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/OpenSim/Data/MSSQL/MSSQLInventoryData.cs b/OpenSim/Data/MSSQL/MSSQLInventoryData.cs index 1482184..c1eee8d 100644 --- a/OpenSim/Data/MSSQL/MSSQLInventoryData.cs +++ b/OpenSim/Data/MSSQL/MSSQLInventoryData.cs @@ -635,9 +635,9 @@ namespace OpenSim.Data.MSSQL /// connection to the database private void DeleteItemsInFolder(UUID folderID, SqlConnection connection) { - using (SqlCommand command = new SqlCommand("DELETE FROM inventoryitems WHERE folderID=@folderID", connection)) + using (SqlCommand command = new SqlCommand("DELETE FROM inventoryitems WHERE parentFolderID=@parentFolderID", connection)) { - command.Parameters.Add(database.CreateParameter("folderID", folderID)); + command.Parameters.Add(database.CreateParameter("parentFolderID", folderID)); try { diff --git a/OpenSim/Data/MSSQL/MSSQLUserData.cs b/OpenSim/Data/MSSQL/MSSQLUserData.cs index 3ef1053..7fe8ed0 100644 --- a/OpenSim/Data/MSSQL/MSSQLUserData.cs +++ b/OpenSim/Data/MSSQL/MSSQLUserData.cs @@ -582,8 +582,21 @@ namespace OpenSim.Data.MSSQL /// the appearence override public void UpdateUserAppearance(UUID user, AvatarAppearance appearance) { - string sql = @"DELETE FROM avatarappearance WHERE owner=@owner; - INSERT INTO avatarappearance + string sql = @"DELETE FROM avatarappearance WHERE owner=@owner"; + using (AutoClosingSqlCommand cmd = database.Query(sql)) + { + cmd.Parameters.Add(database.CreateParameter("@owner", appearance.Owner)); + try + { + cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + m_log.ErrorFormat("[USER DB] Error deleting old user appearance, error: {0}", e.Message); + } + } + + sql=@"INSERT INTO avatarappearance (owner, serial, visual_params, texture, avatar_height, body_item, body_asset, skin_item, skin_asset, hair_item, hair_asset, eyes_item, eyes_asset, shirt_item, shirt_asset, -- cgit v1.1 From 72b96e81213c0dd3d586f552bd2cbd9221c5341d Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 23 May 2010 06:12:11 +0100 Subject: Add the SitGround flag back in --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 49a7766..d7660fd 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -140,6 +140,7 @@ namespace OpenSim.Region.Framework.Scenes private Vector3? m_forceToApply; private uint m_requestedSitTargetID; private UUID m_requestedSitTargetUUID; + public bool SitGround = false; private SendCourseLocationsMethod m_sendCourseLocationsMethod; @@ -1643,7 +1644,7 @@ namespace OpenSim.Region.Framework.Scenes } } - if (update_movementflag) + if (update_movementflag && !SitGround) Animator.UpdateMovementAnimations(); m_scene.EventManager.TriggerOnClientMovement(this); @@ -1754,6 +1755,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void StandUp() { + SitGround = false; + if (m_parentID != 0) { SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); -- cgit v1.1 From 2603f9a134ca3a3e5ed823d4f670feeab02537e7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 24 May 2010 16:53:43 +0100 Subject: stop "load oar" reporting ignored objects when those objects were actually loaded just fine this fix also means that loaded scripts are properly/more promptly started here, the fix is only done in the oar module. In master, the underlying problem was fixed instead but this is more invasive. --- OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 381c8f7..2e30e09 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -276,7 +276,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) + if (!m_scene.AddRestoredSceneObject(sceneObject, true, false)) { sceneObjectsLoadedCount++; sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); -- cgit v1.1 From 8048a8a39daf98b1068e84473e3e29ce0323e6f0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 24 May 2010 17:33:58 +0100 Subject: backport some IGroupsModule method doc and an extra exposed method from git master --- .../Region/Framework/Interfaces/IGroupsModule.cs | 33 ++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs index 8980b2d..9683da0 100644 --- a/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IGroupsModule.cs @@ -37,6 +37,37 @@ namespace OpenSim.Region.Framework.Interfaces { event NewGroupNotice OnNewGroupNotice; + /// + /// Create a group + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// The UUID of the created group + UUID CreateGroup( + IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, + bool openEnrollment, bool allowPublish, bool maturePublish); + + /// + /// Get a group + /// + /// Name of the group + /// The group's data. Null if there is no such group. + GroupRecord GetGroupRecord(string name); + + /// + /// Get a group + /// + /// ID of the group + /// The group's data. Null if there is no such group. + GroupRecord GetGroupRecord(UUID GroupID); + void ActivateGroup(IClientAPI remoteClient, UUID groupID); List GroupTitlesRequest(IClientAPI remoteClient, UUID groupID); List GroupMembersRequest(IClientAPI remoteClient, UUID groupID); @@ -51,7 +82,6 @@ namespace OpenSim.Region.Framework.Interfaces void SetGroupAcceptNotices(IClientAPI remoteClient, UUID groupID, bool acceptNotices, bool listInProfile); void GroupTitleUpdate(IClientAPI remoteClient, UUID GroupID, UUID TitleRoleID); - UUID CreateGroup(IClientAPI remoteClient, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); GroupNoticeData[] GroupNoticesListRequest(IClientAPI remoteClient, UUID GroupID); string GetGroupTitle(UUID avatarID); @@ -64,7 +94,6 @@ namespace OpenSim.Region.Framework.Interfaces void LeaveGroupRequest(IClientAPI remoteClient, UUID GroupID); void EjectGroupMemberRequest(IClientAPI remoteClient, UUID GroupID, UUID EjecteeID); void InviteGroupRequest(IClientAPI remoteClient, UUID GroupID, UUID InviteeID, UUID RoleID); - GroupRecord GetGroupRecord(UUID GroupID); void NotifyChange(UUID GroupID); } } -- cgit v1.1 From a6c7995b71ee1886bf94b2c63d0a603525a0667f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 24 May 2010 19:19:44 +0100 Subject: backport from master fix for attachment display this fix stops two full updates being sent on attachment rather than one. Sending two can stop the client displaying attachments properly --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 5 ++++- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 1 - OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index af5742c..42a748f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2076,7 +2076,10 @@ namespace OpenSim.Region.Framework.Scenes group.RootPart.IsAttachment = true; } - AddNewSceneObject(group, true); + // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since + // we'll be doing that later on. Scheduling more than one full update during the attachment + // process causes some clients to fail to display the attachment properly. + AddNewSceneObject(group, true, !attachment); // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); // if attachment we set it's asset id so object updates can reflect that diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index ad24160..59a2f41 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -536,7 +536,6 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[SCENE GRAPH]: Retrieved single object {0} for attachment to {1} on point {2}", // objatt.Name, remoteClient.Name, AttachmentPt); - if (objatt != null) { bool tainted = false; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c14b39a..602b811 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1514,7 +1514,7 @@ namespace OpenSim.Region.Framework.Scenes internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags) { // m_log.DebugFormat( -// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); +// "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); if (m_rootPart.UUID == part.UUID) { -- cgit v1.1 From f90d81a864c8ae1cf8125839bc883dc0ace7f214 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 26 May 2010 19:26:30 +0200 Subject: Just because there is an agent update handler, that doesn't mean there is a pre agent update handler. Null check these separately. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 173c9e5..51cc763 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -4922,14 +4922,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP arg.SessionID = x.SessionID; arg.State = x.State; UpdateAgent handlerAgentUpdate = OnAgentUpdate; + UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; lastarg = arg; // save this set of arguments for nexttime - if (handlerAgentUpdate != null) - { + if (handlerPreAgentUpdate != null) OnPreAgentUpdate(this, arg); + if (handlerAgentUpdate != null) OnAgentUpdate(this, arg); - } handlerAgentUpdate = null; + handlerPreAgentUpdate = null; } } -- cgit v1.1 From 9e3b5a558718bc7a0b919fa083811f6a02322409 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 26 May 2010 19:29:56 +0200 Subject: Remove orphaned .dll.config files from tests --- ...enSim.Framework.Communications.Tests.dll.config | 33 ---------------------- bin/OpenSim.Framework.Servers.Tests.dll.config | 33 ---------------------- bin/OpenSim.Framework.Tests.dll.config | 33 ---------------------- bin/OpenSim.Region.CoreModules.Tests.dll.config | 33 ---------------------- bin/OpenSim.Region.Framework.Tests.dll.config | 33 ---------------------- bin/OpenSim.Region.ScriptEngine.Tests.dll.config | 33 ---------------------- 6 files changed, 198 deletions(-) delete mode 100644 bin/OpenSim.Framework.Communications.Tests.dll.config delete mode 100644 bin/OpenSim.Framework.Servers.Tests.dll.config delete mode 100644 bin/OpenSim.Framework.Tests.dll.config delete mode 100644 bin/OpenSim.Region.CoreModules.Tests.dll.config delete mode 100644 bin/OpenSim.Region.Framework.Tests.dll.config delete mode 100644 bin/OpenSim.Region.ScriptEngine.Tests.dll.config diff --git a/bin/OpenSim.Framework.Communications.Tests.dll.config b/bin/OpenSim.Framework.Communications.Tests.dll.config deleted file mode 100644 index a3f681d..0000000 --- a/bin/OpenSim.Framework.Communications.Tests.dll.config +++ /dev/null @@ -1,33 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bin/OpenSim.Framework.Servers.Tests.dll.config b/bin/OpenSim.Framework.Servers.Tests.dll.config deleted file mode 100644 index a3f681d..0000000 --- a/bin/OpenSim.Framework.Servers.Tests.dll.config +++ /dev/null @@ -1,33 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bin/OpenSim.Framework.Tests.dll.config b/bin/OpenSim.Framework.Tests.dll.config deleted file mode 100644 index a3f681d..0000000 --- a/bin/OpenSim.Framework.Tests.dll.config +++ /dev/null @@ -1,33 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bin/OpenSim.Region.CoreModules.Tests.dll.config b/bin/OpenSim.Region.CoreModules.Tests.dll.config deleted file mode 100644 index a3f681d..0000000 --- a/bin/OpenSim.Region.CoreModules.Tests.dll.config +++ /dev/null @@ -1,33 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bin/OpenSim.Region.Framework.Tests.dll.config b/bin/OpenSim.Region.Framework.Tests.dll.config deleted file mode 100644 index a3f681d..0000000 --- a/bin/OpenSim.Region.Framework.Tests.dll.config +++ /dev/null @@ -1,33 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bin/OpenSim.Region.ScriptEngine.Tests.dll.config b/bin/OpenSim.Region.ScriptEngine.Tests.dll.config deleted file mode 100644 index a3f681d..0000000 --- a/bin/OpenSim.Region.ScriptEngine.Tests.dll.config +++ /dev/null @@ -1,33 +0,0 @@ - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- cgit v1.1 From 32c43bf59a3b9c3cb0b9eb1d52f664997e39a50d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 5 Apr 2010 19:37:02 +0100 Subject: Partially implement share with group option for object inventory items If serverside permissions are off then this works as expected. Previously, it was impossible for more than one person to edit such items even if permissions were off. If serverside permissions are on then this works as expected if the object was created by an avatar who had the required group active. However, if the group for the object is later set then the contained item is still not editable. This may be linked to a wider bug where the object is still not modifiable by the group anyway Resolve conflict in LLClientView --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 13 ++++++++----- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 1 + .../Region/Framework/Scenes/SceneObjectGroup.Inventory.cs | 4 +++- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 10 +++++++++- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 724c8bc..bd0c146 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -657,8 +657,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void ProcessSpecificPacketAsync(object state) { AsyncPacketProcess packetObject = (AsyncPacketProcess)state; - packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack); - + packetObject.result = packetObject.Method(packetObject.ClientView, packetObject.Pack); } #endregion Packet Handling @@ -7662,12 +7661,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP newTaskItem.GroupPermissions = updatetask.InventoryData.GroupMask; newTaskItem.EveryonePermissions = updatetask.InventoryData.EveryoneMask; newTaskItem.NextPermissions = updatetask.InventoryData.NextOwnerMask; + + // Unused? Clicking share with group sets GroupPermissions instead, so perhaps this is something + // different //newTaskItem.GroupOwned=updatetask.InventoryData.GroupOwned; newTaskItem.Type = updatetask.InventoryData.Type; newTaskItem.InvType = updatetask.InventoryData.InvType; newTaskItem.Flags = updatetask.InventoryData.Flags; //newTaskItem.SaleType=updatetask.InventoryData.SaleType; - //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice;; + //newTaskItem.SalePrice=updatetask.InventoryData.SalePrice; newTaskItem.Name = Util.FieldToString(updatetask.InventoryData.Name); newTaskItem.Description = Util.FieldToString(updatetask.InventoryData.Description); newTaskItem.CreationDate = (uint)updatetask.InventoryData.CreationDate; @@ -7675,7 +7677,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP newTaskItem, updatetask.UpdateData.LocalID); } } - } + } return true; } @@ -11590,6 +11592,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public PacketMethod method; public bool Async; } + public class AsyncPacketProcess { public bool result = false; @@ -11632,4 +11635,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(packet, ThrottleOutPacketType.Task); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 42a748f..26d3372 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1222,6 +1222,7 @@ namespace OpenSim.Region.Framework.Scenes item = CommsManager.UserProfileCacheService.LibraryRoot.FindItem(itemID); } + // If we've found the item in the user's inventory or in the library if (item != null) { part.ParentGroup.AddInventoryItem(remoteClient, primLocalID, item, copyID); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 71354b4..4034744 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -173,7 +173,9 @@ namespace OpenSim.Region.Framework.Scenes item.NextPermissions; taskItem.NextPermissions = item.NextPermissions; taskItem.CurrentPermissions |= 8; - } else { + } + else + { taskItem.BasePermissions = item.BasePermissions; taskItem.CurrentPermissions = item.CurrentPermissions; taskItem.CurrentPermissions |= 8; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 21ca1de..d175695 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -528,6 +528,7 @@ namespace OpenSim.Region.Framework.Scenes item.ParentID = m_part.UUID; item.ParentPartID = m_part.UUID; item.Name = name; + item.GroupID = m_part.GroupID; lock (m_items) { @@ -620,6 +621,12 @@ namespace OpenSim.Region.Framework.Scenes item.ParentID = m_part.UUID; item.ParentPartID = m_part.UUID; item.Flags = m_items[item.ItemID].Flags; + + // If group permissions have been set on, check that the groupID is up to date in case it has + // changed since permissions were last set. + if (item.GroupPermissions != (uint)PermissionMask.None) + item.GroupID = m_part.GroupID; + if (item.AssetID == UUID.Zero) { item.AssetID = m_items[item.ItemID].AssetID; @@ -771,6 +778,7 @@ namespace OpenSim.Region.Framework.Scenes uint everyoneMask = 0; uint baseMask = item.BasePermissions; uint ownerMask = item.CurrentPermissions; + uint groupMask = item.GroupPermissions; invString.AddItemStart(); invString.AddNameValueLine("item_id", item.ItemID.ToString()); @@ -780,7 +788,7 @@ namespace OpenSim.Region.Framework.Scenes invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); - invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); + invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); -- cgit v1.1 From 66a833796c6eb6c7db75fa001370b3ee7689b9e7 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 5 Apr 2010 20:42:20 +0100 Subject: check group membership and powers with the groups module rather than just the client's active group id this resolves the earlier issue where notecards/scripts shared with group could only be edited if the user had that group active --- .../World/Permissions/PermissionsModule.cs | 39 +++++++++++++++------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index b557186..db900df 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -145,7 +145,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions private Dictionary GrantVB = new Dictionary(); private Dictionary GrantJS = new Dictionary(); private Dictionary GrantYP = new Dictionary(); - private IFriendsModule m_friendsModule = null; + private IFriendsModule m_friendsModule; + private IGroupsModule m_groupsModule; #endregion @@ -370,9 +371,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_friendsModule = m_scene.RequestModuleInterface(); if (m_friendsModule == null) - m_log.Error("[PERMISSIONS]: Friends module not found, friend permissions will not work"); - else - m_log.Info("[PERMISSIONS]: Friends module found, friend permissions enabled"); + m_log.Warn("[PERMISSIONS]: Friends module not found, friend permissions will not work"); + + m_groupsModule = m_scene.RequestModuleInterface(); + + if (m_groupsModule == null) + m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work"); } public void Close() @@ -407,14 +411,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions // with the powers requested (powers = 0 for no powers check) protected bool IsGroupMember(UUID groupID, UUID userID, ulong powers) { - ScenePresence sp = m_scene.GetScenePresence(userID); - if (sp != null) - { - IClientAPI client = sp.ControllingClient; + if (null == m_groupsModule) + return false; + + GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, userID); - return ((groupID == client.ActiveGroupId) && (client.ActiveGroupPowers != 0) && - ((powers == 0) || ((client.ActiveGroupPowers & powers) == powers))); + if (gmd != null) + { + if (((gmd.GroupPowers != 0) && powers == 0) || (gmd.GroupPowers & powers) == powers) + return true; } + return false; } @@ -705,8 +712,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions permission = false; } +// m_log.DebugFormat( +// "[PERMISSIONS]: group.GroupID = {0}, part.GroupMask = {1}, isGroupMember = {2} for {3}", +// group.GroupID, +// m_scene.GetSceneObjectPart(objId).GroupMask, +// IsGroupMember(group.GroupID, currentUser, 0), +// currentUser); + // Group members should be able to edit group objects - if ((group.GroupID != UUID.Zero) && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) && IsGroupMember(group.GroupID, currentUser, 0)) + if ((group.GroupID != UUID.Zero) + && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) + && IsGroupMember(group.GroupID, currentUser, 0)) { // Return immediately, so that the administrator can shares group objects return true; @@ -941,7 +957,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); } -- cgit v1.1 From d6e1333810b41407378a534a720128b498e0aada Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 19 Apr 2010 21:02:36 +0100 Subject: If a transfer request is received for a task inventory item asset, then route the permissions request through the existing CanEditScript() and CanEditNotecard() methods. This implements the 'share with group' flag for notecards and scripts in prim inventory since the PermissionsModule checks group membership and permissions. Other than that, the code in PermissionsModule duplicates the checks in LLClientView so there should be no change other than allowing group members to edit embedded notecards and scripts. For all other asset types, the permission checking code in LLClientView continues to be used, pending refactoring of suitable permissions code This means that 'share with group' will not yet work for prim inventory items other than notecards and scripts --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 99 +++++++++++++++++----- .../World/Permissions/PermissionsModule.cs | 17 ++-- 2 files changed, 91 insertions(+), 25 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index bd0c146..c9ef173 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -7053,32 +7053,89 @@ namespace OpenSim.Region.ClientStack.LindenUDP taskID = new UUID(transfer.TransferInfo.Params, 48); UUID itemID = new UUID(transfer.TransferInfo.Params, 64); UUID requestID = new UUID(transfer.TransferInfo.Params, 80); + +// m_log.DebugFormat( +// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}", +// requestID, itemID, taskID, Name); + if (!(((Scene)m_scene).Permissions.BypassPermissions())) { if (taskID != UUID.Zero) // Prim { SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); if (part == null) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist", + Name, requestID, itemID, taskID); return true; + } - if (part.OwnerID != AgentId) - return true; - - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return true; - - TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); - if (ti == null) - return true; - - if (ti.OwnerID != AgentId) - return true; - - if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) - return true; - - if (ti.AssetID != requestID) + TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID); + if (tii == null) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist", + Name, requestID, itemID, taskID); return true; + } + + if (tii.Type == (int)AssetType.LSLText) + { + if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId)) + return true; + } + else if (tii.Type == (int)AssetType.Notecard) + { + if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId)) + return true; + } + else + { + // TODO: Change this code to allow items other than notecards and scripts to be successfully + // shared with group. In fact, all this permissions checking should move to an IPermissionsModule + if (part.OwnerID != AgentId) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}", + Name, requestID, itemID, taskID, part.OwnerID); + return true; + } + + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set", + Name, requestID, itemID, taskID); + return true; + } + + if (tii.OwnerID != AgentId) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}", + Name, requestID, itemID, taskID, tii.OwnerID); + return true; + } + + if (( + tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer", + Name, requestID, itemID, taskID); + return true; + } + + if (tii.AssetID != requestID) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}", + Name, requestID, itemID, taskID, tii.AssetID); + return true; + } + } } else // Agent { @@ -7114,7 +7171,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (assetRequestItem.AssetID != requestID) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", + Name, requestID, itemID, assetRequestItem.AssetID); return true; + } } } } @@ -11310,8 +11372,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // } } - //check to see if asset is in local cache, if not we need to request it from asset server. - //m_log.Debug("asset request " + requestID); +// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index db900df..a972ca6 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -1063,7 +1063,9 @@ namespace OpenSim.Region.CoreModules.World.Permissions if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) return false; - } else { + } + else + { if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) return false; } @@ -1079,7 +1081,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; if (!IsGroupMember(ti.GroupID, user, 0)) - return false; + return false; } // Require full perms @@ -1483,14 +1485,16 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (part.OwnerID != user) { if (part.GroupID == UUID.Zero) - return false; + return false; if (!IsGroupMember(part.GroupID, user, 0)) return false; if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) return false; - } else { + } + else + { if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) return false; } @@ -1806,7 +1810,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions // Is it correct to be less restrictive for lists of objects to be returned? } - private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) { + private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) + { //m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType); switch (scriptType) { case 0: @@ -1840,4 +1845,4 @@ namespace OpenSim.Region.CoreModules.World.Permissions return(false); } } -} +} \ No newline at end of file -- cgit v1.1 From ac5373427f99d259a55147e097a8a76050a60db6 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 27 May 2010 20:08:12 +0200 Subject: Comment noisy "CONNECTION DEBUGGING" messages, because they push more important stuff off screen too fast. Clean this time --- OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs | 14 +++++++------- OpenSim/Server/Handlers/Simulation/AgentHandlers.cs | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs index 17d7850..e50481a 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HomeAgentHandlers.cs @@ -61,13 +61,13 @@ namespace OpenSim.Server.Handlers.Hypergrid public Hashtable Handler(Hashtable request) { - m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called"); - - m_log.Debug("---------------------------"); - m_log.Debug(" >> uri=" + request["uri"]); - m_log.Debug(" >> content-type=" + request["content-type"]); - m_log.Debug(" >> http-method=" + request["http-method"]); - m_log.Debug("---------------------------\n"); +// m_log.Debug("[CONNECTION DEBUGGING]: HomeAgentHandler Called"); +// +// m_log.Debug("---------------------------"); +// m_log.Debug(" >> uri=" + request["uri"]); +// m_log.Debug(" >> content-type=" + request["content-type"]); +// m_log.Debug(" >> http-method=" + request["http-method"]); +// m_log.Debug("---------------------------\n"); Hashtable responsedata = new Hashtable(); responsedata["content_type"] = "text/html"; diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index b648e12..c4117f5 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -61,13 +61,13 @@ namespace OpenSim.Server.Handlers.Simulation public Hashtable Handler(Hashtable request) { - m_log.Debug("[CONNECTION DEBUGGING]: AgentHandler Called"); - - m_log.Debug("---------------------------"); - m_log.Debug(" >> uri=" + request["uri"]); - m_log.Debug(" >> content-type=" + request["content-type"]); - m_log.Debug(" >> http-method=" + request["http-method"]); - m_log.Debug("---------------------------\n"); +// m_log.Debug("[CONNECTION DEBUGGING]: AgentHandler Called"); +// +// m_log.Debug("---------------------------"); +// m_log.Debug(" >> uri=" + request["uri"]); +// m_log.Debug(" >> content-type=" + request["content-type"]); +// m_log.Debug(" >> http-method=" + request["http-method"]); +// m_log.Debug("---------------------------\n"); Hashtable responsedata = new Hashtable(); responsedata["content_type"] = "text/html"; -- cgit v1.1 From ba49319c077bc5e7b998674aaac62497e757706c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 27 May 2010 20:08:48 +0200 Subject: Prevent a null ref --- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs index 4ba4fab..2fc98e5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs +++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs @@ -84,6 +84,9 @@ namespace OpenSim.Region.Framework.Scenes while (m_pendingObjects != null && m_pendingObjects.Count > 0) { SceneObjectGroup g = m_pendingObjects.Dequeue(); + // Yes, this can really happen + if (g == null) + continue; // This is where we should check for draw distance // do culling and stuff. Problem with that is that until -- cgit v1.1 From 5074d290e4aeb583560272cadc8ba09aa8337210 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 27 May 2010 21:35:17 +0100 Subject: commit code which stops full updates being fired multiple times when attachments cross standalone region boundaries lots of messy debug code here too which would need to be removed --- .../Interregion/LocalInterregionComms.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 5 +++ .../Framework/Scenes/Scene.PacketHandlers.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.cs | 43 +++++++++++++++++++--- .../Framework/Scenes/SceneCommunicationService.cs | 2 + OpenSim/Region/Framework/Scenes/SceneGraph.cs | 34 ++++++++++++++++- .../Region/Framework/Scenes/SceneObjectGroup.cs | 15 ++++++-- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 34 +++++++++++++---- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 8 +++- bin/OpenSim.exe.config | 2 +- 10 files changed, 123 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs index d68c683..4abc215 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs @@ -260,7 +260,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion { if (s.RegionInfo.RegionHandle == regionHandle) { - //m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); + m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); if (isLocalCall) { // We need to make a local copy of the object diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 42a748f..aa724c5 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2449,6 +2449,8 @@ namespace OpenSim.Region.Framework.Scenes return; } + m_log.DebugFormat("[SCENE INVENTORY]: {0} {1} IsAttachment={2}", att.Name, att.LocalId, att.IsAttachment); + Console.WriteLine("HERE X"); ScenePresence presence; if (TryGetAvatar(remoteClient.AgentId, out presence)) { @@ -2456,9 +2458,12 @@ namespace OpenSim.Region.Framework.Scenes InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = InventoryService.GetItem(item); presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); + Console.WriteLine("HERE Y"); if (m_AvatarFactory != null) m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + + Console.WriteLine("HERE Z"); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index ac04dc7..d8e604f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -124,6 +124,7 @@ namespace OpenSim.Region.Framework.Scenes { if (((SceneObjectGroup)ent).LocalId == primLocalID) { + m_log.DebugFormat("[SCENE]: Received full update request for {0} from {1}", primLocalID, remoteClient.Name); ((SceneObjectGroup)ent).SendFullUpdateToClient(remoteClient); return; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 637ebff..dd2d2cc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1850,9 +1850,31 @@ namespace OpenSim.Region.Framework.Scenes /// true if the object was added, false if an object with the same uuid was already in the scene /// public bool AddRestoredSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) + { + return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); + } + + /// + /// Add an object into the scene that has come from storage + /// + /// + /// + /// + /// If true, changes to the object will be reflected in its persisted data + /// If false, the persisted data will not be changed even if the object in the scene is changed + /// + /// + /// If true, we won't persist this object until it changes + /// If false, we'll persist this object immediately + /// + /// + /// true if the object was added, false if an object with the same uuid was already in the scene + /// + public bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) { - return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted); + return AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); } /// @@ -2461,7 +2483,7 @@ namespace OpenSim.Region.Framework.Scenes /// public bool IncomingCreateObject(ISceneObject sog) { - //m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); + m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); SceneObjectGroup newObject; try { @@ -2533,10 +2555,12 @@ namespace OpenSim.Region.Framework.Scenes if (sceneObject.IsAttachmentCheckFull()) // Attachment { + m_log.DebugFormat("[SCENE]: Adding attachment {0} {1}", sceneObject.Name, sceneObject.LocalId); + sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); sceneObject.RootPart.AddFlag(PrimFlags.Phantom); - AddRestoredSceneObject(sceneObject, false, false); + AddRestoredSceneObject(sceneObject, false, false, false); // Handle attachment special case SceneObjectPart RootPrim = sceneObject.RootPart; @@ -2544,6 +2568,8 @@ namespace OpenSim.Region.Framework.Scenes // Fix up attachment Parent Local ID ScenePresence sp = GetScenePresence(sceneObject.OwnerID); + Console.WriteLine("AAAA"); + //uint parentLocalID = 0; if (sp != null) { @@ -2562,20 +2588,25 @@ namespace OpenSim.Region.Framework.Scenes //grp.SetFromAssetID(grp.RootPart.LastOwnerID); m_log.DebugFormat( "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); - + + RootPrim.RemFlag(PrimFlags.TemporaryOnRez); AttachObject( sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false); - RootPrim.RemFlag(PrimFlags.TemporaryOnRez); - grp.SendGroupFullUpdate(); + + //grp.SendGroupFullUpdate(); } else { RootPrim.RemFlag(PrimFlags.TemporaryOnRez); RootPrim.AddFlag(PrimFlags.TemporaryOnRez); } + + Console.WriteLine("BBBB"); } else { + m_log.DebugFormat("[SCENE]: Adding ordinary object {0} {1}", sceneObject.Name, sceneObject.LocalId); + AddRestoredSceneObject(sceneObject, true, false); if (!Permissions.CanObjectEntry(sceneObject.UUID, diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 2f6a0db..50feb17 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -1383,7 +1383,9 @@ namespace OpenSim.Region.Framework.Scenes // now we have a child agent in this region. Request all interesting data about other (root) agents agent.SendInitialFullUpdateToAllClients(); + Console.WriteLine("SCS 1"); agent.CrossAttachmentsIntoNewRegion(neighbourHandle, true); + Console.WriteLine("SCS 2"); // m_scene.SendKillObject(m_localId); diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 59a2f41..fa3c5eb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -216,11 +216,15 @@ namespace OpenSim.Region.Framework.Scenes /// If true, we won't persist this object until it changes /// If false, we'll persist this object immediately /// + /// + /// If true, we send updates to the client to tell it about this object + /// If false, we leave it up to the caller to do this + /// /// /// true if the object was added, false if an object with the same uuid was already in the scene /// protected internal bool AddRestoredSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { if (!alreadyPersisted) { @@ -228,8 +232,29 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.HasGroupChanged = true; } - return AddSceneObject(sceneObject, attachToBackup, true); + return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); } + +// /// +// /// Add an object into the scene that has come from storage +// /// +// /// +// /// +// /// If true, changes to the object will be reflected in its persisted data +// /// If false, the persisted data will not be changed even if the object in the scene is changed +// /// +// /// +// /// If true, we won't persist this object until it changes +// /// If false, we'll persist this object immediately +// /// +// /// +// /// true if the object was added, false if an object with the same uuid was already in the scene +// /// +// protected internal bool AddRestoredSceneObject( +// SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) +// { +// AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); +// } /// /// Add a newly created object to the scene. This will both update the scene, and send information about the @@ -611,11 +636,13 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool AttachObject( IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) { + Console.WriteLine("HERE A"); SceneObjectGroup group = GetGroupByPrim(objectLocalID); if (group != null) { if (m_parentScene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) { + Console.WriteLine("HERE -1"); // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. @@ -654,9 +681,12 @@ namespace OpenSim.Region.Framework.Scenes itemId = group.GetFromItemID(); } + Console.WriteLine("HERE 0"); m_parentScene.AttachObject(remoteClient, AttachmentPt, itemId, group); + Console.WriteLine("HERE 1"); group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); + Console.WriteLine("HERE 2"); // In case it is later dropped again, don't let // it get cleaned up // diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 602b811..ba3fde7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1494,6 +1494,10 @@ namespace OpenSim.Region.Framework.Scenes public void SendFullUpdateToClient(IClientAPI remoteClient) { + if (IsAttachment) + m_log.DebugFormat( + "[SOG]: Sending full update to client {0} for {1} {2}", remoteClient.Name, Name, LocalId); + SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); lock (m_parts) @@ -1513,8 +1517,9 @@ namespace OpenSim.Region.Framework.Scenes /// internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags) { -// m_log.DebugFormat( -// "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); + if (IsAttachment) + m_log.DebugFormat( + "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); if (m_rootPart.UUID == part.UUID) { @@ -1994,7 +1999,8 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleFullUpdateToAvatar(ScenePresence presence) { -// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); + if (IsAttachment) + m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); RootPart.AddFullUpdateToAvatar(presence); @@ -2026,7 +2032,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForFullUpdate() { -// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); + if (IsAttachment) + m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); checkAtTargets(); RootPart.ScheduleFullUpdate(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a85a4b3..ffbb427 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1259,16 +1259,17 @@ namespace OpenSim.Region.Framework.Scenes /// Tell all scene presences that they should send updates for this part to their clients /// public void AddFullUpdateToAllAvatars() - { + { ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) - { - avatars[i].SceneViewer.QueuePartForUpdate(this); - } + AddFullUpdateToAvatar(avatars[i]); } public void AddFullUpdateToAvatar(ScenePresence presence) { + if (IsAttachment) + m_log.DebugFormat("AddFullUpdateToAllAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); + presence.SceneViewer.QueuePartForUpdate(this); } @@ -1287,13 +1288,14 @@ namespace OpenSim.Region.Framework.Scenes { ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) - { - avatars[i].SceneViewer.QueuePartForUpdate(this); - } + AddTerseUpdateToAvatar(avatars[i]); } public void AddTerseUpdateToAvatar(ScenePresence presence) { + if (IsAttachment) + m_log.DebugFormat("AddTerseUpdateToAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); + presence.SceneViewer.QueuePartForUpdate(this); } @@ -2727,7 +2729,8 @@ namespace OpenSim.Region.Framework.Scenes ///
public void ScheduleFullUpdate() { -// m_log.DebugFormat("[SCENE OBJECT PART]: Scheduling full update for {0} {1}", Name, LocalId); + if (IsAttachment) + m_log.DebugFormat("[SOP]: Scheduling full update for {0} {1}", Name, LocalId); if (m_parentGroup != null) { @@ -2840,6 +2843,10 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags) { + if (IsAttachment) + m_log.DebugFormat( + "[SCENE OBJECT PART]: Sending part full update to {0} for {1} {2}", remoteClient.Name, Name, LocalId); + m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags); } @@ -2848,6 +2855,10 @@ namespace OpenSim.Region.Framework.Scenes ///
public void SendFullUpdateToAllClients() { + if (IsAttachment) + m_log.DebugFormat( + "[SCENE OBJECT PART]: Sending full update for {0} {1} for all clients", Name, LocalId); + ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) { @@ -2859,6 +2870,10 @@ namespace OpenSim.Region.Framework.Scenes public void SendFullUpdateToAllClientsExcept(UUID agentID) { + if (IsAttachment) + m_log.DebugFormat( + "[SCENE OBJECT PART]: Sending full update for {0} {1} to all clients except {2}", Name, LocalId, agentID); + ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) { @@ -2965,6 +2980,9 @@ namespace OpenSim.Region.Framework.Scenes { if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes { + if (IsAttachment) + m_log.DebugFormat("[SOP]: Sending scheduled full update for {0} {1}", Name, LocalId); + AddFullUpdateToAllAvatars(); ClearUpdateSchedule(); } diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs index e4296ef..6f2bef9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs +++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Reflection; using OpenMetaverse; using log4net; using OpenSim.Framework; @@ -39,6 +40,8 @@ namespace OpenSim.Region.Framework.Scenes { public class SceneViewer : ISceneViewer { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected ScenePresence m_presence; protected UpdateQueue m_partsUpdateQueue = new UpdateQueue(); protected Queue m_pendingObjects; @@ -60,6 +63,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void QueuePartForUpdate(SceneObjectPart part) { + if (part.IsAttachment) + m_log.DebugFormat("[SCENE VIEWER]: Queueing part {0} {1} for update", part.Name, part.LocalId); + lock (m_partsUpdateQueue) { m_partsUpdateQueue.Enqueue(part); @@ -134,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes } else if (update.LastTerseUpdateTime <= part.TimeStampTerse) { -// m_log.DebugFormat( +// m_log.DebugFormat(AddFullUpdateToAvatar // "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}", // part.Name, part.UUID, part.TimeStampTerse); diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index 3c7adf5..4e7ef51 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -12,7 +12,7 @@ - + -- cgit v1.1 From 66b4309f342d92cf7aad4a367e417cf569e244cd Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 28 May 2010 02:44:12 +0200 Subject: Apply Mike's TokenBucket fix --- .../Region/ClientStack/LindenUDP/TokenBucket.cs | 66 +++++++++------------- 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs index bdbd284..91e3d20 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs @@ -133,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP this.parent = parent; MaxBurst = maxBurst; DripRate = dripRate; - lastDrip = Environment.TickCount & Int32.MaxValue; + lastDrip = Environment.TickCount; } /// @@ -144,40 +144,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// the bucket, otherwise false public bool RemoveTokens(int amount) { - bool dummy; - return RemoveTokens(amount, out dummy); - } - - /// - /// Remove a given number of tokens from the bucket - /// - /// Number of tokens to remove from the bucket - /// True if tokens were added to the bucket - /// during this call, otherwise false - /// True if the requested number of tokens were removed from - /// the bucket, otherwise false - public bool RemoveTokens(int amount, out bool dripSucceeded) - { if (maxBurst == 0) { - dripSucceeded = true; return true; } - dripSucceeded = Drip(); - - if (content - amount >= 0) + if (amount > maxBurst) { - if (parent != null && !parent.RemoveTokens(amount)) - return false; + throw new Exception("amount " + amount + " exceeds maxBurst " + maxBurst); + } - content -= amount; - return true; + Drip(); + + if (content < amount) + { + return false; } - else + + if (parent != null && !parent.RemoveTokens(amount)) { return false; } + + content -= amount; + return true; } /// @@ -193,25 +183,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP content = maxBurst; return true; } - else - { - int now = Environment.TickCount & Int32.MaxValue; - int deltaMS = now - lastDrip; - if (deltaMS <= 0) - { - if (deltaMS < 0) - lastDrip = now; - return false; - } + int now = Environment.TickCount; + int deltaMS = now - lastDrip; + lastDrip = now; - int dripAmount = deltaMS * tokensPerMS; - - content = Math.Min(content + dripAmount, maxBurst); - lastDrip = now; + if (deltaMS <= 0) + { + return false; + } - return true; + long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content; + if (dripAmount > maxBurst) + { + dripAmount = maxBurst; } + content = (int)dripAmount; + return true; } } } -- cgit v1.1 From 7d6680b38a1220d6709cb189c0a2c430731f58cf Mon Sep 17 00:00:00 2001 From: Mike Rieker Date: Thu, 27 May 2010 21:28:47 -0400 Subject: fix hanging output throttle arithmetic had multiply overflow and subtract wrap-around errors --- .../Region/ClientStack/LindenUDP/TokenBucket.cs | 66 +++++++++------------- 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs index bdbd284..91e3d20 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs @@ -133,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP this.parent = parent; MaxBurst = maxBurst; DripRate = dripRate; - lastDrip = Environment.TickCount & Int32.MaxValue; + lastDrip = Environment.TickCount; } /// @@ -144,40 +144,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// the bucket, otherwise false public bool RemoveTokens(int amount) { - bool dummy; - return RemoveTokens(amount, out dummy); - } - - /// - /// Remove a given number of tokens from the bucket - /// - /// Number of tokens to remove from the bucket - /// True if tokens were added to the bucket - /// during this call, otherwise false - /// True if the requested number of tokens were removed from - /// the bucket, otherwise false - public bool RemoveTokens(int amount, out bool dripSucceeded) - { if (maxBurst == 0) { - dripSucceeded = true; return true; } - dripSucceeded = Drip(); - - if (content - amount >= 0) + if (amount > maxBurst) { - if (parent != null && !parent.RemoveTokens(amount)) - return false; + throw new Exception("amount " + amount + " exceeds maxBurst " + maxBurst); + } - content -= amount; - return true; + Drip(); + + if (content < amount) + { + return false; } - else + + if (parent != null && !parent.RemoveTokens(amount)) { return false; } + + content -= amount; + return true; } /// @@ -193,25 +183,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP content = maxBurst; return true; } - else - { - int now = Environment.TickCount & Int32.MaxValue; - int deltaMS = now - lastDrip; - if (deltaMS <= 0) - { - if (deltaMS < 0) - lastDrip = now; - return false; - } + int now = Environment.TickCount; + int deltaMS = now - lastDrip; + lastDrip = now; - int dripAmount = deltaMS * tokensPerMS; - - content = Math.Min(content + dripAmount, maxBurst); - lastDrip = now; + if (deltaMS <= 0) + { + return false; + } - return true; + long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content; + if (dripAmount > maxBurst) + { + dripAmount = maxBurst; } + content = (int)dripAmount; + return true; } } } -- cgit v1.1 From c7d812802fcb2531c49f0fe4f4971571f332183d Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 28 May 2010 18:49:32 +0100 Subject: Adjust Scene.DeleteAllSceneObjects() to not delete objects attached to avatars. This is going to be the right behaviour in all cases, I should think. This means that avatars in region when an oar is loaded do not lose their attachments --- OpenSim/Region/Framework/Scenes/Scene.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index dd2d2cc..f8ca047 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1908,7 +1908,7 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Delete every object from the scene + /// Delete every object from the scene. This does not include attachments worn by avatars. /// public void DeleteAllSceneObjects() { @@ -1919,7 +1919,11 @@ namespace OpenSim.Region.Framework.Scenes foreach (EntityBase e in entities) { if (e is SceneObjectGroup) - DeleteSceneObject((SceneObjectGroup)e, false); + { + SceneObjectGroup sog = (SceneObjectGroup)e; + if (!sog.IsAttachment) + DeleteSceneObject((SceneObjectGroup)e, false); + } } } } -- cgit v1.1 From e7bf6afd3afa5fc4760b417e0c0e079f23d20f59 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 29 May 2010 05:14:18 +0200 Subject: Get the user's DOB back from the server response properly. --- OpenSim/Services/Interfaces/IUserAccountService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/Interfaces/IUserAccountService.cs b/OpenSim/Services/Interfaces/IUserAccountService.cs index e316731..09d1d87 100644 --- a/OpenSim/Services/Interfaces/IUserAccountService.cs +++ b/OpenSim/Services/Interfaces/IUserAccountService.cs @@ -91,7 +91,7 @@ namespace OpenSim.Services.Interfaces UserTitle = kvp["UserTitle"].ToString(); if (kvp.ContainsKey("Created")) - Convert.ToInt32(kvp["Created"].ToString()); + Created = Convert.ToInt32(kvp["Created"].ToString()); if (kvp.ContainsKey("ServiceURLs") && kvp["ServiceURLs"] != null) { ServiceURLs = new Dictionary(); -- cgit v1.1 From 2f409116db570be77fc75df188a4044250dce226 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 29 May 2010 01:03:59 -0700 Subject: Stop IGridService from throwing a fatal exception when an IPEndPoint cannot be resolved, and add some handlers to deal with this cleanly; a condition was observed on OSGrid where a neighbouring region with an invalid (unresolveable) hostname would prevent a region from starting. This is bad. --- .../EntityTransfer/EntityTransferModule.cs | 31 ++++++++++++++-------- .../Hypergrid/GatekeeperServiceConnector.cs | 14 ++++++++-- .../Connectors/Land/LandServiceConnector.cs | 2 ++ .../Neighbour/NeighbourServiceConnector.cs | 4 ++- .../SimianGrid/SimianGridServiceConnector.cs | 4 ++- .../Simulation/SimulationServiceConnector.cs | 8 ++++-- OpenSim/Services/Interfaces/IGridService.cs | 8 ++++-- OpenSim/Services/LLLoginService/LLLoginResponse.cs | 1 + 8 files changed, 53 insertions(+), 19 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index ef37f63..dc1025d 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -261,7 +261,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, // it's actually doing a lot of work. IPEndPoint endPoint = finalDestination.ExternalEndPoint; - if (endPoint.Address != null) + if (endPoint != null && endPoint.Address != null) { // Fixing a bug where teleporting while sitting results in the avatar ending up removed from // both regions @@ -825,15 +825,19 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); IEventQueue eq = agent.Scene.RequestModuleInterface(); - if (eq != null) - { - eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, - capsPath, agent.UUID, agent.ControllingClient.SessionId); - } - else + IPEndPoint neighbourExternal = neighbourRegion.ExternalEndPoint; + if (neighbourExternal != null) { - agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, - capsPath); + if (eq != null) + { + eq.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourExternal, + capsPath, agent.UUID, agent.ControllingClient.SessionId); + } + else + { + agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourExternal, + capsPath); + } } if (!WaitForCallback(agent.UUID)) @@ -906,10 +910,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.child = true; agent.Appearance = sp.Appearance; - InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; - d.BeginInvoke(sp, agent, region, region.ExternalEndPoint, true, + IPEndPoint external = region.ExternalEndPoint; + if (external != null) + { + InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; + d.BeginInvoke(sp, agent, region, external, true, InformClientOfNeighbourCompleted, d); + } } #endregion @@ -1038,6 +1046,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; try { + //neighbour.ExternalEndPoint may return null, which will be caught d.BeginInvoke(sp, cagents[count], neighbour, neighbour.ExternalEndPoint, newAgent, InformClientOfNeighbourCompleted, d); diff --git a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs index c426bba..6f159a0 100644 --- a/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/GatekeeperServiceConnector.cs @@ -87,7 +87,12 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("link_region", paramList); - string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"; + IPEndPoint ext = info.ExternalEndPoint; + string uri = ""; + if (ext != null) + { + uri = "http://" + ext.Address + ":" + info.HttpPort + "/"; + } //m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: Linking to " + uri); XmlRpcResponse response = null; try @@ -189,7 +194,12 @@ namespace OpenSim.Services.Connectors.Hypergrid paramList.Add(hash); XmlRpcRequest request = new XmlRpcRequest("get_region", paramList); - string uri = "http://" + gatekeeper.ExternalEndPoint.Address + ":" + gatekeeper.HttpPort + "/"; + IPEndPoint ext = gatekeeper.ExternalEndPoint; + string uri = ""; + if (ext != null) + { + uri = "http://" + ext.Address + ":" + gatekeeper.HttpPort + "/"; + } m_log.Debug("[GATEKEEPER SERVICE CONNECTOR]: contacting " + uri); XmlRpcResponse response = null; try diff --git a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs index 06bc11c..0223a77 100644 --- a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs @@ -83,6 +83,8 @@ namespace OpenSim.Services.Connectors if (info != null) // just to be sure { XmlRpcRequest request = new XmlRpcRequest("land_data", paramList); + + //Possible nullref from info.externalendpoint will be caught here string uri = "http://" + info.ExternalEndPoint.Address + ":" + info.HttpPort + "/"; XmlRpcResponse response = request.Send(uri, 10000); if (response.IsFault) diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs index 0a982f8..daf0439 100644 --- a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs +++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs @@ -87,7 +87,9 @@ namespace OpenSim.Services.Connectors public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion) { - string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/"; + IPEndPoint ext = region.ExternalEndPoint; + if (ext == null) return false; + string uri = "http://" + ext.Address + ":" + region.HttpPort + "/region/" + thisRegion.RegionID + "/"; //m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri); WebRequest HelloNeighbourRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 3a61226..57924b7 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -104,6 +104,8 @@ namespace OpenSim.Services.Connectors.SimianGrid public string RegisterRegion(UUID scopeID, GridRegion regionInfo) { + IPEndPoint ext = regionInfo.ExternalEndPoint; + if (ext == null) return "Region registration for " + regionInfo.RegionName + " failed: Could not resolve EndPoint"; Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0); Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0); @@ -114,7 +116,7 @@ namespace OpenSim.Services.Connectors.SimianGrid { "ServerURI", OSD.FromString(regionInfo.ServerURI) }, { "InternalAddress", OSD.FromString(regionInfo.InternalEndPoint.Address.ToString()) }, { "InternalPort", OSD.FromInteger(regionInfo.InternalEndPoint.Port) }, - { "ExternalAddress", OSD.FromString(regionInfo.ExternalEndPoint.Address.ToString()) }, + { "ExternalAddress", OSD.FromString(ext.Address.ToString()) }, { "ExternalPort", OSD.FromInteger(regionInfo.ExternalEndPoint.Port) }, { "MapTexture", OSD.FromUUID(regionInfo.TerrainImage) }, { "Access", OSD.FromInteger(regionInfo.Access) }, diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 8e0063b..748faef 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -348,9 +348,11 @@ namespace OpenSim.Services.Connectors.Simulation public bool RetrieveAgent(GridRegion destination, UUID id, out IAgentData agent) { + IPEndPoint ext = destination.ExternalEndPoint; agent = null; + if (ext == null) return false; // Eventually, we want to use a caps url instead of the agentID - string uri = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; + string uri = "http://" + ext.Address + ":" + destination.HttpPort + AgentPath() + id + "/" + destination.RegionID.ToString() + "/"; //Console.WriteLine(" >>> DoRetrieveRootAgentCall <<< " + uri); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); @@ -514,8 +516,10 @@ namespace OpenSim.Services.Connectors.Simulation public bool CreateObject(GridRegion destination, ISceneObject sog, bool isLocalCall) { + IPEndPoint ext = destination.ExternalEndPoint; + if (ext == null) return false; string uri - = "http://" + destination.ExternalEndPoint.Address + ":" + destination.HttpPort + ObjectPath() + sog.UUID + "/"; + = "http://" + ext.Address + ":" + destination.HttpPort + ObjectPath() + sog.UUID + "/"; //m_log.Debug(" >>> DoCreateObjectCall <<< " + uri); WebRequest ObjectCreateRequest = WebRequest.Create(uri); diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index e55b633..94cee57 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -259,9 +259,13 @@ namespace OpenSim.Services.Interfaces } catch (SocketException e) { - throw new Exception( + /*throw new Exception( "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" + - e + "' attached to this exception", e); + e + "' attached to this exception", e);*/ + // Don't throw a fatal exception here, instead, return Null and handle it in the caller. + // Reason is, on systems such as OSgrid it has occured that known hostnames stop + // resolving and thus make surrounding regions crash out with this exception. + return null; } return new IPEndPoint(ia, m_internalEndPoint.Port); diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index edf41bc..6a2cbeb 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -327,6 +327,7 @@ namespace OpenSim.Services.LLLoginService private void FillOutRegionData(GridRegion destination) { IPEndPoint endPoint = destination.ExternalEndPoint; + if (endPoint == null) return; SimAddress = endPoint.Address.ToString(); SimPort = (uint)endPoint.Port; RegionX = (uint)destination.RegionLocX; -- cgit v1.1 From e3dac1292ef000daadda3e264354d8df0fc77c22 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 29 May 2010 02:10:34 -0700 Subject: Implement suspended updates - When an operation is occurring on lots of prims in a single group, don't schedule any updates until the operation has completed. This makes things like llSetAlpha(LINK_SET,0.0,ALL_SIDES); a *lot* faster, more efficient and less buggy, and also makes unlinking a lot better. Linking is still treacherous.. this needs to be analysed. --- OpenSim/Region/Framework/ModuleLoader.cs | 3 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 47 ++++++-- .../Region/Framework/Scenes/SceneObjectGroup.cs | 17 +++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 8 +- .../Shared/Api/Implementation/LSL_Api.cs | 132 +++++++++++++++++---- 5 files changed, 168 insertions(+), 39 deletions(-) diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs index 23be9c2..69ba2042 100644 --- a/OpenSim/Region/Framework/ModuleLoader.cs +++ b/OpenSim/Region/Framework/ModuleLoader.cs @@ -226,7 +226,8 @@ namespace OpenSim.Region.Framework "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e); // justincc: Right now this is fatal to really get the user's attention - throw e; + // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to? + //throw e; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index d4658ec..445c2c8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1499,10 +1499,13 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void LinkObjects(SceneObjectPart root, List children) { + SceneObjectGroup parentGroup = root.ParentGroup; + if (parentGroup == null) return; Monitor.Enter(m_updateLock); + try { - SceneObjectGroup parentGroup = root.ParentGroup; + parentGroup.areUpdatesSuspended = true; List childGroups = new List(); if (parentGroup != null) @@ -1541,12 +1544,12 @@ namespace OpenSim.Region.Framework.Scenes // occur on link to invoke this elsewhere (such as object selection) parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); parentGroup.TriggerScriptChangedEvent(Changed.LINK); - parentGroup.HasGroupChanged = true; - parentGroup.ScheduleGroupForFullUpdate(); - } finally { + parentGroup.areUpdatesSuspended = false; + parentGroup.HasGroupChanged = true; + parentGroup.ScheduleGroupForFullUpdate(); Monitor.Exit(m_updateLock); } } @@ -1583,11 +1586,22 @@ namespace OpenSim.Region.Framework.Scenes } } - foreach (SceneObjectPart child in childParts) + if (childParts.Count > 0) { - // Unlink all child parts from their groups - // - child.ParentGroup.DelinkFromGroup(child, true); + try + { + childParts[0].ParentGroup.areUpdatesSuspended = true; + foreach (SceneObjectPart child in childParts) + { + // Unlink all child parts from their groups + // + child.ParentGroup.DelinkFromGroup(child, true); + } + } + finally + { + childParts[0].ParentGroup.areUpdatesSuspended = false; + } } foreach (SceneObjectPart root in rootParts) @@ -1611,10 +1625,21 @@ namespace OpenSim.Region.Framework.Scenes if (numChildren > 1) sendEventsToRemainder = false; - foreach (SceneObjectPart p in newSet) + if (newSet.Count > 0) { - if (p != group.RootPart) - group.DelinkFromGroup(p, sendEventsToRemainder); + try + { + newSet[0].ParentGroup.areUpdatesSuspended = true; + foreach (SceneObjectPart p in newSet) + { + if (p != group.RootPart) + group.DelinkFromGroup(p, sendEventsToRemainder); + } + } + finally + { + newSet[0].ParentGroup.areUpdatesSuspended = false; + } } // If there is more than one prim remaining, we diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index cee2be3..9ebb168 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -109,9 +109,26 @@ namespace OpenSim.Region.Framework.Scenes private long m_maxPersistTime = 0; private long m_minPersistTime = 0; private Random m_rand; + private bool m_suspendUpdates; private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); + public bool areUpdatesSuspended + { + get + { + return m_suspendUpdates; + } + set + { + m_suspendUpdates = value; + if (!value) + { + QueueForUpdateCheck(); + } + } + } + public void lockPartsForRead(bool locked) { if (locked) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index c84596b..6e73b65 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2724,7 +2724,10 @@ namespace OpenSim.Region.Framework.Scenes if (m_parentGroup != null) { - m_parentGroup.QueueForUpdateCheck(); + if (!m_parentGroup.areUpdatesSuspended) + { + m_parentGroup.QueueForUpdateCheck(); + } } int timeNow = Util.UnixTimeSinceEpoch(); @@ -4450,8 +4453,9 @@ namespace OpenSim.Region.Framework.Scenes { m_shape.TextureEntry = textureEntry; TriggerScriptChangedEvent(Changed.TEXTURE); - + m_updateFlag = 1; ParentGroup.HasGroupChanged = true; + //This is madness.. //ParentGroup.ScheduleGroupForFullUpdate(); //This is sparta diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 68f6e7b..bb02fa3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1649,9 +1649,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - SetAlpha(part, alpha, face); + if (parts.Count > 0) + { + try + { + parts[0].ParentGroup.areUpdatesSuspended = true; + foreach (SceneObjectPart part in parts) + SetAlpha(part, alpha, face); + } + finally + { + parts[0].ParentGroup.areUpdatesSuspended = false; + } + } } protected void SetAlpha(SceneObjectPart part, double alpha, int face) @@ -1816,10 +1826,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - SetTexture(part, texture, face); - + if (parts.Count > 0) + { + try + { + parts[0].ParentGroup.areUpdatesSuspended = true; + foreach (SceneObjectPart part in parts) + SetTexture(part, texture, face); + } + finally + { + parts[0].ParentGroup.areUpdatesSuspended = false; + } + } ScriptSleep(200); } @@ -3661,9 +3680,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLinkColor(int linknumber, LSL_Vector color, int face) { List parts = GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); + if (parts.Count > 0) + { + try + { + parts[0].ParentGroup.areUpdatesSuspended = true; + foreach (SceneObjectPart part in parts) + part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); + } + finally + { + parts[0].ParentGroup.areUpdatesSuspended = false; + } + } } public void llCreateLink(string target, int parent) @@ -3776,10 +3805,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Restructuring Multiple Prims. List parts = new List(parentPrim.Children.Values); parts.Remove(parentPrim.RootPart); - foreach (SceneObjectPart part in parts) + if (parts.Count > 0) { - parentPrim.DelinkFromGroup(part.LocalId, true); + try + { + parts[0].ParentGroup.areUpdatesSuspended = true; + foreach (SceneObjectPart part in parts) + { + parentPrim.DelinkFromGroup(part.LocalId, true); + } + } + finally + { + parts[0].ParentGroup.areUpdatesSuspended = false; + } } + parentPrim.HasGroupChanged = true; parentPrim.ScheduleGroupForFullUpdate(); parentPrim.TriggerScriptChangedEvent(Changed.LINK); @@ -3788,11 +3829,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { SceneObjectPart newRoot = parts[0]; parts.Remove(newRoot); - foreach (SceneObjectPart part in parts) + + try { - part.UpdateFlag = 0; - newRoot.ParentGroup.LinkToGroup(part.ParentGroup); + parts[0].ParentGroup.areUpdatesSuspended = true; + foreach (SceneObjectPart part in parts) + { + part.UpdateFlag = 0; + newRoot.ParentGroup.LinkToGroup(part.ParentGroup); + } } + finally + { + parts[0].ParentGroup.areUpdatesSuspended = false; + } + + newRoot.ParentGroup.HasGroupChanged = true; newRoot.ParentGroup.ScheduleGroupForFullUpdate(); } @@ -3818,11 +3870,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = new List(parentPrim.Children.Values); parts.Remove(parentPrim.RootPart); - - foreach (SceneObjectPart part in parts) + if (parts.Count > 0) { - parentPrim.DelinkFromGroup(part.LocalId, true); - parentPrim.TriggerScriptChangedEvent(Changed.LINK); + try + { + parts[0].ParentGroup.areUpdatesSuspended = true; + foreach (SceneObjectPart part in parts) + { + parentPrim.DelinkFromGroup(part.LocalId, true); + parentPrim.TriggerScriptChangedEvent(Changed.LINK); + } + } + finally + { + parts[0].ParentGroup.areUpdatesSuspended = false; + } } parentPrim.HasGroupChanged = true; parentPrim.ScheduleGroupForFullUpdate(); @@ -5664,10 +5726,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); - - foreach (var part in parts) + if (parts.Count > 0) { - SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); + try + { + parts[0].ParentGroup.areUpdatesSuspended = true; + foreach (var part in parts) + { + SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); + } + } + finally + { + parts[0].ParentGroup.areUpdatesSuspended = false; + } } } @@ -7068,9 +7140,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - SetPrimParams(part, rules); + if (parts.Count>0) + { + try + { + parts[0].ParentGroup.areUpdatesSuspended = true; + foreach (SceneObjectPart part in parts) + SetPrimParams(part, rules); + } + finally + { + parts[0].ParentGroup.areUpdatesSuspended = false; + } + } } public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) -- cgit v1.1 From 31439293ccdb5df914dc13287a8f178529fccb6b Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 29 May 2010 03:56:34 -0700 Subject: Meta7 Communities : Authorization service added, skeleton, not yet functional --- .../Services/Meta7Communities/Meta7Communities.cs | 59 ++++++++++++++++++++++ prebuild.xml | 32 ++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 OpenSim/Services/Meta7Communities/Meta7Communities.cs diff --git a/OpenSim/Services/Meta7Communities/Meta7Communities.cs b/OpenSim/Services/Meta7Communities/Meta7Communities.cs new file mode 100644 index 0000000..32f5c32 --- /dev/null +++ b/OpenSim/Services/Meta7Communities/Meta7Communities.cs @@ -0,0 +1,59 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using Nini.Config; +using log4net; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Data; +using OpenSim.Services.Interfaces; +using OpenSim.Services.AuthorizationService; +using OpenMetaverse; + +namespace OpenSim.Services.Meta7Communities +{ + public class Meta7Communities : AuthorizationServiceBase, IAuthorizationService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + public Meta7Communities(IConfigSource config) + : base(config) + { + m_log.Info("[Communities]: Local Authorization service enabled"); + } + + public bool IsAuthorizedForRegion(string userID, string regionID, out string message) + { + message = "NO GOATS"; + return false; + } + } +} diff --git a/prebuild.xml b/prebuild.xml index fb01d51..7e92454 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1033,6 +1033,38 @@ + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + + + -- cgit v1.1 From 84e30bee6dce30853cf4438382b39e65ec3fa622 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 29 May 2010 12:34:02 +0200 Subject: Revert "Meta7 Communities : Authorization service added, skeleton, not yet functional" This reverts commit 31439293ccdb5df914dc13287a8f178529fccb6b. --- .../Services/Meta7Communities/Meta7Communities.cs | 59 ---------------------- prebuild.xml | 32 ------------ 2 files changed, 91 deletions(-) delete mode 100644 OpenSim/Services/Meta7Communities/Meta7Communities.cs diff --git a/OpenSim/Services/Meta7Communities/Meta7Communities.cs b/OpenSim/Services/Meta7Communities/Meta7Communities.cs deleted file mode 100644 index 32f5c32..0000000 --- a/OpenSim/Services/Meta7Communities/Meta7Communities.cs +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using Nini.Config; -using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Console; -using OpenSim.Data; -using OpenSim.Services.Interfaces; -using OpenSim.Services.AuthorizationService; -using OpenMetaverse; - -namespace OpenSim.Services.Meta7Communities -{ - public class Meta7Communities : AuthorizationServiceBase, IAuthorizationService - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - public Meta7Communities(IConfigSource config) - : base(config) - { - m_log.Info("[Communities]: Local Authorization service enabled"); - } - - public bool IsAuthorizedForRegion(string userID, string regionID, out string message) - { - message = "NO GOATS"; - return false; - } - } -} diff --git a/prebuild.xml b/prebuild.xml index 7e92454..fb01d51 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1033,38 +1033,6 @@ - - - - ../../../bin/ - - - - - ../../../bin/ - - - - ../../../bin/ - - - - - - - - - - - - - - - - - - - -- cgit v1.1 From 59a536743354ffaa12b23378f559d2d59d7d5304 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 30 May 2010 13:46:05 +0200 Subject: Changes OSSL Api permissions for the case of UUID list. In 0.6.9, the UUIDs would be the IDs of the prim owners in whose prims these functions would run. This changes it so the UUID is the SCRIPT CREATOR instead. Further, osfunctions limited by uuid will not run if the creator and owner differ and the owner has mod rights on the script. There is still a danger in passing moodifiable scripts to others, as they can insert a harmful function, then remove the mod rights to make it runnable. As before, care needs to be taken, but where it was modable prims that were the risk before, modable scripts are the weak spot now. In cases where prim owner == script creator == script owner, nothing will change. --- .../Shared/Api/Implementation/OSSL_Api.cs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 942e4ef..8cfa833 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -278,10 +278,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (!m_FunctionPerms[function].Contains(UUID.Zero)) { - if (!m_FunctionPerms[function].Contains(m_host.OwnerID)) + TaskInventoryItem ti = m_host.Inventory.GetInventoryItem(m_itemID); + if (ti == null) + { + OSSLError( + String.Format("{0} permission error. Can't find script in prim inventory.", + function)); + } + if (!m_FunctionPerms[function].Contains(ti.CreatorID)) OSSLError( - String.Format("{0} permission denied. Prim owner is not in the list of users allowed to execute this function.", + String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function.", function)); + if (ti.CreatorID != ti.OwnerID) + { + if ((ti.CurrentPermissions & (uint)PermissionMask.Modify) != 0) + OSSLError( + String.Format("{0} permission denied. Script permissions error.", + function)); + + } } } } @@ -2141,4 +2156,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } -} \ No newline at end of file +} -- cgit v1.1 From 890f3cc54cc57883a110b372530bf2a7d5b37fff Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 30 May 2010 15:46:54 +0200 Subject: Changes osFunction permissions again. Allow_ with a list of UUIDs now again refers to prim OWNERS. A new option set, Creators_, is added to allow selection by script creator. For existing installs, this means no functional change. The warning from my prior commit doesn't apply anymore. --- .../Shared/Api/Implementation/OSSL_Api.cs | 67 ++++++++++++++++------ bin/OpenSim.ini.example | 6 ++ 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 8cfa833..2e0456e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -105,6 +105,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // modification of user data, or allows the compromise of // sensitive data by design. + class FunctionPerms + { + public List AllowedCreators; + public List AllowedOwners; + + public FunctionPerms() + { + AllowedCreators = new List(); + AllowedOwners = new List(); + } + } + [Serializable] public class OSSL_Api : MarshalByRefObject, IOSSL_Api, IScriptApi { @@ -117,7 +129,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; internal float m_ScriptDelayFactor = 1.0f; internal float m_ScriptDistanceFactor = 1.0f; - internal Dictionary > m_FunctionPerms = new Dictionary >(); + internal Dictionary m_FunctionPerms = new Dictionary(); public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) { @@ -217,31 +229,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_FunctionPerms.ContainsKey(function)) { - string perm = m_ScriptEngine.Config.GetString("Allow_" + function, ""); - if (perm == "") + FunctionPerms perms = new FunctionPerms(); + m_FunctionPerms[function] = perms; + + string ownerPerm = m_ScriptEngine.Config.GetString("Allow_" + function, ""); + string creatorPerm = m_ScriptEngine.Config.GetString("Creators_" + function, ""); + if (ownerPerm == "" && creatorPerm == "") { - m_FunctionPerms[function] = null; // a null value is default + // Default behavior + perms.AllowedOwners = null; + perms.AllowedCreators = null; } else { bool allowed; - if (bool.TryParse(perm, out allowed)) + if (bool.TryParse(ownerPerm, out allowed)) { // Boolean given if (allowed) { - m_FunctionPerms[function] = new List(); - m_FunctionPerms[function].Add(UUID.Zero); + // Allow globally + perms.AllowedOwners.Add(UUID.Zero); } - else - m_FunctionPerms[function] = new List(); // Empty list = none } else { - m_FunctionPerms[function] = new List(); + string[] ids = ownerPerm.Split(new char[] {','}); + foreach (string id in ids) + { + string current = id.Trim(); + UUID uuid; + + if (UUID.TryParse(current, out uuid)) + { + if (uuid != UUID.Zero) + perms.AllowedOwners.Add(uuid); + } + } - string[] ids = perm.Split(new char[] {','}); + ids = creatorPerm.Split(new char[] {','}); foreach (string id in ids) { string current = id.Trim(); @@ -250,7 +277,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (UUID.TryParse(current, out uuid)) { if (uuid != UUID.Zero) - m_FunctionPerms[function].Add(uuid); + perms.AllowedCreators.Add(uuid); } } } @@ -266,8 +293,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // // To allow use by anyone, the list contains UUID.Zero // - if (m_FunctionPerms[function] == null) // No list = true + if (m_FunctionPerms[function].AllowedOwners == null) { + // Allow / disallow by threat level if (level > m_MaxThreatLevel) OSSLError( String.Format( @@ -276,8 +304,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - if (!m_FunctionPerms[function].Contains(UUID.Zero)) + if (!m_FunctionPerms[function].AllowedOwners.Contains(UUID.Zero)) { + // Not anyone. Do detailed checks + if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID)) + { + // prim owner is in the list of allowed owners + return; + } + TaskInventoryItem ti = m_host.Inventory.GetInventoryItem(m_itemID); if (ti == null) { @@ -285,9 +320,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api String.Format("{0} permission error. Can't find script in prim inventory.", function)); } - if (!m_FunctionPerms[function].Contains(ti.CreatorID)) + if (!m_FunctionPerms[function].AllowedCreators.Contains(ti.CreatorID)) OSSLError( - String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function.", + String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.", function)); if (ti.CreatorID != ti.OwnerID) { diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index e67c8bd..0142a0d 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -985,6 +985,12 @@ ; Comma separated list of UUIDS allows the function for that list of UUIDS ; Allow_osSetRegionWaterHeight = 888760cb-a3cf-43ac-8ea4-8732fd3ee2bb + ; You can also use script creators as the uuid + ; Creators_osSetRegionWaterHeight = , ... + + ; If both Allow_ and Creators_ are given, effective permissions + ; are the union of the two. + ; Allow for llCreateLink and llBreakLink to work without asking for permission ; only enable this in a trusted environment otherwise you may be subject to hijacking ; AutomaticLinkPermission = false -- cgit v1.1 From 992efdc28325fb87776c9bac777342a0379ebe8d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 31 May 2010 01:02:04 +0200 Subject: Fix a nullref in EventManager caused by RegionReady not setting the scene --- .../OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index c653e98..672109b 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -146,6 +146,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30); c.Sender = null; c.SenderUUID = UUID.Zero; + c.Scene = m_scene; m_log.InfoFormat("[RegionReady]: Region \"{0}\" is ready: \"{1}\" on channel {2}", m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); -- cgit v1.1 From bbb4d6e4c934cd25615c98f2ee4500a5d28fa701 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 31 May 2010 01:02:04 +0200 Subject: Fix a nullref in EventManager caused by RegionReady not setting the scene --- .../OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index c653e98..672109b 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -146,6 +146,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady c.Position = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 30); c.Sender = null; c.SenderUUID = UUID.Zero; + c.Scene = m_scene; m_log.InfoFormat("[RegionReady]: Region \"{0}\" is ready: \"{1}\" on channel {2}", m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); -- cgit v1.1 From 6c1665bf46f691f83e93561cfbcdcd4d3f3bd954 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 31 May 2010 08:38:41 -0700 Subject: Fix casting in llParcelMediaCommandList so that it actually, you know, works --- .../Shared/Api/Implementation/LSL_Api.cs | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index bb02fa3..d0f245b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9046,17 +9046,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api int width = 0; int height = 0; - ParcelMediaCommandEnum? commandToSend = null; + uint commandToSend = 0; float time = 0.0f; // default is from start ScenePresence presence = null; for (int i = 0; i < commandList.Data.Length; i++) { - ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; + uint command = (uint)(commandList.GetLSLIntegerItem(i)); switch (command) { - case ParcelMediaCommandEnum.Agent: + case (uint)ParcelMediaCommandEnum.Agent: // we send only to one agent if ((i + 1) < commandList.Length) { @@ -9073,25 +9073,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Loop: + case (uint)ParcelMediaCommandEnum.Loop: loop = 1; commandToSend = command; update = true; //need to send the media update packet to set looping break; - case ParcelMediaCommandEnum.Play: + case (uint)ParcelMediaCommandEnum.Play: loop = 0; commandToSend = command; update = true; //need to send the media update packet to make sure it doesn't loop break; - case ParcelMediaCommandEnum.Pause: - case ParcelMediaCommandEnum.Stop: - case ParcelMediaCommandEnum.Unload: + case (uint)ParcelMediaCommandEnum.Pause: + case (uint)ParcelMediaCommandEnum.Stop: + case (uint)ParcelMediaCommandEnum.Unload: commandToSend = command; break; - case ParcelMediaCommandEnum.Url: + case (uint)ParcelMediaCommandEnum.Url: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) @@ -9104,7 +9104,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Texture: + case (uint)ParcelMediaCommandEnum.Texture: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) @@ -9117,7 +9117,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Time: + case (uint)ParcelMediaCommandEnum.Time: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Float) @@ -9129,7 +9129,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.AutoAlign: + case (uint)ParcelMediaCommandEnum.AutoAlign: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Integer) @@ -9143,7 +9143,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Type: + case (uint)ParcelMediaCommandEnum.Type: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) @@ -9156,7 +9156,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Desc: + case (uint)ParcelMediaCommandEnum.Desc: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) @@ -9169,7 +9169,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Size: + case (uint)ParcelMediaCommandEnum.Size: if ((i + 2) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Integer) @@ -9239,7 +9239,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - if (commandToSend != null) + if (commandToSend != 0) { // the commandList contained a start/stop/... command, too if (presence == null) -- cgit v1.1 From 4be13b1a42f2899c6d2c985777a7501d59b0e4a5 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 31 May 2010 08:38:41 -0700 Subject: Fix casting in llParcelMediaCommandList so that it actually, you know, works --- .../Shared/Api/Implementation/LSL_Api.cs | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 75dd615..8c7cc34 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8925,17 +8925,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api int width = 0; int height = 0; - ParcelMediaCommandEnum? commandToSend = null; + uint commandToSend = 0; float time = 0.0f; // default is from start ScenePresence presence = null; for (int i = 0; i < commandList.Data.Length; i++) { - ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; + uint command = (uint)(commandList.GetLSLIntegerItem(i)); switch (command) { - case ParcelMediaCommandEnum.Agent: + case (uint)ParcelMediaCommandEnum.Agent: // we send only to one agent if ((i + 1) < commandList.Length) { @@ -8952,25 +8952,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Loop: + case (uint)ParcelMediaCommandEnum.Loop: loop = 1; commandToSend = command; update = true; //need to send the media update packet to set looping break; - case ParcelMediaCommandEnum.Play: + case (uint)ParcelMediaCommandEnum.Play: loop = 0; commandToSend = command; update = true; //need to send the media update packet to make sure it doesn't loop break; - case ParcelMediaCommandEnum.Pause: - case ParcelMediaCommandEnum.Stop: - case ParcelMediaCommandEnum.Unload: + case (uint)ParcelMediaCommandEnum.Pause: + case (uint)ParcelMediaCommandEnum.Stop: + case (uint)ParcelMediaCommandEnum.Unload: commandToSend = command; break; - case ParcelMediaCommandEnum.Url: + case (uint)ParcelMediaCommandEnum.Url: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) @@ -8983,7 +8983,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Texture: + case (uint)ParcelMediaCommandEnum.Texture: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) @@ -8996,7 +8996,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Time: + case (uint)ParcelMediaCommandEnum.Time: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Float) @@ -9008,7 +9008,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.AutoAlign: + case (uint)ParcelMediaCommandEnum.AutoAlign: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Integer) @@ -9022,7 +9022,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Type: + case (uint)ParcelMediaCommandEnum.Type: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) @@ -9035,7 +9035,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Desc: + case (uint)ParcelMediaCommandEnum.Desc: if ((i + 1) < commandList.Length) { if (commandList.Data[i + 1] is LSL_String) @@ -9048,7 +9048,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; - case ParcelMediaCommandEnum.Size: + case (uint)ParcelMediaCommandEnum.Size: if ((i + 2) < commandList.Length) { if (commandList.Data[i + 1] is LSL_Integer) @@ -9116,7 +9116,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - if (commandToSend != null) + if (commandToSend != 0) { // the commandList contained a start/stop/... command, too if (presence == null) -- cgit v1.1 From d4b4cbf5a5fead727b5e2e48f69d2016eb942cff Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 31 May 2010 19:00:02 +0200 Subject: Fix create selection getting overwritten by multiple updates for the same prim. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 4 ++-- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 9 ++++++++- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 51cc763..fe8475a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -4561,11 +4561,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (recipientID == data.OwnerID) { - if ((data.Flags & PrimFlags.CreateSelected) != 0) + if (data.CreateSelected) { // Only send this flag once, then unset it flags |= PrimFlags.CreateSelected; - data.Flags &= ~PrimFlags.CreateSelected; + data.CreateSelected = false; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 445c2c8..5fbc658 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1542,7 +1542,7 @@ namespace OpenSim.Region.Framework.Scenes // We need to explicitly resend the newly link prim's object properties since no other actions // occur on link to invoke this elsewhere (such as object selection) - parentGroup.RootPart.AddFlag(PrimFlags.CreateSelected); + parentGroup.RootPart.CreateSelected = true; parentGroup.TriggerScriptChangedEvent(Changed.LINK); } finally diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 9ebb168..509ec01 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2486,7 +2486,7 @@ namespace OpenSim.Region.Framework.Scenes linkPart.LinkNum = 2; linkPart.SetParent(this); - linkPart.AddFlag(PrimFlags.CreateSelected); + linkPart.CreateSelected = true; //if (linkPart.PhysActor != null) //{ diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 6e73b65..2f4191d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -388,7 +388,6 @@ namespace OpenSim.Region.Framework.Scenes // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log _flags = 0; - _flags |= PrimFlags.CreateSelected; TrimPermissions(); //m_undo = new UndoStack(ParentGroup.GetSceneMaxUndo()); @@ -418,6 +417,7 @@ namespace OpenSim.Region.Framework.Scenes private PrimFlags _flags = 0; private DateTime m_expires; private DateTime m_rezzed; + private bool m_createSelected = true; public UUID CreatorID { @@ -978,6 +978,13 @@ namespace OpenSim.Region.Framework.Scenes set { m_updateFlag = value; } } + [XmlIgnore] + public bool CreateSelected + { + get { return m_createSelected; } + set { m_createSelected = value; } + } + #endregion //--------------- diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index bb02fa3..228ab6d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3742,7 +3742,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } parentPrim.TriggerScriptChangedEvent(Changed.LINK); - parentPrim.RootPart.AddFlag(PrimFlags.CreateSelected); + parentPrim.RootPart.CreateSelected = true; parentPrim.HasGroupChanged = true; parentPrim.ScheduleGroupForFullUpdate(); -- cgit v1.1 From 70f779041334e7cf3642c334e9800362afde7895 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 1 Jun 2010 01:07:46 +0200 Subject: Split GetAxisAlignedBoundingBox into two methods to allow calculation of combined bounding boxes and offsets --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 509ec01..4203ba9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -794,9 +794,15 @@ namespace OpenSim.Region.Framework.Scenes /// offsetHeight is the offset in the Z axis from the centre of the bounding box to the centre of the root prim /// /// - public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) + public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) { - float maxX = -256f, maxY = -256f, maxZ = -256f, minX = 256f, minY = 256f, minZ = 256f; + maxX = -256f; + maxY = -256f; + maxZ = -256f; + minX = 256f; + minY = 256f; + minZ = 256f; + lockPartsForRead(true); { foreach (SceneObjectPart part in m_parts.Values) @@ -1034,7 +1040,18 @@ namespace OpenSim.Region.Framework.Scenes } } lockPartsForRead(false); + } + + public Vector3 GetAxisAlignedBoundingBox(out float offsetHeight) + { + float minX; + float maxX; + float minY; + float maxY; + float minZ; + float maxZ; + GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ); Vector3 boundingBox = new Vector3(maxX - minX, maxY - minY, maxZ - minZ); offsetHeight = 0; -- cgit v1.1 From f57f2370f1737e997e8871d5b05a426e9ac19ba7 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 1 Jun 2010 01:25:24 +0200 Subject: Add a method to get the bounding box and root prim offsets within it for a group of prims. --- OpenSim/Region/Framework/Scenes/Scene.cs | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 933999e..22248af 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5236,5 +5236,49 @@ namespace OpenSim.Region.Framework.Scenes ReloadEstateData(); } } + + public Vector3[] GetCombinedBoundingBox(List objects, out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) + { + minX = 256; + maxX = -256; + minY = 256; + maxY = -256; + minZ = 8192; + maxZ = -256; + + List offsets = new List(); + + foreach (SceneObjectGroup g in objects) + { + float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; + + g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); + + if (minX > ominX) + minX = ominX; + if (minY > ominY) + minY = ominY; + if (minZ > ominZ) + minZ = ominZ; + if (maxX < omaxX) + maxX = omaxX; + if (maxY < omaxY) + maxY = omaxY; + if (maxZ < omaxZ) + maxZ = omaxZ; + } + + foreach (SceneObjectGroup g in objects) + { + Vector3 vec = g.AbsolutePosition; + vec.X -= minX; + vec.Y -= minY; + vec.Z -= minZ; + + offsets.Add(vec); + } + + return offsets.ToArray(); + } } } -- cgit v1.1 From bf233ea0dc564dbae3896d8b5ac355fb2f247a00 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 1 Jun 2010 02:27:30 +0200 Subject: Continuing refactor. Refactor DeRezObject to deal with multiple objects --- .../InventoryAccess/HGInventoryAccessModule.cs | 17 ++- .../InventoryAccess/InventoryAccessModule.cs | 14 +++ .../Framework/Interfaces/IInventoryAccessModule.cs | 2 +- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 18 ++- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 138 ++++++++++++--------- 5 files changed, 118 insertions(+), 71 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 93aeb94..2ab46aa 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -119,9 +119,22 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess /// /// DeleteToInventory /// - public override UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) + public override UUID DeleteToInventory(DeRezAction action, UUID folderID, List objectGroups, IClientAPI remoteClient) { - UUID assetID = base.DeleteToInventory(action, folderID, objectGroup, remoteClient); + UUID ret = UUID.Zero; + + // HACK: Only works for lists of length one. + // Intermediate version, just to make things compile + foreach (SceneObjectGroup g in objectGroups) + ret = DeleteToInventory(action, folderID, g, remoteClient); + + return ret; + } + + public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, + SceneObjectGroup objectGroup, IClientAPI remoteClient) + { + UUID assetID = base.DeleteToInventory(action, folderID, new List() {objectGroup}, remoteClient); if (!assetID.Equals(UUID.Zero)) { diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 901dcba..3035d88 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -189,6 +189,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess /// /// public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, + List objectGroups, IClientAPI remoteClient) + { + // HACK: This is only working for lists containing a single item! + // It's just a hack to make this WIP compile and run. Nothing + // currently calls this with multiple items. + UUID ret = UUID.Zero; + + foreach (SceneObjectGroup g in objectGroups) + ret = DeleteToInventory(action, folderID, g, remoteClient); + + return ret; + } + + public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) { UUID assetID = UUID.Zero; diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs index 8185258..97f4188 100644 --- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs @@ -38,7 +38,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IInventoryAccessModule { UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data); - UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient); + UUID DeleteToInventory(DeRezAction action, UUID folderID, List objectGroups, IClientAPI remoteClient); SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment); diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index c08b961..241cac0 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Scenes { public DeRezAction action; public IClientAPI remoteClient; - public SceneObjectGroup objectGroup; + public List objectGroups; public UUID folderID; public bool permissionToDelete; } @@ -75,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes /// Delete the given object from the scene /// public void DeleteToInventory(DeRezAction action, UUID folderID, - SceneObjectGroup objectGroup, IClientAPI remoteClient, + List objectGroups, IClientAPI remoteClient, bool permissionToDelete) { if (Enabled) @@ -87,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); dtis.action = action; dtis.folderID = folderID; - dtis.objectGroup = objectGroup; + dtis.objectGroups = objectGroups; dtis.remoteClient = remoteClient; dtis.permissionToDelete = permissionToDelete; @@ -103,7 +103,10 @@ namespace OpenSim.Region.Framework.Scenes // This is not ideal since the object will still be available for manipulation when it should be, but it's // better than losing the object for now. if (permissionToDelete) - objectGroup.DeleteGroup(false); + { + foreach (SceneObjectGroup g in objectGroups) + g.DeleteGroup(false); + } } private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) @@ -140,9 +143,12 @@ namespace OpenSim.Region.Framework.Scenes { IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); if (invAccess != null) - invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); + invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient); if (x.permissionToDelete) - m_scene.DeleteSceneObject(x.objectGroup, false); + { + foreach (SceneObjectGroup g in x.objectGroups) + m_scene.DeleteSceneObject(g, false); + } } catch (Exception e) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index cbe3456..e1128a6 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1550,79 +1550,98 @@ namespace OpenSim.Region.Framework.Scenes public virtual void DeRezObject(IClientAPI remoteClient, uint localID, UUID groupID, DeRezAction action, UUID destinationID) { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part == null) - return; + DeRezObjects(remoteClient, new List() { localID} , groupID, action, destinationID); + } - if (part.ParentGroup == null || part.ParentGroup.IsDeleted) - return; + public virtual void DeRezObjects(IClientAPI remoteClient, List localIDs, + UUID groupID, DeRezAction action, UUID destinationID) + { + // First, see of we can perform the requested action and + // build a list of eligible objects + List deleteIDs = new List(); + List deleteGroups = new List(); - // Can't delete child prims - if (part != part.ParentGroup.RootPart) - return; + // Start with true for both, then remove the flags if objects + // that we can't derez are part of the selection + bool permissionToTake = true; + bool permissionToTakeCopy = true; + bool permissionToDelete = true; - SceneObjectGroup grp = part.ParentGroup; + foreach (uint localID in localIDs) + { + // Invalid id + SceneObjectPart part = GetSceneObjectPart(localID); + if (part == null) + continue; - //force a database backup/update on this SceneObjectGroup - //So that we know the database is upto date, for when deleting the object from it - ForceSceneObjectBackup(grp); + // Already deleted by someone else + if (part.ParentGroup == null || part.ParentGroup.IsDeleted) + continue; - bool permissionToTake = false; - bool permissionToDelete = false; + // Can't delete child prims + if (part != part.ParentGroup.RootPart) + continue; - if (action == DeRezAction.SaveToExistingUserInventoryItem) - { - if (grp.OwnerID == remoteClient.AgentId && grp.RootPart.FromUserInventoryItemID != UUID.Zero) - { - permissionToTake = true; + SceneObjectGroup grp = part.ParentGroup; + + deleteIDs.Add(localID); + deleteGroups.Add(grp); + + // Force a database backup/update on this SceneObjectGroup + // So that we know the database is upto date, + // for when deleting the object from it + ForceSceneObjectBackup(grp); + + if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) + permissionToTakeCopy = false; + if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) + permissionToTake = false; + + if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) permissionToDelete = false; - } + } - else if (action == DeRezAction.TakeCopy) + + // Handle god perms + if (Permissions.IsGod(remoteClient.AgentId)) { - permissionToTake = - Permissions.CanTakeCopyObject( - grp.UUID, - remoteClient.AgentId); + permissionToTake = true; + permissionToTakeCopy = true; + permissionToDelete = true; } - else if (action == DeRezAction.GodTakeCopy) - { - permissionToTake = - Permissions.IsGod( - remoteClient.AgentId); - } - else if (action == DeRezAction.Take) - { - permissionToTake = - Permissions.CanTakeObject( - grp.UUID, - remoteClient.AgentId); - //If they can take, they can delete! - permissionToDelete = permissionToTake; - } - else if (action == DeRezAction.Delete) + // If we're re-saving, we don't even want to delete + if (action == DeRezAction.SaveToExistingUserInventoryItem) + permissionToDelete = false; + + // if we want to take a copy,, we also don't want to delete + // Note: after this point, the permissionToTakeCopy flag + // becomes irrelevant. It already includes the permissionToTake + // permission and after excluding no copy items here, we can + // just use that. + if (action == DeRezAction.TakeCopy) { - permissionToTake = - Permissions.CanDeleteObject( - grp.UUID, - remoteClient.AgentId); - permissionToDelete = permissionToTake; + // If we don't have permission, stop right here + if (!permissionToTakeCopy) + return; + + // Don't delete + permissionToDelete = false; } - else if (action == DeRezAction.Return) + + if (action == DeRezAction.Return) { if (remoteClient != null) { - permissionToTake = - Permissions.CanReturnObjects( + if (Permissions.CanReturnObjects( null, remoteClient.AgentId, - new List() {grp}); - permissionToDelete = permissionToTake; - - if (permissionToDelete) + deleteGroups)) + foreach (SceneObjectGroup g in deleteGroups) { - AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return"); + AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); + DeleteSceneObject(g, false); + return; } } else // Auto return passes through here with null agent @@ -1631,22 +1650,17 @@ namespace OpenSim.Region.Framework.Scenes permissionToDelete = true; } } - else - { - m_log.DebugFormat( - "[AGENT INVENTORY]: Ignoring unexpected derez action {0} for {1}", action, remoteClient.Name); - return; - } if (permissionToTake) { m_asyncSceneObjectDeleter.DeleteToInventory( - action, destinationID, grp, remoteClient, + action, destinationID, deleteGroups, remoteClient, permissionToDelete); } else if (permissionToDelete) { - DeleteSceneObject(grp, false); + foreach (SceneObjectGroup g in deleteGroups) + DeleteSceneObject(g, false); } } -- cgit v1.1 From eca15cfbf25134ddc8bb752abbe3a6ba01bf07a9 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 1 Jun 2010 02:45:14 +0200 Subject: Change the handling of CreateSelected. Only send it on real creation, not for each prim coming into view. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2f4191d..e4a36ef 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -388,6 +388,7 @@ namespace OpenSim.Region.Framework.Scenes // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log _flags = 0; + CreateSelected = true; TrimPermissions(); //m_undo = new UndoStack(ParentGroup.GetSceneMaxUndo()); @@ -417,7 +418,7 @@ namespace OpenSim.Region.Framework.Scenes private PrimFlags _flags = 0; private DateTime m_expires; private DateTime m_rezzed; - private bool m_createSelected = true; + private bool m_createSelected = false; public UUID CreatorID { -- cgit v1.1 From 6c4c72546c25ee760d43bc75422ae484b68fbea0 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 1 Jun 2010 03:04:49 +0200 Subject: Fix prim returns I broke earlier --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e1128a6..e111867 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1637,11 +1637,14 @@ namespace OpenSim.Region.Framework.Scenes null, remoteClient.AgentId, deleteGroups)) - foreach (SceneObjectGroup g in deleteGroups) { - AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); - DeleteSceneObject(g, false); - return; + permissionToTake = true; + permissionToDelete = true; + + foreach (SceneObjectGroup g in deleteGroups) + { + AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); + } } } else // Auto return passes through here with null agent -- cgit v1.1 From 16d8602d3cad613a830a4903bb0d2beb1fa6b7e2 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 1 Jun 2010 03:04:49 +0200 Subject: Fix prim returns I broke earlier --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 11 +++++++---- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e1128a6..e111867 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1637,11 +1637,14 @@ namespace OpenSim.Region.Framework.Scenes null, remoteClient.AgentId, deleteGroups)) - foreach (SceneObjectGroup g in deleteGroups) { - AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); - DeleteSceneObject(g, false); - return; + permissionToTake = true; + permissionToDelete = true; + + foreach (SceneObjectGroup g in deleteGroups) + { + AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); + } } } else // Auto return passes through here with null agent diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 4203ba9..7e73f91 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -801,7 +801,7 @@ namespace OpenSim.Region.Framework.Scenes maxZ = -256f; minX = 256f; minY = 256f; - minZ = 256f; + minZ = 8192f; lockPartsForRead(true); { -- cgit v1.1 From f5ca70127347b20f9bfbb81fe777b9a602bfef0d Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 1 Jun 2010 14:19:26 +0100 Subject: Comment and remove JScript support. Mono 2.7Dev and 2.8 no longer include the needed libraries --- .../ScriptEngine/Shared/CodeTools/Compiler.cs | 38 +++++++++++----------- prebuild.xml | 7 ---- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index d8c0ba5..959164b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -32,7 +32,7 @@ using System.Globalization; using System.Reflection; using System.IO; using Microsoft.CSharp; -using Microsoft.JScript; +//using Microsoft.JScript; using Microsoft.VisualBasic; using log4net; using OpenSim.Region.Framework.Interfaces; @@ -82,7 +82,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider(); private static VBCodeProvider VBcodeProvider = new VBCodeProvider(); - private static JScriptCodeProvider JScodeProvider = new JScriptCodeProvider(); +// private static JScriptCodeProvider JScodeProvider = new JScriptCodeProvider(); private static CSharpCodeProvider YPcodeProvider = new CSharpCodeProvider(); // YP is translated into CSharp private static YP2CSConverter YP_Converter = new YP2CSConverter(); @@ -395,9 +395,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools case enumCompileType.vb: compileScript = CreateVBCompilerScript(compileScript); break; - case enumCompileType.js: - compileScript = CreateJSCompilerScript(compileScript); - break; +// case enumCompileType.js: +// compileScript = CreateJSCompilerScript(compileScript); +// break; case enumCompileType.yp: compileScript = CreateYPCompilerScript(compileScript); break; @@ -420,16 +420,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools } } - private static string CreateJSCompilerScript(string compileScript) - { - compileScript = String.Empty + - "import OpenSim.Region.ScriptEngine.Shared; import System.Collections.Generic;\r\n" + - "package SecondLife {\r\n" + - "class Script extends OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" + - compileScript + - "} }\r\n"; - return compileScript; - } +// private static string CreateJSCompilerScript(string compileScript) +// { +// compileScript = String.Empty + +// "import OpenSim.Region.ScriptEngine.Shared; import System.Collections.Generic;\r\n" + +// "package SecondLife {\r\n" + +// "class Script extends OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" + +// compileScript + +// "} }\r\n"; +// return compileScript; +// } private static string CreateCSCompilerScript(string compileScript) { @@ -580,10 +580,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools } } while (!complete); break; - case enumCompileType.js: - results = JScodeProvider.CompileAssemblyFromSource( - parameters, Script); - break; +// case enumCompileType.js: +// results = JScodeProvider.CompileAssemblyFromSource( +// parameters, Script); +// break; case enumCompileType.yp: results = YPcodeProvider.CompileAssemblyFromSource( parameters, Script); diff --git a/prebuild.xml b/prebuild.xml index 6b25792..66ab532 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -765,7 +765,6 @@ - @@ -1619,7 +1618,6 @@ - @@ -1702,7 +1700,6 @@ - @@ -2671,7 +2668,6 @@ ../../../../../bin/ - @@ -2808,7 +2804,6 @@ - @@ -3270,7 +3265,6 @@ - @@ -3334,7 +3328,6 @@ - -- cgit v1.1 From c900134f911b7f11c4fa25c67d55c112b1f56033 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 1 Jun 2010 16:03:53 +0200 Subject: Lock the object queue when dequeueing --- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 159 +++++++++++++------------ 1 file changed, 81 insertions(+), 78 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs index 2fc98e5..5cbd8d9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs +++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs @@ -67,105 +67,108 @@ namespace OpenSim.Region.Framework.Scenes public void SendPrimUpdates() { - if (m_pendingObjects == null) + lock(m_pendingObjects) { - if (!m_presence.IsChildAgent || (m_presence.Scene.m_seeIntoRegionFromNeighbor)) + if (m_pendingObjects == null) { - m_pendingObjects = new Queue(); - - foreach (EntityBase e in m_presence.Scene.Entities) + if (!m_presence.IsChildAgent || (m_presence.Scene.m_seeIntoRegionFromNeighbor)) { - if (e != null && e is SceneObjectGroup) - m_pendingObjects.Enqueue((SceneObjectGroup)e); + m_pendingObjects = new Queue(); + + foreach (EntityBase e in m_presence.Scene.Entities) + { + if (e != null && e is SceneObjectGroup) + m_pendingObjects.Enqueue((SceneObjectGroup)e); + } } } - } - - while (m_pendingObjects != null && m_pendingObjects.Count > 0) - { - SceneObjectGroup g = m_pendingObjects.Dequeue(); - // Yes, this can really happen - if (g == null) - continue; - - // This is where we should check for draw distance - // do culling and stuff. Problem with that is that until - // we recheck in movement, that won't work right. - // So it's not implemented now. - // - - // Don't even queue if we have sent this one - // - if (!m_updateTimes.ContainsKey(g.UUID)) - g.ScheduleFullUpdateToAvatar(m_presence); - } - while (m_partsUpdateQueue.Count > 0) - { - SceneObjectPart part = m_partsUpdateQueue.Dequeue(); - - if (part.ParentGroup == null || part.ParentGroup.IsDeleted) - continue; - - if (m_updateTimes.ContainsKey(part.UUID)) + while (m_pendingObjects != null && m_pendingObjects.Count > 0) { - ScenePartUpdate update = m_updateTimes[part.UUID]; + SceneObjectGroup g = m_pendingObjects.Dequeue(); + // Yes, this can really happen + if (g == null) + continue; - // We deal with the possibility that two updates occur at - // the same unix time at the update point itself. + // This is where we should check for draw distance + // do culling and stuff. Problem with that is that until + // we recheck in movement, that won't work right. + // So it's not implemented now. + // + + // Don't even queue if we have sent this one + // + if (!m_updateTimes.ContainsKey(g.UUID)) + g.ScheduleFullUpdateToAvatar(m_presence); + } - if ((update.LastFullUpdateTime < part.TimeStampFull) || - part.IsAttachment) + while (m_partsUpdateQueue.Count > 0) + { + SceneObjectPart part = m_partsUpdateQueue.Dequeue(); + + if (part.ParentGroup == null || part.ParentGroup.IsDeleted) + continue; + + if (m_updateTimes.ContainsKey(part.UUID)) { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}", -// part.Name, part.UUID, part.TimeStampFull); + ScenePartUpdate update = m_updateTimes[part.UUID]; - part.SendFullUpdate(m_presence.ControllingClient, - m_presence.GenerateClientFlags(part.UUID)); + // We deal with the possibility that two updates occur at + // the same unix time at the update point itself. - // We'll update to the part's timestamp rather than - // the current time to avoid the race condition - // whereby the next tick occurs while we are doing - // this update. If this happened, then subsequent - // updates which occurred on the same tick or the - // next tick of the last update would be ignored. + if ((update.LastFullUpdateTime < part.TimeStampFull) || + part.IsAttachment) + { + // m_log.DebugFormat( + // "[SCENE PRESENCE]: Fully updating prim {0}, {1} - part timestamp {2}", + // part.Name, part.UUID, part.TimeStampFull); - update.LastFullUpdateTime = part.TimeStampFull; + part.SendFullUpdate(m_presence.ControllingClient, + m_presence.GenerateClientFlags(part.UUID)); - } - else if (update.LastTerseUpdateTime <= part.TimeStampTerse) - { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}", -// part.Name, part.UUID, part.TimeStampTerse); + // We'll update to the part's timestamp rather than + // the current time to avoid the race condition + // whereby the next tick occurs while we are doing + // this update. If this happened, then subsequent + // updates which occurred on the same tick or the + // next tick of the last update would be ignored. - part.SendTerseUpdateToClient(m_presence.ControllingClient); + update.LastFullUpdateTime = part.TimeStampFull; - update.LastTerseUpdateTime = part.TimeStampTerse; - } - } - else - { - //never been sent to client before so do full update - ScenePartUpdate update = new ScenePartUpdate(); - update.FullID = part.UUID; - update.LastFullUpdateTime = part.TimeStampFull; - m_updateTimes.Add(part.UUID, update); + } + else if (update.LastTerseUpdateTime <= part.TimeStampTerse) + { + // m_log.DebugFormat( + // "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}", + // part.Name, part.UUID, part.TimeStampTerse); - // Attachment handling - // - if (part.ParentGroup.RootPart.Shape.PCode == 9 && part.ParentGroup.RootPart.Shape.State != 0) + part.SendTerseUpdateToClient(m_presence.ControllingClient); + + update.LastTerseUpdateTime = part.TimeStampTerse; + } + } + else { - if (part != part.ParentGroup.RootPart) + //never been sent to client before so do full update + ScenePartUpdate update = new ScenePartUpdate(); + update.FullID = part.UUID; + update.LastFullUpdateTime = part.TimeStampFull; + m_updateTimes.Add(part.UUID, update); + + // Attachment handling + // + if (part.ParentGroup.RootPart.Shape.PCode == 9 && part.ParentGroup.RootPart.Shape.State != 0) + { + if (part != part.ParentGroup.RootPart) + continue; + + part.ParentGroup.SendFullUpdateToClient(m_presence.ControllingClient); continue; + } - part.ParentGroup.SendFullUpdateToClient(m_presence.ControllingClient); - continue; + part.SendFullUpdate(m_presence.ControllingClient, + m_presence.GenerateClientFlags(part.UUID)); } - - part.SendFullUpdate(m_presence.ControllingClient, - m_presence.GenerateClientFlags(part.UUID)); } } } -- cgit v1.1 From 6668c789d34bf9b068df5821973fdb75cf129b75 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 1 Jun 2010 19:01:21 +0200 Subject: One should not lock null objects. --- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs index 5cbd8d9..f478a4a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs +++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs @@ -67,14 +67,14 @@ namespace OpenSim.Region.Framework.Scenes public void SendPrimUpdates() { - lock(m_pendingObjects) + if (m_pendingObjects == null) { - if (m_pendingObjects == null) + if (!m_presence.IsChildAgent || (m_presence.Scene.m_seeIntoRegionFromNeighbor)) { - if (!m_presence.IsChildAgent || (m_presence.Scene.m_seeIntoRegionFromNeighbor)) - { - m_pendingObjects = new Queue(); + m_pendingObjects = new Queue(); + lock(m_pendingObjects) + { foreach (EntityBase e in m_presence.Scene.Entities) { if (e != null && e is SceneObjectGroup) @@ -82,7 +82,10 @@ namespace OpenSim.Region.Framework.Scenes } } } + } + lock(m_pendingObjects) + { while (m_pendingObjects != null && m_pendingObjects.Count > 0) { SceneObjectGroup g = m_pendingObjects.Dequeue(); -- cgit v1.1 From 0209033dd9e2d4b4e4554d626d2e00388268e080 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 1 Jun 2010 13:22:24 -0700 Subject: Gosh, fixing another nullref issue in cmGetAvatarList. I deserve spanks. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 4f1e9f7..5b180ff 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -98,9 +98,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (avatar.IsChildAgent == false) { - result.Add(avatar.UUID); - result.Add(avatar.PhysicsActor.Position); - result.Add(avatar.Name); + if (avatar.PhysicsActor != null && avatar.PhysicsActor.Position != null) + { + result.Add(avatar.UUID); + result.Add(avatar.PhysicsActor.Position); + result.Add(avatar.Name); + } } } } -- cgit v1.1 From 90c814a7cace3bac3df451a8b184c32f462c4da2 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 1 Jun 2010 13:29:12 -0700 Subject: Fix nullref in cmGetAvatarList() (ported from 0.69) --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 3e62c1a..4fb5c95 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -125,9 +125,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (avatar.IsChildAgent == false) { - result.Add(avatar.UUID); - result.Add(avatar.PhysicsActor.Position); - result.Add(avatar.Name); + if (avatar.PhysicsActor != null && avatar.PhysicsActor.Position != null) + { + result.Add(avatar.UUID); + result.Add(avatar.PhysicsActor.Position); + result.Add(avatar.Name); + } } } }); -- cgit v1.1 From d8962ef4151043babe8d5c33c332bf49b020b119 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 2 Jun 2010 01:01:56 +0200 Subject: Add two new osFunctions: list osGetPrimititveParams(key prim, list rules); osSetPrimitiveParams(key prim, list rules); --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 18 ++++++++++++++++++ .../ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 16 ++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 3 +++ .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 4 ++++ .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 9 +++++++++ 5 files changed, 50 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8cc5e25..481a3e6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10261,6 +10261,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(100); return tid.ToString(); } + + public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + { + SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); + if (obj == null) + return; + + SetPrimParams(obj, rules); + } + + public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + { + SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); + if (obj == null) + return new LSL_List(); + + return GetLinkPrimitiveParams(obj, rules); + } } public class NotecardCache diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 2e0456e..f2a2f32 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2190,5 +2190,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } + + public LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules) + { + CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams"); + m_host.AddScriptLPS(1); + + return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); + } + + public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) + { + CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams"); + m_host.AddScriptLPS(1); + + m_LSL_Api.SetPrimitiveParamsEx(prim, rules); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 7ab04a3..cba46a3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -395,5 +395,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Vector llWind(LSL_Vector offset); LSL_String llXorBase64Strings(string str1, string str2); LSL_String llXorBase64StringsCorrect(string str1, string str2); + + void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); + LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 9dbd369..1ab7f10 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -35,6 +35,7 @@ using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; +using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { @@ -173,5 +174,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osSetSpeed(string UUID, float SpeedModifier); void osCauseHealing(string avatar, double healing); void osCauseDamage(string avatar, double damage); + LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); + void osSetPrimitiveParams(LSL_Key prim, LSL_List rules); + } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index fd9309a..7af5d43 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -41,6 +41,7 @@ using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; @@ -678,5 +679,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osCauseHealing(avatar, healing); } + public LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules) + { + return m_OSSL_Functions.osGetPrimitiveParams(prim, rules); + } + public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) + { + m_OSSL_Functions.osSetPrimitiveParams(prim, rules); + } } } -- cgit v1.1 From 70aa965c2678f91e45986f50a89588339a904f04 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 2 Jun 2010 01:04:17 +0200 Subject: Add a forgotten security check. Make the new functions only work on prims owned by the host prim owner. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 481a3e6..3c2ef34 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10268,6 +10268,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj == null) return; + if (obj.OwnerID != m_host.OwnerID) + return; + SetPrimParams(obj, rules); } @@ -10277,6 +10280,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj == null) return new LSL_List(); + if (obj.OwnerID != m_host.OwnerID) + return new LSL_List(); + return GetLinkPrimitiveParams(obj, rules); } } -- cgit v1.1 From 293f775fa56c8bcb3986373e004f54e549168be6 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 2 Jun 2010 07:59:18 -0700 Subject: Always provide at least 2 packets of a texture (if the texture is larger than 1 packet). This fixes compatibility with the newer (broken) SnowGlobe and Emerald viewer(s), but also matches the behaviour of SL. --- OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs index 9869a99..5c17b0e 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs @@ -202,6 +202,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_stopPacket = TexturePacketCount(); } + //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way) + if (m_stopPacket == 1 && Layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++; + m_currentPacket = StartPacket; } } -- cgit v1.1 From 241ed5734ee3c5b1417484dfa22af6cf6ae60b82 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 2 Jun 2010 17:14:37 +0100 Subject: After aborting a thread, wait for it to actually finish. EXPERIMENTAL for OSG testing. DO NOT UPDATE TO THIS UNLESS YOU KNOW WHAT YOU'RE DOING! --- OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index d30d2dc..f5b187f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -536,6 +536,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance if (!m_InSelfDelete) result.Abort(); + result.Wait(TimeSpan.FromSeconds(10)); lock (m_EventQueue) { m_CurrentResult = null; -- cgit v1.1 From c5cfae7bac9273d32c78409fe5080a202043b277 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 2 Jun 2010 17:39:58 +0100 Subject: Revert "After aborting a thread, wait for it to actually finish. EXPERIMENTAL for OSG" This reverts commit 241ed5734ee3c5b1417484dfa22af6cf6ae60b82. --- OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index f5b187f..d30d2dc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -536,7 +536,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance if (!m_InSelfDelete) result.Abort(); - result.Wait(TimeSpan.FromSeconds(10)); lock (m_EventQueue) { m_CurrentResult = null; -- cgit v1.1 From 698066d7e3a59281b6b1caa499ad32ff389c8bb6 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 2 Jun 2010 17:41:28 +0100 Subject: Next OSG TEST RELEASE. Join aborted threads. --- ThirdParty/SmartThreadPool/WorkItem.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ThirdParty/SmartThreadPool/WorkItem.cs b/ThirdParty/SmartThreadPool/WorkItem.cs index d0c0524..12668b0 100644 --- a/ThirdParty/SmartThreadPool/WorkItem.cs +++ b/ThirdParty/SmartThreadPool/WorkItem.cs @@ -1027,7 +1027,10 @@ namespace Amib.Threading.Internal lock (this) { if(currentThread != null) + { currentThread.Abort(); + currentThread.Join(); + } } } } -- cgit v1.1 From c38f7c96e78436cbefcbbe1d8820e28488f6d2dd Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 2 Jun 2010 18:00:44 +0100 Subject: Revert "Next OSG TEST RELEASE. Join aborted threads." This reverts commit 698066d7e3a59281b6b1caa499ad32ff389c8bb6. --- ThirdParty/SmartThreadPool/WorkItem.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/ThirdParty/SmartThreadPool/WorkItem.cs b/ThirdParty/SmartThreadPool/WorkItem.cs index 12668b0..d0c0524 100644 --- a/ThirdParty/SmartThreadPool/WorkItem.cs +++ b/ThirdParty/SmartThreadPool/WorkItem.cs @@ -1027,10 +1027,7 @@ namespace Amib.Threading.Internal lock (this) { if(currentThread != null) - { currentThread.Abort(); - currentThread.Join(); - } } } } -- cgit v1.1 From 20e6b7a320df97c69c9f23b2081c376951c39bed Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 2 Jun 2010 18:05:58 +0100 Subject: Next OSG test. Cowardly refuse to save the state of badly behaved scripts, instead of forcing the issue. --- OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index d30d2dc..18351ad 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -541,7 +541,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_CurrentResult = null; } - return true; + return false; } public void SetState(string state) @@ -991,7 +991,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public string GetXMLState() { bool run = Running; - Stop(100); + bool stopped = Stop(100); Running = run; // We should not be doing this, but since we are about to @@ -1002,6 +1002,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance // Force an update of the in-memory plugin data // + if (!stopped) + return String.Empty; + PluginData = AsyncCommandManager.GetSerializationData(m_Engine, m_ItemID); return ScriptSerializer.Serialize(this); -- cgit v1.1 From f831a1778baa766b4810e352f3ae2ab6736e4620 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 2 Jun 2010 19:57:03 +0100 Subject: Next OSG test. Don't remove app domains if they contain running threads. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 98e77c0..46d674d 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -277,7 +277,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine // Clear the event queue and abort the instance thread // instance.ClearQueue(); - instance.Stop(0); + bool stopped = instance.Stop(0); // Release events, timer, etc // @@ -287,7 +287,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine // Must be done explicitly because they have infinite // lifetime // - m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); + if (stopped) + m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); if (m_DomainScripts[instance.AppDomain].Count == 0) { m_DomainScripts.Remove(instance.AppDomain); @@ -804,7 +805,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_Scripts.Remove(itemID); instance.ClearQueue(); - instance.Stop(0); + bool stopped = instance.Stop(0); // bool objectRemoved = false; @@ -829,7 +830,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.RemoveState(); instance.DestroyScriptInstance(); - m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); + if (stopped) + m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); if (m_DomainScripts[instance.AppDomain].Count == 0) { m_DomainScripts.Remove(instance.AppDomain); -- cgit v1.1 From 82d0d1c092d309ab5c498e279155fc1ceb5738c8 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 2 Jun 2010 21:02:53 +0100 Subject: Revert "Next OSG test. Don't remove app domains if they contain running threads." This reverts commit f831a1778baa766b4810e352f3ae2ab6736e4620. With this, post-fixes is back to normal. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 46d674d..98e77c0 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -277,7 +277,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine // Clear the event queue and abort the instance thread // instance.ClearQueue(); - bool stopped = instance.Stop(0); + instance.Stop(0); // Release events, timer, etc // @@ -287,8 +287,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine // Must be done explicitly because they have infinite // lifetime // - if (stopped) - m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); + m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); if (m_DomainScripts[instance.AppDomain].Count == 0) { m_DomainScripts.Remove(instance.AppDomain); @@ -805,7 +804,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_Scripts.Remove(itemID); instance.ClearQueue(); - bool stopped = instance.Stop(0); + instance.Stop(0); // bool objectRemoved = false; @@ -830,8 +829,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.RemoveState(); instance.DestroyScriptInstance(); - if (stopped) - m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); + m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); if (m_DomainScripts[instance.AppDomain].Count == 0) { m_DomainScripts.Remove(instance.AppDomain); -- cgit v1.1 From dda7185b437fbbbd8ec7871b910a04990069a829 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 3 Jun 2010 17:55:50 -0700 Subject: Change the admin kick message to something more generic, "OpenSim Manager" is not really accurate --- OpenSim/Region/Application/OpenSim.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index a09b903..75561a7 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -427,7 +427,7 @@ namespace OpenSim if (alert != null) presence.ControllingClient.Kick(alert); else - presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n"); + presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); // ...and close on our side presence.Scene.IncomingCloseAgent(presence.UUID); -- cgit v1.1 From 8eb70f9719585f26f4dc610b383d546bda091655 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 4 Jun 2010 17:14:12 +0100 Subject: Fix bug where prim items were not loaded in the new sqlite database handler This addresses mantis http://opensimulator.org/mantis/view.php?id=4739 --- OpenSim/Data/SQLite/SQLiteRegionData.cs | 66 +++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs index fe6e919..4313db8 100644 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLite/SQLiteRegionData.cs @@ -93,7 +93,7 @@ namespace OpenSim.Data.SQLite ds = new DataSet("Region"); - m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); + m_log.Info("[SQLITE REGION DB]: Sqlite - connecting: " + connectionString); m_conn = new SqliteConnection(m_connectionString); m_conn.Open(); @@ -156,7 +156,7 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on prims table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on prims table"); } try @@ -165,16 +165,25 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on primshapes table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on primshapes table"); } try { + itemsDa.Fill(ds.Tables["primitems"]); + } + catch (Exception) + { + m_log.Info("[SQLITE REGION DB]: Caught fill error on primitems table"); + } + + try + { terrainDa.Fill(ds.Tables["terrain"]); } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on terrain table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on terrain table"); } try @@ -183,7 +192,7 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on land table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on land table"); } try @@ -192,7 +201,7 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on landaccesslist table"); } try @@ -201,7 +210,7 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on regionsettings table"); } // We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values! @@ -425,7 +434,7 @@ namespace OpenSim.Data.SQLite lock (ds) { DataRow[] primsForRegion = prims.Select(byRegion); - m_log.Info("[REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); +// m_log.Info("[SQLITE REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); // First, create all groups foreach (DataRow primRow in primsForRegion) @@ -447,8 +456,8 @@ namespace OpenSim.Data.SQLite } else { - m_log.Info( - "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + m_log.Warn( + "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape"); prim.Shape = PrimitiveBaseShape.Default; } @@ -460,11 +469,11 @@ namespace OpenSim.Data.SQLite } catch (Exception e) { - m_log.Error("[REGION DB]: Failed create prim object in new group, exception and data follows"); - m_log.Info("[REGION DB]: " + e.ToString()); + m_log.Error("[SQLITE REGION DB]: Failed create prim object in new group, exception and data follows"); + m_log.Error("[SQLITE REGION DB]: ", e); foreach (DataColumn col in prims.Columns) { - m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); } } } @@ -489,7 +498,7 @@ namespace OpenSim.Data.SQLite else { m_log.Warn( - "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape"); prim.Shape = PrimitiveBaseShape.Default; } @@ -499,11 +508,11 @@ namespace OpenSim.Data.SQLite } catch (Exception e) { - m_log.Error("[REGION DB]: Failed create prim object in group, exception and data follows"); - m_log.Info("[REGION DB]: " + e.ToString()); + m_log.Error("[SQLITE REGION DB]: Failed create prim object in group, exception and data follows"); + m_log.Error("[SQLITE REGION DB]: ", e); foreach (DataColumn col in prims.Columns) { - m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); } } } @@ -516,20 +525,23 @@ namespace OpenSim.Data.SQLite /// /// the prim private void LoadItems(SceneObjectPart prim) - { - //m_log.DebugFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); - + { +// m_log.DebugFormat("[SQLITE REGION DB]: Loading inventory for {0} {1}", prim.Name, prim.UUID); + DataTable dbItems = ds.Tables["primitems"]; - String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); + String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); DataRow[] dbItemRows = dbItems.Select(sql); IList inventory = new List(); +// m_log.DebugFormat( +// "[SQLITE REGION DB]: Found {0} items for {1} {2}", dbItemRows.Length, prim.Name, prim.UUID); + foreach (DataRow row in dbItemRows) { TaskInventoryItem item = buildItem(row); inventory.Add(item); - //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); +// m_log.DebugFormat("[SQLITE REGION DB]: Restored item {0} {1}", item.Name, item.ItemID); } prim.Inventory.RestoreInventoryItems(inventory); @@ -565,7 +577,7 @@ namespace OpenSim.Data.SQLite // the following is an work around for .NET. The perf // issues associated with it aren't as bad as you think. - m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString()); + m_log.Debug("[SQLITE REGION DB]: Storing terrain revision r" + revision.ToString()); String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + " values(:RegionUUID, :Revision, :Heightfield)"; @@ -621,11 +633,11 @@ namespace OpenSim.Data.SQLite } else { - m_log.Info("[REGION DB]: No terrain found for region"); + m_log.Warn("[SQLITE REGION DB]: No terrain found for region"); return null; } - m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString()); + m_log.Debug("[SQLITE REGION DB]: Loaded terrain revision r" + rev.ToString()); } } return terret; @@ -1407,7 +1419,7 @@ namespace OpenSim.Data.SQLite } catch (InvalidCastException) { - m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); + m_log.ErrorFormat("[SQLITE REGION DB]: unable to get parcel telehub settings for {1}", newData.Name); newData.UserLocation = Vector3.Zero; newData.UserLookAt = Vector3.Zero; } @@ -1914,7 +1926,7 @@ namespace OpenSim.Data.SQLite /// public void StorePrimInventory(UUID primID, ICollection items) { - //m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); +// m_log.DebugFormat("[SQLITE REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); DataTable dbItems = ds.Tables["primitems"]; -- cgit v1.1 From bdeda18b52f7ab37501f1751573e26e85656a4e4 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 4 Jun 2010 18:54:48 +0100 Subject: Revert "commit code which stops full updates being fired multiple times when attachments cross standalone region boundaries" This reverts commit 5074d290e4aeb583560272cadc8ba09aa8337210. This gets rid of the massive amount of scene object log spam - sorry about that, folks --- .../Interregion/LocalInterregionComms.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 5 --- .../Framework/Scenes/Scene.PacketHandlers.cs | 1 - OpenSim/Region/Framework/Scenes/Scene.cs | 43 +++------------------- .../Framework/Scenes/SceneCommunicationService.cs | 2 - OpenSim/Region/Framework/Scenes/SceneGraph.cs | 34 +---------------- .../Region/Framework/Scenes/SceneObjectGroup.cs | 15 ++------ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 34 ++++------------- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 8 +--- bin/OpenSim.exe.config | 2 +- 10 files changed, 23 insertions(+), 123 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs index 4abc215..d68c683 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs @@ -260,7 +260,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion { if (s.RegionInfo.RegionHandle == regionHandle) { - m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); + //m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); if (isLocalCall) { // We need to make a local copy of the object diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index f556b35..a2634f7 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2449,8 +2449,6 @@ namespace OpenSim.Region.Framework.Scenes return; } - m_log.DebugFormat("[SCENE INVENTORY]: {0} {1} IsAttachment={2}", att.Name, att.LocalId, att.IsAttachment); - Console.WriteLine("HERE X"); ScenePresence presence; if (TryGetAvatar(remoteClient.AgentId, out presence)) { @@ -2458,12 +2456,9 @@ namespace OpenSim.Region.Framework.Scenes InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = InventoryService.GetItem(item); presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); - Console.WriteLine("HERE Y"); if (m_AvatarFactory != null) m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - - Console.WriteLine("HERE Z"); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index d8e604f..ac04dc7 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -124,7 +124,6 @@ namespace OpenSim.Region.Framework.Scenes { if (((SceneObjectGroup)ent).LocalId == primLocalID) { - m_log.DebugFormat("[SCENE]: Received full update request for {0} from {1}", primLocalID, remoteClient.Name); ((SceneObjectGroup)ent).SendFullUpdateToClient(remoteClient); return; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f8ca047..e8c4978 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1850,31 +1850,9 @@ namespace OpenSim.Region.Framework.Scenes /// true if the object was added, false if an object with the same uuid was already in the scene /// public bool AddRestoredSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) - { - return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); - } - - /// - /// Add an object into the scene that has come from storage - /// - /// - /// - /// - /// If true, changes to the object will be reflected in its persisted data - /// If false, the persisted data will not be changed even if the object in the scene is changed - /// - /// - /// If true, we won't persist this object until it changes - /// If false, we'll persist this object immediately - /// - /// - /// true if the object was added, false if an object with the same uuid was already in the scene - /// - public bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) { - return AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); + return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted); } /// @@ -2487,7 +2465,7 @@ namespace OpenSim.Region.Framework.Scenes /// public bool IncomingCreateObject(ISceneObject sog) { - m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); + //m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); SceneObjectGroup newObject; try { @@ -2559,12 +2537,10 @@ namespace OpenSim.Region.Framework.Scenes if (sceneObject.IsAttachmentCheckFull()) // Attachment { - m_log.DebugFormat("[SCENE]: Adding attachment {0} {1}", sceneObject.Name, sceneObject.LocalId); - sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); sceneObject.RootPart.AddFlag(PrimFlags.Phantom); - AddRestoredSceneObject(sceneObject, false, false, false); + AddRestoredSceneObject(sceneObject, false, false); // Handle attachment special case SceneObjectPart RootPrim = sceneObject.RootPart; @@ -2572,8 +2548,6 @@ namespace OpenSim.Region.Framework.Scenes // Fix up attachment Parent Local ID ScenePresence sp = GetScenePresence(sceneObject.OwnerID); - Console.WriteLine("AAAA"); - //uint parentLocalID = 0; if (sp != null) { @@ -2592,25 +2566,20 @@ namespace OpenSim.Region.Framework.Scenes //grp.SetFromAssetID(grp.RootPart.LastOwnerID); m_log.DebugFormat( "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); - - RootPrim.RemFlag(PrimFlags.TemporaryOnRez); + AttachObject( sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false); - - //grp.SendGroupFullUpdate(); + RootPrim.RemFlag(PrimFlags.TemporaryOnRez); + grp.SendGroupFullUpdate(); } else { RootPrim.RemFlag(PrimFlags.TemporaryOnRez); RootPrim.AddFlag(PrimFlags.TemporaryOnRez); } - - Console.WriteLine("BBBB"); } else { - m_log.DebugFormat("[SCENE]: Adding ordinary object {0} {1}", sceneObject.Name, sceneObject.LocalId); - AddRestoredSceneObject(sceneObject, true, false); if (!Permissions.CanObjectEntry(sceneObject.UUID, diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 50feb17..2f6a0db 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -1383,9 +1383,7 @@ namespace OpenSim.Region.Framework.Scenes // now we have a child agent in this region. Request all interesting data about other (root) agents agent.SendInitialFullUpdateToAllClients(); - Console.WriteLine("SCS 1"); agent.CrossAttachmentsIntoNewRegion(neighbourHandle, true); - Console.WriteLine("SCS 2"); // m_scene.SendKillObject(m_localId); diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index fa3c5eb..59a2f41 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -216,15 +216,11 @@ namespace OpenSim.Region.Framework.Scenes /// If true, we won't persist this object until it changes /// If false, we'll persist this object immediately /// - /// - /// If true, we send updates to the client to tell it about this object - /// If false, we leave it up to the caller to do this - /// /// /// true if the object was added, false if an object with the same uuid was already in the scene /// protected internal bool AddRestoredSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) { if (!alreadyPersisted) { @@ -232,29 +228,8 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.HasGroupChanged = true; } - return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); + return AddSceneObject(sceneObject, attachToBackup, true); } - -// /// -// /// Add an object into the scene that has come from storage -// /// -// /// -// /// -// /// If true, changes to the object will be reflected in its persisted data -// /// If false, the persisted data will not be changed even if the object in the scene is changed -// /// -// /// -// /// If true, we won't persist this object until it changes -// /// If false, we'll persist this object immediately -// /// -// /// -// /// true if the object was added, false if an object with the same uuid was already in the scene -// /// -// protected internal bool AddRestoredSceneObject( -// SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) -// { -// AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); -// } /// /// Add a newly created object to the scene. This will both update the scene, and send information about the @@ -636,13 +611,11 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool AttachObject( IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) { - Console.WriteLine("HERE A"); SceneObjectGroup group = GetGroupByPrim(objectLocalID); if (group != null) { if (m_parentScene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) { - Console.WriteLine("HERE -1"); // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. @@ -681,12 +654,9 @@ namespace OpenSim.Region.Framework.Scenes itemId = group.GetFromItemID(); } - Console.WriteLine("HERE 0"); m_parentScene.AttachObject(remoteClient, AttachmentPt, itemId, group); - Console.WriteLine("HERE 1"); group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); - Console.WriteLine("HERE 2"); // In case it is later dropped again, don't let // it get cleaned up // diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ba3fde7..602b811 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1494,10 +1494,6 @@ namespace OpenSim.Region.Framework.Scenes public void SendFullUpdateToClient(IClientAPI remoteClient) { - if (IsAttachment) - m_log.DebugFormat( - "[SOG]: Sending full update to client {0} for {1} {2}", remoteClient.Name, Name, LocalId); - SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); lock (m_parts) @@ -1517,9 +1513,8 @@ namespace OpenSim.Region.Framework.Scenes /// internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags) { - if (IsAttachment) - m_log.DebugFormat( - "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); +// m_log.DebugFormat( +// "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); if (m_rootPart.UUID == part.UUID) { @@ -1999,8 +1994,7 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleFullUpdateToAvatar(ScenePresence presence) { - if (IsAttachment) - m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); +// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); RootPart.AddFullUpdateToAvatar(presence); @@ -2032,8 +2026,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForFullUpdate() { - if (IsAttachment) - m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); +// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); checkAtTargets(); RootPart.ScheduleFullUpdate(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index ffbb427..a85a4b3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1259,17 +1259,16 @@ namespace OpenSim.Region.Framework.Scenes /// Tell all scene presences that they should send updates for this part to their clients /// public void AddFullUpdateToAllAvatars() - { + { ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) - AddFullUpdateToAvatar(avatars[i]); + { + avatars[i].SceneViewer.QueuePartForUpdate(this); + } } public void AddFullUpdateToAvatar(ScenePresence presence) { - if (IsAttachment) - m_log.DebugFormat("AddFullUpdateToAllAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); - presence.SceneViewer.QueuePartForUpdate(this); } @@ -1288,14 +1287,13 @@ namespace OpenSim.Region.Framework.Scenes { ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) - AddTerseUpdateToAvatar(avatars[i]); + { + avatars[i].SceneViewer.QueuePartForUpdate(this); + } } public void AddTerseUpdateToAvatar(ScenePresence presence) { - if (IsAttachment) - m_log.DebugFormat("AddTerseUpdateToAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); - presence.SceneViewer.QueuePartForUpdate(this); } @@ -2729,8 +2727,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleFullUpdate() { - if (IsAttachment) - m_log.DebugFormat("[SOP]: Scheduling full update for {0} {1}", Name, LocalId); +// m_log.DebugFormat("[SCENE OBJECT PART]: Scheduling full update for {0} {1}", Name, LocalId); if (m_parentGroup != null) { @@ -2843,10 +2840,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags) { - if (IsAttachment) - m_log.DebugFormat( - "[SCENE OBJECT PART]: Sending part full update to {0} for {1} {2}", remoteClient.Name, Name, LocalId); - m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags); } @@ -2855,10 +2848,6 @@ namespace OpenSim.Region.Framework.Scenes ///
public void SendFullUpdateToAllClients() { - if (IsAttachment) - m_log.DebugFormat( - "[SCENE OBJECT PART]: Sending full update for {0} {1} for all clients", Name, LocalId); - ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) { @@ -2870,10 +2859,6 @@ namespace OpenSim.Region.Framework.Scenes public void SendFullUpdateToAllClientsExcept(UUID agentID) { - if (IsAttachment) - m_log.DebugFormat( - "[SCENE OBJECT PART]: Sending full update for {0} {1} to all clients except {2}", Name, LocalId, agentID); - ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) { @@ -2980,9 +2965,6 @@ namespace OpenSim.Region.Framework.Scenes { if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes { - if (IsAttachment) - m_log.DebugFormat("[SOP]: Sending scheduled full update for {0} {1}", Name, LocalId); - AddFullUpdateToAllAvatars(); ClearUpdateSchedule(); } diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs index 6f2bef9..e4296ef 100644 --- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs +++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs @@ -27,7 +27,6 @@ using System; using System.Collections.Generic; -using System.Reflection; using OpenMetaverse; using log4net; using OpenSim.Framework; @@ -40,8 +39,6 @@ namespace OpenSim.Region.Framework.Scenes { public class SceneViewer : ISceneViewer { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - protected ScenePresence m_presence; protected UpdateQueue m_partsUpdateQueue = new UpdateQueue(); protected Queue m_pendingObjects; @@ -63,9 +60,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void QueuePartForUpdate(SceneObjectPart part) { - if (part.IsAttachment) - m_log.DebugFormat("[SCENE VIEWER]: Queueing part {0} {1} for update", part.Name, part.LocalId); - lock (m_partsUpdateQueue) { m_partsUpdateQueue.Enqueue(part); @@ -140,7 +134,7 @@ namespace OpenSim.Region.Framework.Scenes } else if (update.LastTerseUpdateTime <= part.TimeStampTerse) { -// m_log.DebugFormat(AddFullUpdateToAvatar +// m_log.DebugFormat( // "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}", // part.Name, part.UUID, part.TimeStampTerse); diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index 4e7ef51..3c7adf5 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -12,7 +12,7 @@ - + -- cgit v1.1 From e962c44749ca63dec9df7de1c74b03d9b59c3f20 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Fri, 4 Jun 2010 19:36:31 -0700 Subject: Fix support for PRIM_SCULPT_FLAG_INVERT and PRIM_SCULPT_FLAG_MIRROR in the llSetPrimitiveParams series of functions. This makes it possible to mirror a sculpt by script. --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3c2ef34..0a4544c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7112,13 +7112,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api shapeBlock.PathScaleX = 100; shapeBlock.PathScaleY = 150; - if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && - type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && - type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && - type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) + if ((type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER) == 0 && + (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE) == 0 && + (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE) == 0 && + (type & (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) == 0) { // default - type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; + type = type | (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; } // retain pathcurve -- cgit v1.1 From fad5158ab4ab01a179eac80c92df301157fb8319 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 7 Jun 2010 00:09:22 +0200 Subject: Add a call to SOG.ResumeScripts() after region crossing / teleport --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 22248af..19329a8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2495,6 +2495,8 @@ namespace OpenSim.Region.Framework.Scenes newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, 1); + newObject.ResumeScripts(); + // Do this as late as possible so that listeners have full access to the incoming object EventManager.TriggerOnIncomingSceneObject(newObject); -- cgit v1.1 From 50ddb20204e8eb513212fe80d80b1308280fd47f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 27 May 2010 21:35:17 +0100 Subject: commit code which stops full updates being fired multiple times when attachments cross standalone region boundaries lots of messy debug code here too which would need to be removed --- .../Interregion/LocalInterregionComms.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 5 +++ .../Framework/Scenes/Scene.PacketHandlers.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.cs | 43 +++++++++++++++++++--- .../Framework/Scenes/SceneCommunicationService.cs | 2 + OpenSim/Region/Framework/Scenes/SceneGraph.cs | 34 ++++++++++++++++- .../Region/Framework/Scenes/SceneObjectGroup.cs | 15 ++++++-- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 34 +++++++++++++---- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 8 +++- bin/OpenSim.exe.config | 2 +- 10 files changed, 123 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs index d68c683..4abc215 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs @@ -260,7 +260,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion { if (s.RegionInfo.RegionHandle == regionHandle) { - //m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); + m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); if (isLocalCall) { // We need to make a local copy of the object diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index a2634f7..f556b35 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2449,6 +2449,8 @@ namespace OpenSim.Region.Framework.Scenes return; } + m_log.DebugFormat("[SCENE INVENTORY]: {0} {1} IsAttachment={2}", att.Name, att.LocalId, att.IsAttachment); + Console.WriteLine("HERE X"); ScenePresence presence; if (TryGetAvatar(remoteClient.AgentId, out presence)) { @@ -2456,9 +2458,12 @@ namespace OpenSim.Region.Framework.Scenes InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = InventoryService.GetItem(item); presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); + Console.WriteLine("HERE Y"); if (m_AvatarFactory != null) m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + + Console.WriteLine("HERE Z"); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index ac04dc7..d8e604f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -124,6 +124,7 @@ namespace OpenSim.Region.Framework.Scenes { if (((SceneObjectGroup)ent).LocalId == primLocalID) { + m_log.DebugFormat("[SCENE]: Received full update request for {0} from {1}", primLocalID, remoteClient.Name); ((SceneObjectGroup)ent).SendFullUpdateToClient(remoteClient); return; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e8c4978..f8ca047 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1850,9 +1850,31 @@ namespace OpenSim.Region.Framework.Scenes /// true if the object was added, false if an object with the same uuid was already in the scene /// public bool AddRestoredSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) + { + return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); + } + + /// + /// Add an object into the scene that has come from storage + /// + /// + /// + /// + /// If true, changes to the object will be reflected in its persisted data + /// If false, the persisted data will not be changed even if the object in the scene is changed + /// + /// + /// If true, we won't persist this object until it changes + /// If false, we'll persist this object immediately + /// + /// + /// true if the object was added, false if an object with the same uuid was already in the scene + /// + public bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) { - return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted); + return AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); } /// @@ -2465,7 +2487,7 @@ namespace OpenSim.Region.Framework.Scenes /// public bool IncomingCreateObject(ISceneObject sog) { - //m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); + m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); SceneObjectGroup newObject; try { @@ -2537,10 +2559,12 @@ namespace OpenSim.Region.Framework.Scenes if (sceneObject.IsAttachmentCheckFull()) // Attachment { + m_log.DebugFormat("[SCENE]: Adding attachment {0} {1}", sceneObject.Name, sceneObject.LocalId); + sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); sceneObject.RootPart.AddFlag(PrimFlags.Phantom); - AddRestoredSceneObject(sceneObject, false, false); + AddRestoredSceneObject(sceneObject, false, false, false); // Handle attachment special case SceneObjectPart RootPrim = sceneObject.RootPart; @@ -2548,6 +2572,8 @@ namespace OpenSim.Region.Framework.Scenes // Fix up attachment Parent Local ID ScenePresence sp = GetScenePresence(sceneObject.OwnerID); + Console.WriteLine("AAAA"); + //uint parentLocalID = 0; if (sp != null) { @@ -2566,20 +2592,25 @@ namespace OpenSim.Region.Framework.Scenes //grp.SetFromAssetID(grp.RootPart.LastOwnerID); m_log.DebugFormat( "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); - + + RootPrim.RemFlag(PrimFlags.TemporaryOnRez); AttachObject( sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false); - RootPrim.RemFlag(PrimFlags.TemporaryOnRez); - grp.SendGroupFullUpdate(); + + //grp.SendGroupFullUpdate(); } else { RootPrim.RemFlag(PrimFlags.TemporaryOnRez); RootPrim.AddFlag(PrimFlags.TemporaryOnRez); } + + Console.WriteLine("BBBB"); } else { + m_log.DebugFormat("[SCENE]: Adding ordinary object {0} {1}", sceneObject.Name, sceneObject.LocalId); + AddRestoredSceneObject(sceneObject, true, false); if (!Permissions.CanObjectEntry(sceneObject.UUID, diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 2f6a0db..50feb17 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -1383,7 +1383,9 @@ namespace OpenSim.Region.Framework.Scenes // now we have a child agent in this region. Request all interesting data about other (root) agents agent.SendInitialFullUpdateToAllClients(); + Console.WriteLine("SCS 1"); agent.CrossAttachmentsIntoNewRegion(neighbourHandle, true); + Console.WriteLine("SCS 2"); // m_scene.SendKillObject(m_localId); diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 59a2f41..fa3c5eb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -216,11 +216,15 @@ namespace OpenSim.Region.Framework.Scenes /// If true, we won't persist this object until it changes /// If false, we'll persist this object immediately /// + /// + /// If true, we send updates to the client to tell it about this object + /// If false, we leave it up to the caller to do this + /// /// /// true if the object was added, false if an object with the same uuid was already in the scene /// protected internal bool AddRestoredSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { if (!alreadyPersisted) { @@ -228,8 +232,29 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.HasGroupChanged = true; } - return AddSceneObject(sceneObject, attachToBackup, true); + return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); } + +// /// +// /// Add an object into the scene that has come from storage +// /// +// /// +// /// +// /// If true, changes to the object will be reflected in its persisted data +// /// If false, the persisted data will not be changed even if the object in the scene is changed +// /// +// /// +// /// If true, we won't persist this object until it changes +// /// If false, we'll persist this object immediately +// /// +// /// +// /// true if the object was added, false if an object with the same uuid was already in the scene +// /// +// protected internal bool AddRestoredSceneObject( +// SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) +// { +// AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); +// } /// /// Add a newly created object to the scene. This will both update the scene, and send information about the @@ -611,11 +636,13 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool AttachObject( IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) { + Console.WriteLine("HERE A"); SceneObjectGroup group = GetGroupByPrim(objectLocalID); if (group != null) { if (m_parentScene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) { + Console.WriteLine("HERE -1"); // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. @@ -654,9 +681,12 @@ namespace OpenSim.Region.Framework.Scenes itemId = group.GetFromItemID(); } + Console.WriteLine("HERE 0"); m_parentScene.AttachObject(remoteClient, AttachmentPt, itemId, group); + Console.WriteLine("HERE 1"); group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); + Console.WriteLine("HERE 2"); // In case it is later dropped again, don't let // it get cleaned up // diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 602b811..ba3fde7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1494,6 +1494,10 @@ namespace OpenSim.Region.Framework.Scenes public void SendFullUpdateToClient(IClientAPI remoteClient) { + if (IsAttachment) + m_log.DebugFormat( + "[SOG]: Sending full update to client {0} for {1} {2}", remoteClient.Name, Name, LocalId); + SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); lock (m_parts) @@ -1513,8 +1517,9 @@ namespace OpenSim.Region.Framework.Scenes /// internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags) { -// m_log.DebugFormat( -// "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); + if (IsAttachment) + m_log.DebugFormat( + "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); if (m_rootPart.UUID == part.UUID) { @@ -1994,7 +1999,8 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleFullUpdateToAvatar(ScenePresence presence) { -// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); + if (IsAttachment) + m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); RootPart.AddFullUpdateToAvatar(presence); @@ -2026,7 +2032,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForFullUpdate() { -// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); + if (IsAttachment) + m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); checkAtTargets(); RootPart.ScheduleFullUpdate(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a85a4b3..ffbb427 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1259,16 +1259,17 @@ namespace OpenSim.Region.Framework.Scenes /// Tell all scene presences that they should send updates for this part to their clients /// public void AddFullUpdateToAllAvatars() - { + { ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) - { - avatars[i].SceneViewer.QueuePartForUpdate(this); - } + AddFullUpdateToAvatar(avatars[i]); } public void AddFullUpdateToAvatar(ScenePresence presence) { + if (IsAttachment) + m_log.DebugFormat("AddFullUpdateToAllAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); + presence.SceneViewer.QueuePartForUpdate(this); } @@ -1287,13 +1288,14 @@ namespace OpenSim.Region.Framework.Scenes { ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) - { - avatars[i].SceneViewer.QueuePartForUpdate(this); - } + AddTerseUpdateToAvatar(avatars[i]); } public void AddTerseUpdateToAvatar(ScenePresence presence) { + if (IsAttachment) + m_log.DebugFormat("AddTerseUpdateToAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); + presence.SceneViewer.QueuePartForUpdate(this); } @@ -2727,7 +2729,8 @@ namespace OpenSim.Region.Framework.Scenes ///
public void ScheduleFullUpdate() { -// m_log.DebugFormat("[SCENE OBJECT PART]: Scheduling full update for {0} {1}", Name, LocalId); + if (IsAttachment) + m_log.DebugFormat("[SOP]: Scheduling full update for {0} {1}", Name, LocalId); if (m_parentGroup != null) { @@ -2840,6 +2843,10 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags) { + if (IsAttachment) + m_log.DebugFormat( + "[SCENE OBJECT PART]: Sending part full update to {0} for {1} {2}", remoteClient.Name, Name, LocalId); + m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags); } @@ -2848,6 +2855,10 @@ namespace OpenSim.Region.Framework.Scenes ///
public void SendFullUpdateToAllClients() { + if (IsAttachment) + m_log.DebugFormat( + "[SCENE OBJECT PART]: Sending full update for {0} {1} for all clients", Name, LocalId); + ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) { @@ -2859,6 +2870,10 @@ namespace OpenSim.Region.Framework.Scenes public void SendFullUpdateToAllClientsExcept(UUID agentID) { + if (IsAttachment) + m_log.DebugFormat( + "[SCENE OBJECT PART]: Sending full update for {0} {1} to all clients except {2}", Name, LocalId, agentID); + ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) { @@ -2965,6 +2980,9 @@ namespace OpenSim.Region.Framework.Scenes { if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes { + if (IsAttachment) + m_log.DebugFormat("[SOP]: Sending scheduled full update for {0} {1}", Name, LocalId); + AddFullUpdateToAllAvatars(); ClearUpdateSchedule(); } diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs index e4296ef..6f2bef9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs +++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Reflection; using OpenMetaverse; using log4net; using OpenSim.Framework; @@ -39,6 +40,8 @@ namespace OpenSim.Region.Framework.Scenes { public class SceneViewer : ISceneViewer { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected ScenePresence m_presence; protected UpdateQueue m_partsUpdateQueue = new UpdateQueue(); protected Queue m_pendingObjects; @@ -60,6 +63,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void QueuePartForUpdate(SceneObjectPart part) { + if (part.IsAttachment) + m_log.DebugFormat("[SCENE VIEWER]: Queueing part {0} {1} for update", part.Name, part.LocalId); + lock (m_partsUpdateQueue) { m_partsUpdateQueue.Enqueue(part); @@ -134,7 +140,7 @@ namespace OpenSim.Region.Framework.Scenes } else if (update.LastTerseUpdateTime <= part.TimeStampTerse) { -// m_log.DebugFormat( +// m_log.DebugFormat(AddFullUpdateToAvatar // "[SCENE PRESENCE]: Tersely updating prim {0}, {1} - part timestamp {2}", // part.Name, part.UUID, part.TimeStampTerse); diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index 3c7adf5..4e7ef51 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -12,7 +12,7 @@ - + -- cgit v1.1 From 693b5d08381a7672b3ebeb693ee50a82e8e59125 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 7 Jun 2010 16:07:43 +0100 Subject: reapply fix for double sending of attachment update on standalone region crossing --- .../Interregion/LocalInterregionComms.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 8 ++--- .../Framework/Scenes/Scene.PacketHandlers.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 10 +++---- .../Framework/Scenes/SceneCommunicationService.cs | 4 +-- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 10 +++---- .../Region/Framework/Scenes/SceneObjectGroup.cs | 20 ++++++------- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 34 +++++++++++----------- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 6 ++-- 9 files changed, 48 insertions(+), 48 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs index 4abc215..0730f8b 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Interregion/LocalInterregionComms.cs @@ -260,7 +260,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Interregion { if (s.RegionInfo.RegionHandle == regionHandle) { - m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); +// m_log.Debug("[LOCAL COMMS]: Found region to SendCreateObject"); if (isLocalCall) { // We need to make a local copy of the object diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index f556b35..a11b1f1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -2449,8 +2449,8 @@ namespace OpenSim.Region.Framework.Scenes return; } - m_log.DebugFormat("[SCENE INVENTORY]: {0} {1} IsAttachment={2}", att.Name, att.LocalId, att.IsAttachment); - Console.WriteLine("HERE X"); +// m_log.DebugFormat("[SCENE INVENTORY]: {0} {1} IsAttachment={2}", att.Name, att.LocalId, att.IsAttachment); +// Console.WriteLine("HERE X"); ScenePresence presence; if (TryGetAvatar(remoteClient.AgentId, out presence)) { @@ -2458,12 +2458,12 @@ namespace OpenSim.Region.Framework.Scenes InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = InventoryService.GetItem(item); presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); - Console.WriteLine("HERE Y"); +// Console.WriteLine("HERE Y"); if (m_AvatarFactory != null) m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - Console.WriteLine("HERE Z"); +// Console.WriteLine("HERE Z"); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index d8e604f..adc9496 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -124,7 +124,7 @@ namespace OpenSim.Region.Framework.Scenes { if (((SceneObjectGroup)ent).LocalId == primLocalID) { - m_log.DebugFormat("[SCENE]: Received full update request for {0} from {1}", primLocalID, remoteClient.Name); +// m_log.DebugFormat("[SCENE]: Received full update request for {0} from {1}", primLocalID, remoteClient.Name); ((SceneObjectGroup)ent).SendFullUpdateToClient(remoteClient); return; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f8ca047..7089368 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2487,7 +2487,7 @@ namespace OpenSim.Region.Framework.Scenes /// public bool IncomingCreateObject(ISceneObject sog) { - m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); +// m_log.Debug(" >>> IncomingCreateObject(sog) <<< " + ((SceneObjectGroup)sog).AbsolutePosition + " deleted? " + ((SceneObjectGroup)sog).IsDeleted); SceneObjectGroup newObject; try { @@ -2559,7 +2559,7 @@ namespace OpenSim.Region.Framework.Scenes if (sceneObject.IsAttachmentCheckFull()) // Attachment { - m_log.DebugFormat("[SCENE]: Adding attachment {0} {1}", sceneObject.Name, sceneObject.LocalId); +// m_log.DebugFormat("[SCENE]: Adding attachment {0} {1}", sceneObject.Name, sceneObject.LocalId); sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); sceneObject.RootPart.AddFlag(PrimFlags.Phantom); @@ -2572,7 +2572,7 @@ namespace OpenSim.Region.Framework.Scenes // Fix up attachment Parent Local ID ScenePresence sp = GetScenePresence(sceneObject.OwnerID); - Console.WriteLine("AAAA"); +// Console.WriteLine("AAAA"); //uint parentLocalID = 0; if (sp != null) @@ -2605,11 +2605,11 @@ namespace OpenSim.Region.Framework.Scenes RootPrim.AddFlag(PrimFlags.TemporaryOnRez); } - Console.WriteLine("BBBB"); +// Console.WriteLine("BBBB"); } else { - m_log.DebugFormat("[SCENE]: Adding ordinary object {0} {1}", sceneObject.Name, sceneObject.LocalId); +// m_log.DebugFormat("[SCENE]: Adding ordinary object {0} {1}", sceneObject.Name, sceneObject.LocalId); AddRestoredSceneObject(sceneObject, true, false); diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 50feb17..67fa13d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -1383,9 +1383,9 @@ namespace OpenSim.Region.Framework.Scenes // now we have a child agent in this region. Request all interesting data about other (root) agents agent.SendInitialFullUpdateToAllClients(); - Console.WriteLine("SCS 1"); +// Console.WriteLine("SCS 1"); agent.CrossAttachmentsIntoNewRegion(neighbourHandle, true); - Console.WriteLine("SCS 2"); +// Console.WriteLine("SCS 2"); // m_scene.SendKillObject(m_localId); diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index fa3c5eb..bdab696 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -636,13 +636,13 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool AttachObject( IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) { - Console.WriteLine("HERE A"); +// Console.WriteLine("HERE A"); SceneObjectGroup group = GetGroupByPrim(objectLocalID); if (group != null) { if (m_parentScene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) { - Console.WriteLine("HERE -1"); +// Console.WriteLine("HERE -1"); // If the attachment point isn't the same as the one previously used // set it's offset position = 0 so that it appears on the attachment point // and not in a weird location somewhere unknown. @@ -681,12 +681,12 @@ namespace OpenSim.Region.Framework.Scenes itemId = group.GetFromItemID(); } - Console.WriteLine("HERE 0"); +// Console.WriteLine("HERE 0"); m_parentScene.AttachObject(remoteClient, AttachmentPt, itemId, group); - Console.WriteLine("HERE 1"); +// Console.WriteLine("HERE 1"); group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); - Console.WriteLine("HERE 2"); +// Console.WriteLine("HERE 2"); // In case it is later dropped again, don't let // it get cleaned up // diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ba3fde7..451c6f9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1494,9 +1494,9 @@ namespace OpenSim.Region.Framework.Scenes public void SendFullUpdateToClient(IClientAPI remoteClient) { - if (IsAttachment) - m_log.DebugFormat( - "[SOG]: Sending full update to client {0} for {1} {2}", remoteClient.Name, Name, LocalId); +// if (IsAttachment) +// m_log.DebugFormat( +// "[SOG]: Sending full update to client {0} for {1} {2}", remoteClient.Name, Name, LocalId); SendPartFullUpdate(remoteClient, RootPart, m_scene.Permissions.GenerateClientFlags(remoteClient.AgentId, RootPart.UUID)); @@ -1517,9 +1517,9 @@ namespace OpenSim.Region.Framework.Scenes /// internal void SendPartFullUpdate(IClientAPI remoteClient, SceneObjectPart part, uint clientFlags) { - if (IsAttachment) - m_log.DebugFormat( - "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); +// if (IsAttachment) +// m_log.DebugFormat( +// "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); if (m_rootPart.UUID == part.UUID) { @@ -1999,8 +1999,8 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleFullUpdateToAvatar(ScenePresence presence) { - if (IsAttachment) - m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); +// if (IsAttachment) +// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1} just to avatar {2}", Name, UUID, presence.Name); RootPart.AddFullUpdateToAvatar(presence); @@ -2032,8 +2032,8 @@ namespace OpenSim.Region.Framework.Scenes ///
public void ScheduleGroupForFullUpdate() { - if (IsAttachment) - m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); +// if (IsAttachment) +// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); checkAtTargets(); RootPart.ScheduleFullUpdate(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index ffbb427..33624a2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1267,8 +1267,8 @@ namespace OpenSim.Region.Framework.Scenes public void AddFullUpdateToAvatar(ScenePresence presence) { - if (IsAttachment) - m_log.DebugFormat("AddFullUpdateToAllAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); +// if (IsAttachment) +// m_log.DebugFormat("AddFullUpdateToAllAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); presence.SceneViewer.QueuePartForUpdate(this); } @@ -1293,8 +1293,8 @@ namespace OpenSim.Region.Framework.Scenes public void AddTerseUpdateToAvatar(ScenePresence presence) { - if (IsAttachment) - m_log.DebugFormat("AddTerseUpdateToAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); +// if (IsAttachment) +// m_log.DebugFormat("AddTerseUpdateToAvatar() {0} for {1} {2}", presence.Name, Name, LocalId); presence.SceneViewer.QueuePartForUpdate(this); } @@ -2729,8 +2729,8 @@ namespace OpenSim.Region.Framework.Scenes ///
public void ScheduleFullUpdate() { - if (IsAttachment) - m_log.DebugFormat("[SOP]: Scheduling full update for {0} {1}", Name, LocalId); +// if (IsAttachment) +// m_log.DebugFormat("[SOP]: Scheduling full update for {0} {1}", Name, LocalId); if (m_parentGroup != null) { @@ -2843,9 +2843,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags) { - if (IsAttachment) - m_log.DebugFormat( - "[SCENE OBJECT PART]: Sending part full update to {0} for {1} {2}", remoteClient.Name, Name, LocalId); +// if (IsAttachment) +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Sending part full update to {0} for {1} {2}", remoteClient.Name, Name, LocalId); m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags); } @@ -2855,9 +2855,9 @@ namespace OpenSim.Region.Framework.Scenes ///
public void SendFullUpdateToAllClients() { - if (IsAttachment) - m_log.DebugFormat( - "[SCENE OBJECT PART]: Sending full update for {0} {1} for all clients", Name, LocalId); +// if (IsAttachment) +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Sending full update for {0} {1} for all clients", Name, LocalId); ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) @@ -2870,9 +2870,9 @@ namespace OpenSim.Region.Framework.Scenes public void SendFullUpdateToAllClientsExcept(UUID agentID) { - if (IsAttachment) - m_log.DebugFormat( - "[SCENE OBJECT PART]: Sending full update for {0} {1} to all clients except {2}", Name, LocalId, agentID); +// if (IsAttachment) +// m_log.DebugFormat( +// "[SCENE OBJECT PART]: Sending full update for {0} {1} to all clients except {2}", Name, LocalId, agentID); ScenePresence[] avatars = m_parentGroup.Scene.GetScenePresences(); for (int i = 0; i < avatars.Length; i++) @@ -2980,8 +2980,8 @@ namespace OpenSim.Region.Framework.Scenes { if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes { - if (IsAttachment) - m_log.DebugFormat("[SOP]: Sending scheduled full update for {0} {1}", Name, LocalId); +// if (IsAttachment) +// m_log.DebugFormat("[SOP]: Sending scheduled full update for {0} {1}", Name, LocalId); AddFullUpdateToAllAvatars(); ClearUpdateSchedule(); diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs index 6f2bef9..23663dd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs +++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -63,8 +63,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void QueuePartForUpdate(SceneObjectPart part) { - if (part.IsAttachment) - m_log.DebugFormat("[SCENE VIEWER]: Queueing part {0} {1} for update", part.Name, part.LocalId); +// if (part.IsAttachment) +// m_log.DebugFormat("[SCENE VIEWER]: Queueing part {0} {1} for update", part.Name, part.LocalId); lock (m_partsUpdateQueue) { -- cgit v1.1 From 912f0c7fde1d3ec159b9f9b61136a2ac64e7d9dd Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 7 Jun 2010 18:49:22 +0100 Subject: Stop some hud components disappearing on region crossings If viewers (or at least, Linden Viewer 1.23.5) receive child hud object updates before the root prim, then the children are not displayed. Updates were being queued in LLClientView in the right order (root first) but were being sent in a random order since they were all at the same prioritization This commit prioritizes the root prim of a hud to its highest level when queued. I'm not sure if the periodic reprioritization triggered via ScenePresence might reset this, but boosting priority appears to work so far. Also committed is a belt and braces mechanism in LLClientView to prevent child hud prim being sent out before their root, but since this doesn't appear to be needed it is currently commented out. --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 54 ++++++++++++++++++---- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 31 +++++++++++-- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 +- bin/OpenSim.exe.config | 4 +- 4 files changed, 79 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 724c8bc..37929f2 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -365,6 +365,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected HashSet m_killRecord; +// protected HashSet m_attachmentsQueued; +// protected HashSet m_attachmentsSent; + private int m_moneyBalance; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; @@ -456,6 +459,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_primFullUpdates = new PriorityQueue(m_scene.Entities.Count); m_fullUpdateDataBlocksBuilder = new List(); m_killRecord = new HashSet(); +// m_attachmentsQueued = new HashSet(); +// m_attachmentsSent = new HashSet(); m_assetService = m_scene.RequestModuleInterface(); m_hyperAssets = m_scene.RequestModuleInterface(); @@ -3401,6 +3406,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data); OutPacket(objupdate, ThrottleOutPacketType.Task); + + // We need to record the avatar local id since the root prim of an attachment points to this. +// m_attachmentsSent.Add(data.AvatarLocalID); } /// @@ -3523,6 +3531,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data); + +// if (data.attachment) +// m_attachmentsQueued.Add(data.localID); lock (m_primFullUpdates.SyncRoot) m_primFullUpdates.Enqueue(data.priority, objectData, data.localID); @@ -3549,15 +3560,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue(); if (!m_killRecord.Contains(block.ID)) - { + { +// if (m_attachmentsQueued.Contains(block.ID)) +// { +// string text = Util.FieldToString(block.Text); +// if (text.IndexOf("\n") >= 0) +// text = text.Remove(text.IndexOf("\n")); +// +// if (m_attachmentsSent.Contains(block.ParentID)) +// { +// m_log.DebugFormat( +// "[CLIENT]: Sending full info about attached prim {0} text {1}", +// block.ID, text); +// +// m_fullUpdateDataBlocksBuilder.Add(block); +// +// m_attachmentsSent.Add(block.ID); +// } +// else +// { +// m_log.DebugFormat( +// "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet", +// block.ID, text, block.ParentID); +// +// lock (m_primFullUpdates.SyncRoot) +// m_primFullUpdates.Enqueue(double.MaxValue, block, block.ID); +// } +// } +// else +// { m_fullUpdateDataBlocksBuilder.Add(block); - -// string text = Util.FieldToString(outPacket.ObjectData[i].Text); -// if (text.IndexOf("\n") >= 0) -// text = text.Remove(text.IndexOf("\n")); -// m_log.DebugFormat( -// "[CLIENT]: Sending full info about prim {0} text {1} to client {2}", -// outPacket.ObjectData[i].ID, text, Name); +// } } // else // { @@ -4506,6 +4539,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data) { +// if (data.attachment) +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Creating prim update block for {0}, parent {1}, priority {2}", +// data.localID, data.parentID, data.priority); + byte[] objectData = new byte[60]; data.pos.ToBytes(objectData, 0); data.vel.ToBytes(objectData, 12); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 33624a2..479ee4d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2929,10 +2929,33 @@ namespace OpenSim.Region.Framework.Scenes //isattachment = ParentGroup.RootPart.IsAttachment; byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A}; - remoteClient.SendPrimitiveToClient(new SendPrimitiveData(m_regionHandle, m_parentGroup.GetTimeDilation(), LocalId, m_shape, - lPos, Velocity, Acceleration, RotationOffset, AngularVelocity, clientFlags, m_uuid, _ownerID, - m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment, - AttachmentPoint,FromItemID, Sound, SoundGain, SoundFlags, SoundRadius, ParentGroup.GetUpdatePriority(remoteClient))); + + double priority = ParentGroup.GetUpdatePriority(remoteClient); + if (IsRoot && IsAttachment) + { + if (double.MinValue == priority) + { + m_log.WarnFormat( + "[SOP]: Couldn't raise update priority of root part for attachment {0} {1} because priority is already highest value", + Name, LocalId); + } + else + { + priority = double.MinValue; + } + } + + remoteClient.SendPrimitiveToClient( + new SendPrimitiveData(m_regionHandle, m_parentGroup.GetTimeDilation(), LocalId, m_shape, + lPos, Velocity, Acceleration, RotationOffset, AngularVelocity, clientFlags, m_uuid, _ownerID, + m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment, + AttachmentPoint,FromItemID, Sound, SoundGain, SoundFlags, SoundRadius, priority)); + +// if (IsRoot && IsAttachment) +// { +// ScenePresence sp = ParentGroup.Scene.GetScenePresence(remoteClient.AgentId); +// remoteClient.ReprioritizeUpdates(StateUpdateTypes.PrimitiveFull, sp.UpdatePriority); +// } } /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 4973663..18f2fd2 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3871,8 +3871,10 @@ namespace OpenSim.Region.Framework.Scenes } } - private double UpdatePriority(UpdatePriorityData data) + internal double UpdatePriority(UpdatePriorityData data) { +// m_log.DebugFormat("[SCENE PRESENCE]: Reprioritizing updates to client {0} for {1}", Name, data.localID); + EntityBase entity; SceneObjectGroup group; diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index 4e7ef51..aa2162e 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -12,7 +12,9 @@ - + + + -- cgit v1.1 From 255e05beb594001af971228cf9434d1cc2a63dbd Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Mon, 7 Jun 2010 19:52:45 +0100 Subject: minor: remove some commented out code and return ScenePresence.UpdatePriority() to private --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 6 ------ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 479ee4d..19ff288 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2950,12 +2950,6 @@ namespace OpenSim.Region.Framework.Scenes lPos, Velocity, Acceleration, RotationOffset, AngularVelocity, clientFlags, m_uuid, _ownerID, m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment, AttachmentPoint,FromItemID, Sound, SoundGain, SoundFlags, SoundRadius, priority)); - -// if (IsRoot && IsAttachment) -// { -// ScenePresence sp = ParentGroup.Scene.GetScenePresence(remoteClient.AgentId); -// remoteClient.ReprioritizeUpdates(StateUpdateTypes.PrimitiveFull, sp.UpdatePriority); -// } } /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 18f2fd2..51cdf1b 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3871,7 +3871,7 @@ namespace OpenSim.Region.Framework.Scenes } } - internal double UpdatePriority(UpdatePriorityData data) + private double UpdatePriority(UpdatePriorityData data) { // m_log.DebugFormat("[SCENE PRESENCE]: Reprioritizing updates to client {0} for {1}", Name, data.localID); -- cgit v1.1 From 052445806911288b49c36065575556559fe4963e Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 3 Mar 2010 17:50:05 +0000 Subject: remove references to OpenSim.Framework.Commuications.Tests.dll since all relevant test code has been obsoleted this allows the tests to pass on my local system --- .nant/local.include | 22 ---------------------- .../Region/ClientStack/LindenUDP/LLClientView.cs | 16 +++++++++++++--- OpenSim/Region/Framework/Scenes/SceneManager.cs | 2 +- 3 files changed, 14 insertions(+), 26 deletions(-) diff --git a/.nant/local.include b/.nant/local.include index 3db063b..6f0a362 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -95,11 +95,6 @@ - - - - - @@ -160,17 +155,6 @@ - - - - - - - - - - - - diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index ec238ef..58aa26a 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -98,6 +98,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientIPEndpoint, IStatsCollector { + /// + /// Debug packet level. At the moment, only 255 does anything (prints out all in and out packets). + /// + protected int m_debugPacketLevel = 0; + #region Events public event GenericMessage OnGenericMessage; @@ -490,6 +495,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SetDebugPacketLevel(int newDebug) { + m_debugPacketLevel = newDebug; } #region Client Methods @@ -11080,7 +11086,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP LLUDPServer.LogPacketHeader(false, m_circuitCode, 0, packet.Type, (ushort)packet.Length); #endregion BinaryStats - m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, true); + OutPacket(packet, throttlePacketType, true); } /// @@ -11093,6 +11099,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// handles splitting manually protected void OutPacket(Packet packet, ThrottleOutPacketType throttlePacketType, bool doAutomaticSplitting) { + if (m_debugPacketLevel >= 255) + m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); + m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); } @@ -11164,10 +11173,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// OpenMetaverse.packet public void ProcessInPacket(Packet Pack) { -// m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack); + if (m_debugPacketLevel >= 255) + m_log.DebugFormat("[CLIENT]: Packet IN {0}", Pack.Type); if (!ProcessPacketMethod(Pack)) - m_log.Warn("[CLIENT]: unhandled packet " + Pack); + m_log.Warn("[CLIENT]: unhandled packet " + Pack.Type); PacketPool.Instance.ReturnPacket(Pack); } diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index c2e3370..92c278e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs @@ -422,7 +422,7 @@ namespace OpenSim.Region.Framework.Scenes if (!scenePresence.IsChildAgent) { - m_log.ErrorFormat("Packet debug for {0} {1} set to {2}", + m_log.DebugFormat("Packet debug for {0} {1} set to {2}", scenePresence.Firstname, scenePresence.Lastname, newDebug); -- cgit v1.1 From 8b3b89ecf40ebe4e78ca77ccc5e14b2632829119 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 8 Jun 2010 20:31:39 +0100 Subject: backport xmlrpcgroups cache from master --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 4 +- .../World/Permissions/PermissionsModule.cs | 23 ++-- .../Framework/Scenes/Scene.PacketHandlers.cs | 3 +- .../Region/Framework/Scenes/SceneObjectGroup.cs | 6 +- .../XmlRpcGroupsServicesConnectorModule.cs | 135 ++++++++++++++------- 5 files changed, 112 insertions(+), 59 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 58aa26a..20e53fc 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3517,8 +3517,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP // if (text.IndexOf("\n") >= 0) // text = text.Remove(text.IndexOf("\n")); // m_log.DebugFormat( -// "[CLIENT]: Placing request to send full info about prim {0} text {1} to client {2}", -// data.localID, text, Name); +// "[CLIENT]: Queueing send full info about prim {0}, attachment {1}, text {2} to client {3}", +// data.localID, data.attachment, text, Name); if (data.priority == double.NaN) { diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index a972ca6..53556ab 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -411,18 +411,23 @@ namespace OpenSim.Region.CoreModules.World.Permissions // with the powers requested (powers = 0 for no powers check) protected bool IsGroupMember(UUID groupID, UUID userID, ulong powers) { - if (null == m_groupsModule) - return false; - - GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, userID); - - if (gmd != null) + //DateTime t1 = DateTime.Now; + bool result = false; + + if (null != m_groupsModule) { - if (((gmd.GroupPowers != 0) && powers == 0) || (gmd.GroupPowers & powers) == powers) - return true; + GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, userID); + + if (gmd != null) + { + if (((gmd.GroupPowers != 0) && powers == 0) || (gmd.GroupPowers & powers) == powers) + result = true; + } } + + //m_log.DebugFormat("[PERMISSIONS]: Group member check took {0}", (DateTime.Now - t1).TotalMilliseconds); - return false; + return result; } /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index adc9496..869efd7 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -116,6 +116,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void RequestPrim(uint primLocalID, IClientAPI remoteClient) { +// m_log.DebugFormat("[SCENE]: {0} requested full update for {1}", remoteClient.Name, primLocalID); + List EntityList = GetEntities(); foreach (EntityBase ent in EntityList) @@ -124,7 +126,6 @@ namespace OpenSim.Region.Framework.Scenes { if (((SceneObjectGroup)ent).LocalId == primLocalID) { -// m_log.DebugFormat("[SCENE]: Received full update request for {0} from {1}", primLocalID, remoteClient.Name); ((SceneObjectGroup)ent).SendFullUpdateToClient(remoteClient); return; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 451c6f9..fe5e948 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1519,7 +1519,7 @@ namespace OpenSim.Region.Framework.Scenes { // if (IsAttachment) // m_log.DebugFormat( -// "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); +// "[SOG]: Sending part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); if (m_rootPart.UUID == part.UUID) { @@ -2033,7 +2033,7 @@ namespace OpenSim.Region.Framework.Scenes public void ScheduleGroupForFullUpdate() { // if (IsAttachment) -// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); +// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); checkAtTargets(); RootPart.ScheduleFullUpdate(); @@ -2072,7 +2072,7 @@ namespace OpenSim.Region.Framework.Scenes if (IsDeleted) return; -// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); +// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, LocalId); RootPart.SendFullUpdateToAllClients(); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs index 861731c..e64c9a7 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs @@ -29,6 +29,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Reflection; +using System.Text; using Nwc.XmlRpc; @@ -42,6 +43,7 @@ using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { @@ -72,7 +74,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_debugEnabled = false; - + private ExpiringCache m_memoryCache; + private int m_cacheTimeout = 30; + // Used to track which agents are have dropped from a group chat session // Should be reset per agent, on logon // TODO: move this to Flotsam XmlRpc Service @@ -132,8 +136,18 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); - + m_cacheTimeout = groupsConfig.GetInt("GroupsCacheTimeout", 30); + if (m_cacheTimeout == 0) + { + m_log.WarnFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Disabled."); + } + else + { + m_log.InfoFormat("[XMLRPC-GROUPS-CONNECTOR]: Groups Cache Timeout set to {0}.", m_cacheTimeout); + } + // If we got all the config options we need, lets start'er'up + m_memoryCache = new ExpiringCache(); m_connectorEnabled = true; } } @@ -921,61 +935,94 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups /// private Hashtable XmlRpcCall(UUID requestingAgentID, string function, Hashtable param) { - string UserService; - UUID SessionID; - GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); - param.Add("RequestingAgentID", requestingAgentID.ToString()); - param.Add("RequestingAgentUserService", UserService); - param.Add("RequestingSessionID", SessionID.ToString()); - - - param.Add("ReadKey", m_groupReadKey); - param.Add("WriteKey", m_groupWriteKey); + XmlRpcResponse resp = null; + string CacheKey = null; - if (m_debugEnabled) + // Only bother with the cache if it isn't disabled. + if (m_cacheTimeout > 0) { - m_log.Debug("[XMLRPCGROUPDATA] XmlRpcCall Params:"); - foreach (string key in param.Keys) + if (!function.StartsWith("groups.get")) { - m_log.DebugFormat("[XMLRPCGROUPDATA] {0} : {1}", key, param[key]); + // Any and all updates cause the cache to clear + m_memoryCache.Clear(); } - } - - IList parameters = new ArrayList(); - parameters.Add(param); - - ConfigurableKeepAliveXmlRpcRequest req; - req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive); - - XmlRpcResponse resp = null; + else + { + StringBuilder sb = new StringBuilder(requestingAgentID + function); + foreach (object key in param.Keys) + { + if (param[key] != null) + { + sb.AppendFormat(",{0}:{1}", key.ToString(), param[key].ToString()); + } + } - try - { - resp = req.Send(m_groupsServerURI, 10000); + CacheKey = sb.ToString(); + m_memoryCache.TryGetValue(CacheKey, out resp); + } } - catch (Exception e) + + if (resp == null) { + string UserService; + UUID SessionID; + GetClientGroupRequestID(requestingAgentID, out UserService, out SessionID); + param.Add("RequestingAgentID", requestingAgentID.ToString()); + param.Add("RequestingAgentUserService", UserService); + param.Add("RequestingSessionID", SessionID.ToString()); - - m_log.ErrorFormat("[XMLRPCGROUPDATA]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function); - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", e.ToString()); - - if ((req != null) && (req.RequestResponse != null)) - { - foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) + + param.Add("ReadKey", m_groupReadKey); + param.Add("WriteKey", m_groupWriteKey); + + if (m_debugEnabled) { - m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", ResponseLine); + m_log.Debug("[XMLRPCGROUPDATA] XmlRpcCall Params:"); + foreach (string key in param.Keys) + { + m_log.DebugFormat("[XMLRPCGROUPDATA] {0} : {1}", key, param[key]); + } } + + IList parameters = new ArrayList(); + parameters.Add(param); + + ConfigurableKeepAliveXmlRpcRequest req; + req = new ConfigurableKeepAliveXmlRpcRequest(function, parameters, m_disableKeepAlive); + + try + { + resp = req.Send(m_groupsServerURI, 10000); + + if ((m_cacheTimeout > 0) && (CacheKey != null)) + { + m_memoryCache.AddOrUpdate(CacheKey, resp, TimeSpan.FromSeconds(m_cacheTimeout)); + } } - - foreach (string key in param.Keys) + catch (Exception e) { - m_log.WarnFormat("[XMLRPCGROUPDATA]: {0} :: {1}", key, param[key].ToString()); + + + m_log.ErrorFormat("[XMLRPCGROUPDATA]: An error has occured while attempting to access the XmlRpcGroups server method: {0}", function); + m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", e.ToString()); + + if ((req != null) && (req.RequestResponse != null)) + { + foreach (string ResponseLine in req.RequestResponse.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) + { + m_log.ErrorFormat("[XMLRPCGROUPDATA]: {0} ", ResponseLine); + } + } + + foreach (string key in param.Keys) + { + m_log.WarnFormat("[XMLRPCGROUPDATA]: {0} :: {1}", key, param[key].ToString()); + } + + Hashtable respData = new Hashtable(); + respData.Add("error", e.ToString()); + return respData; } - - Hashtable respData = new Hashtable(); - respData.Add("error", e.ToString()); - return respData; } -- cgit v1.1 From 4921d5ac2dc1f439b7820a22c89fd8239ff33bbc Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 8 Jun 2010 22:03:08 +0200 Subject: Make the text mode remote console really work. It can now be used to send multi-word commands with proper quoting, handles arguments with spaces and allows interactive use, e.g. user creation. --- OpenSim/ConsoleClient/ConsoleClient.cs | 38 +++++++++++++++++++++++------- OpenSim/Framework/Console/RemoteConsole.cs | 36 +++++++++++++++++----------- OpenSim/Server/Base/ServicesServerBase.cs | 5 ++++ 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/OpenSim/ConsoleClient/ConsoleClient.cs b/OpenSim/ConsoleClient/ConsoleClient.cs index 8c616e0..f4605da 100644 --- a/OpenSim/ConsoleClient/ConsoleClient.cs +++ b/OpenSim/ConsoleClient/ConsoleClient.cs @@ -29,6 +29,7 @@ using Nini.Config; using log4net; using System.Reflection; using System; +using System.IO; using System.Xml; using System.Collections.Generic; using OpenSim.Server.Base; @@ -73,9 +74,18 @@ namespace OpenSim.ConsoleClient Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/StartSession/", String.Format("USER={0}&PASS={1}", m_User, m_Pass), LoginReply); - int res = m_Server.Run(); + string pidFile = serverConfig.GetString("PIDFile", String.Empty); - Environment.Exit(res); + while (m_Server.Running) + { + System.Threading.Thread.Sleep(500); + // MainConsole.Instance.Prompt(); + } + + if (pidFile != String.Empty) + File.Delete(pidFile); + + Environment.Exit(0); return 0; } @@ -83,13 +93,14 @@ namespace OpenSim.ConsoleClient private static void SendCommand(string module, string[] cmd) { string sendCmd = ""; + string[] cmdlist = new string[cmd.Length - 1]; + + sendCmd = cmd[0]; + if (cmd.Length > 1) { - sendCmd = cmd[0]; - - Array.Copy(cmd, 1, cmd, 0, cmd.Length-1); - Array.Resize(ref cmd, cmd.Length-1); - sendCmd += "\"" + String.Join("\" \"", cmd) + "\""; + Array.Copy(cmd, 1, cmdlist, 0, cmd.Length - 1); + sendCmd += " \"" + String.Join("\" \"", cmdlist) + "\""; } Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/SessionCommand/", String.Format("ID={0}&COMMAND={1}", m_SessionID, sendCmd), CommandReply); @@ -183,16 +194,27 @@ namespace OpenSim.ConsoleClient while (lines.Count > 100) lines.RemoveAt(0); + string prompt = String.Empty; + foreach (string l in lines) { string[] parts = l.Split(new char[] {':'}, 3); if (parts.Length != 3) continue; - MainConsole.Instance.Output(parts[2].Trim(), parts[1]); + if (parts[2].StartsWith("+++") || parts[2].StartsWith("-++")) + prompt = parts[2]; + else + MainConsole.Instance.Output(parts[2].Trim(), parts[1]); } + Requester.MakeRequest(requestUrl, requestData, ReadResponses); + + if (prompt.StartsWith("+++")) + MainConsole.Instance.ReadLine(prompt.Substring(3), true, true); + else if (prompt.StartsWith("-++")) + SendCommand(String.Empty, new string[] { MainConsole.Instance.ReadLine(prompt.Substring(3), false, true) }); } public static void CommandReply(string requestUrl, string requestData, string replyData) diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs index 6f8348d..a46a6cb 100644 --- a/OpenSim/Framework/Console/RemoteConsole.cs +++ b/OpenSim/Framework/Console/RemoteConsole.cs @@ -106,8 +106,15 @@ namespace OpenSim.Framework.Console public override string ReadLine(string p, bool isCommand, bool e) { + if (isCommand) + Output("+++"+p); + else + Output("-++"+p); + m_DataEvent.WaitOne(); + string cmdinput; + lock (m_InputData) { if (m_InputData.Count == 0) @@ -116,29 +123,30 @@ namespace OpenSim.Framework.Console return ""; } - string cmdinput = m_InputData[0]; + cmdinput = m_InputData[0]; m_InputData.RemoveAt(0); if (m_InputData.Count == 0) m_DataEvent.Reset(); - if (isCommand) + } + + if (isCommand) + { + string[] cmd = Commands.Resolve(Parser.Parse(cmdinput)); + + if (cmd.Length != 0) { - string[] cmd = Commands.Resolve(Parser.Parse(cmdinput)); + int i; - if (cmd.Length != 0) + for (i=0 ; i < cmd.Length ; i++) { - int i; - - for (i=0 ; i < cmd.Length ; i++) - { - if (cmd[i].Contains(" ")) - cmd[i] = "\"" + cmd[i] + "\""; - } - return String.Empty; + if (cmd[i].Contains(" ")) + cmd[i] = "\"" + cmd[i] + "\""; } + return String.Empty; } - return cmdinput; } + return cmdinput; } private void DoExpire() @@ -308,7 +316,7 @@ namespace OpenSim.Framework.Console return reply; } - if (post["COMMAND"] == null || post["COMMAND"].ToString() == String.Empty) + if (post["COMMAND"] == null) return reply; lock (m_InputData) diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index 63ba673..a5bebb8 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -236,6 +236,11 @@ namespace OpenSim.Server.Base Initialise(); } + public bool Running + { + get { return m_Running; } + } + public virtual int Run() { while (m_Running) -- cgit v1.1 From 6e2cc98eacf48a24ae19433a3f6c2ba9693c5b9e Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Tue, 8 Jun 2010 16:15:16 -0400 Subject: Fixed llMoveToTarget() and Rotation Lock/Enable (ChODE/ODEPrim only) --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 230 ++++++++++++++++++++------ 1 file changed, 179 insertions(+), 51 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index fbe52c8..7ce01dc 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -64,11 +64,16 @@ namespace OpenSim.Region.Physics.OdePlugin private Vector3 m_taintVelocity; private Vector3 m_taintTorque; private Quaternion m_taintrot; - private Vector3 m_angularEnable = Vector3.One; // Current setting - private Vector3 m_taintAngularLock = Vector3.One; // Request from LSL - - + private Vector3 m_rotateEnable = Vector3.One; // Current setting + private Vector3 m_rotateEnableRequest = Vector3.One; // Request from LSL + private bool m_rotateEnableUpdate = false; + private Vector3 m_lockX; + private Vector3 m_lockY; + private Vector3 m_lockZ; private IntPtr Amotor = IntPtr.Zero; + private IntPtr AmotorX = IntPtr.Zero; + private IntPtr AmotorY = IntPtr.Zero; + private IntPtr AmotorZ = IntPtr.Zero; private Vector3 m_PIDTarget; private float m_PIDTau; @@ -729,7 +734,12 @@ namespace OpenSim.Region.Physics.OdePlugin public override float Buoyancy { get { return m_buoyancy; } - set { m_buoyancy = value; } +// set { m_buoyancy = value; } + set { + m_buoyancy = value; + + Console.WriteLine("m_buoyancy={0}", m_buoyancy); + } } public override void link(PhysicsActor obj) @@ -744,14 +754,18 @@ namespace OpenSim.Region.Physics.OdePlugin public override void LockAngularMotion(Vector3 axis) { - // reverse the zero/non zero values for ODE. + // This is actually ROTATION ENABLE, not a lock. + // default is <1,1,1> which is all enabled. + // The lock value is updated inside Move(), no point in using the taint system. + // OS 'm_taintAngularLock' etc change to m_rotateEnable. if (axis.IsFinite()) { axis.X = (axis.X > 0) ? 1f : 0f; axis.Y = (axis.Y > 0) ? 1f : 0f; axis.Z = (axis.Z > 0) ? 1f : 0f; m_log.DebugFormat("[axislock]: <{0},{1},{2}>", axis.X, axis.Y, axis.Z); - m_taintAngularLock = axis; + m_rotateEnableRequest = axis; + m_rotateEnableUpdate = true; } else { @@ -1391,10 +1405,10 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_taintCollidesWater != m_collidesWater) changefloatonwater(timestep); - - if (!m_angularEnable.ApproxEquals(m_taintAngularLock,0f)) +/* obsolete + if (!m_angularLock.ApproxEquals(m_taintAngularLock,0f)) changeAngularLock(timestep); - + */ } else { @@ -1402,15 +1416,16 @@ namespace OpenSim.Region.Physics.OdePlugin } } - +/* obsolete private void changeAngularLock(float timestep) { if (_parent == null) { - m_angularEnable = m_taintAngularLock; + m_angularLock = m_taintAngularLock; + m_angularLockSet = true; } } - + */ private void changelink(float timestep) { // If the newly set parent is not null @@ -2991,7 +3006,7 @@ Console.WriteLine(" JointCreateFixed"); if (fence == 1) border_limit = 0.5f; // bounce point frcount++; // used to limit debug comment output - if (frcount > 10) + if (frcount > 50) frcount = 0; if(revcount > 0) revcount--; @@ -3200,8 +3215,91 @@ Console.WriteLine(" JointCreateFixed"); } m_lastposition = l_position; - /// End UpdatePositionAndVelocity insert - + /// End UpdatePositionAndVelocity insert + + + // Rotation lock ===================================== + if(m_rotateEnableUpdate) + { + // Snapshot current angles, set up Amotor(s) + m_rotateEnableUpdate = false; + m_rotateEnable = m_rotateEnableRequest; +Console.WriteLine("RotEnable {0} = {1}",m_primName, m_rotateEnable); + + if (Amotor != IntPtr.Zero) + { + d.JointDestroy(Amotor); + Amotor = IntPtr.Zero; +Console.WriteLine("Old Amotor Destroyed"); + } + + if (!m_rotateEnable.ApproxEquals(Vector3.One, 0.003f)) + { // not all are enabled + d.Quaternion r = d.BodyGetQuaternion(Body); + Quaternion locrot = new Quaternion(r.X, r.Y, r.Z, r.W); + // extract the axes vectors + Vector3 vX = new Vector3(1f,0f,0f); + Vector3 vY = new Vector3(0f,1f,0f); + Vector3 vZ = new Vector3(0f,0f,1f); + vX = vX * locrot; + vY = vY * locrot; + vZ = vZ * locrot; + // snapshot the current angle vectors + m_lockX = vX; + m_lockY = vY; + m_lockZ = vZ; + // m_lockRot = locrot; + Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); + d.JointAttach(Amotor, Body, IntPtr.Zero); + d.JointSetAMotorMode(Amotor, 0); // User mode?? +Console.WriteLine("New Amotor Created for {0}", m_primName); + + float axisnum = 3; // how many to lock + axisnum = (axisnum - (m_rotateEnable.X + m_rotateEnable.Y + m_rotateEnable.Z)); + d.JointSetAMotorNumAxes(Amotor,(int)axisnum); +Console.WriteLine("AxisNum={0}",(int)axisnum); + + int i = 0; + + if (m_rotateEnable.X == 0) + { + d.JointSetAMotorAxis(Amotor, i, 0, m_lockX.X, m_lockX.Y, m_lockX.Z); +Console.WriteLine("AxisX {0} set to {1}", i, m_lockX); + i++; + } + + if (m_rotateEnable.Y == 0) + { + d.JointSetAMotorAxis(Amotor, i, 0, m_lockY.X, m_lockY.Y, m_lockY.Z); +Console.WriteLine("AxisY {0} set to {1}", i, m_lockY); + i++; + } + + if (m_rotateEnable.Z == 0) + { + d.JointSetAMotorAxis(Amotor, i, 0, m_lockZ.X, m_lockZ.Y, m_lockZ.Z); +Console.WriteLine("AxisZ {0} set to {1}", i, m_lockZ); + i++; + } + + // These lowstops and high stops are effectively (no wiggle room) + d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0f); + d.JointSetAMotorParam(Amotor, (int) dParam.Vel, 0f); + d.JointSetAMotorParam(Amotor, (int) dParam.Vel3, 0f); + d.JointSetAMotorParam(Amotor, (int) dParam.Vel2, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM3, 0f); + d.JointSetAMotorParam(Amotor, (int)dParam.StopCFM2, 0f); + } // else none are locked + } // end Rotation Update + + + // VEHICLE processing ========================================== if (m_type != Vehicle.TYPE_NONE) { // get body attitude @@ -3420,7 +3518,7 @@ Console.WriteLine(" JointCreateFixed"); //if(frcount == 0) Console.WriteLine("V3 = {0}", angObjectVel); - // Rotation Axis Disables: + /* // Rotation Axis Disables: if (!m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) { if (m_angularEnable.X == 0) @@ -3430,7 +3528,7 @@ Console.WriteLine(" JointCreateFixed"); if (m_angularEnable.Z == 0) angObjectVel.Z = 0f; } - + */ angObjectVel = angObjectVel * rotq; // ================ Converts to WORLD rotation // Vertical attractor section @@ -3500,35 +3598,58 @@ Console.WriteLine(" JointCreateFixed"); } // end VEHICLES else { + // Dyamics (NON-'VEHICLES') are dealt with here ================================================================ + if(!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 - // NON-'VEHICLES' are dealt with here - /// Dynamics Angular Lock ======================================================================== - if (d.BodyIsEnabled(Body) && !m_angularEnable.ApproxEquals(Vector3.One, 0.003f)) - { - d.Vector3 avel2 = d.BodyGetAngularVel(Body); - if (m_angularEnable.X == 0) - avel2.X = 0; - if (m_angularEnable.Y == 0) - avel2.Y = 0; - if (m_angularEnable.Z == 0) - avel2.Z = 0; - d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); - } - - - /// Dynamics Buoyancy =============================================================================== + + /// Dynamics Buoyancy //KF: m_buoyancy is set by llSetBuoyancy() and is for non-vehicle. // m_buoyancy: (unlimited value) <0=Falls fast; 0=1g; 1=0g; >1 = floats up // NB Prims in ODE are no subject to global gravity + // This should only affect gravity operations + float m_mass = CalculateMass(); + // calculate z-force due togravity on object. fz = _parent_scene.gravityz * (1.0f - m_buoyancy) * m_mass; // force = acceleration * mass - if (m_usePID) + if ((m_usePID) && (m_PIDTau > 0.0f)) // Dynamics llMoveToTarget. { -//if(frcount == 0) Console.WriteLine("PID " + m_primName); - // KF - this is for object MoveToTarget. - - //if (!d.BodyIsEnabled(Body)) + fz = 0; // llMoveToTarget ignores gravity. + // it also ignores mass of object, and any physical resting on it. + // Vector3 m_PIDTarget is where we are going + // float m_PIDTau is time to get there + fx = 0; + fy = 0; + d.Vector3 pos = d.BodyGetPosition(Body); + Vector3 error = new Vector3( + (m_PIDTarget.X - pos.X), + (m_PIDTarget.Y - pos.Y), + (m_PIDTarget.Z - pos.Z)); + if (error.ApproxEquals(Vector3.Zero,0.01f)) + { // Very close, Jump there and quit move + d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z); + _target_velocity = Vector3.Zero; + d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z); + } + else + { + float scale = 50.0f * timestep / m_PIDTau; + if ((error.ApproxEquals(Vector3.Zero,0.5f)) && (_target_velocity != Vector3.Zero)) + { + // Nearby, quit update of velocity + } + else + { // Far, calc damped velocity + _target_velocity = error * scale; + } + d.BodySetLinearVel(Body, _target_velocity.X, _target_velocity.Y, _target_velocity.Z); + } + } // end PID MoveToTarget + + /* Original OS implementation: Does not work correctly as another phys object resting on THIS object purturbs its position. + This is incorrect behavior. llMoveToTarget must move the Body no matter what phys object is resting on it. + + //if (!d.BodyIsEnabled(Body)) //d.BodySetForce(Body, 0f, 0f, 0f); // no lock; for now it's only called from within Simulate() @@ -3559,6 +3680,7 @@ Console.WriteLine(" JointCreateFixed"); (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep) ); +if(frcount == 0) Console.WriteLine("PID {0} b={1} fz={2} vel={3}", m_primName, m_buoyancy, fz, _target_velocity); // if velocity is zero, use position control; otherwise, velocity control if (_target_velocity.ApproxEquals(Vector3.Zero,0.1f)) @@ -3591,9 +3713,11 @@ Console.WriteLine(" JointCreateFixed"); fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass); } } // end if (m_usePID) - + End of old PID system */ + + /// Dynamics Hover =================================================================================== - // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller + // Hover PID Controller can only run if the PIDcontroller is not in use. if (m_useHoverPID && !m_usePID) { //Console.WriteLine("Hover " + m_primName); @@ -3709,14 +3833,14 @@ Console.WriteLine(" JointCreateFixed"); // d.BodyAddRelTorque(Body, rotforce.X, rotforce.Y, rotforce.Z); RLAservo = timestep / m_APIDStrength * scaler; rotforce = rotforce * RLAservo * diff_angle ; - + /* if (m_angularEnable.X == 0) rotforce.X = 0; if (m_angularEnable.Y == 0) rotforce.Y = 0; if (m_angularEnable.Z == 0) rotforce.Z = 0; - + */ d.BodySetAngularVel (Body, rotforce.X, rotforce.Y, rotforce.Z); //Console.WriteLine("axis= " + diff_axis + " angle= " + diff_angle + "servo= " + RLAservo); } @@ -3763,11 +3887,12 @@ Console.WriteLine(" JointCreateFixed"); fy = nmin; d.BodyAddForce(Body, fx, fy, fz); //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); - } - } - } - else - { // is not physical, or is not a body or is selected + } // end apply forces + } // end Dynamics + +/* obsolete? + else + { // is not physical, or is not a body or is selected // from old UpdatePositionAndVelocity, ... Not a body.. so Make sure the client isn't interpolating _velocity.X = 0; _velocity.Y = 0; @@ -3781,8 +3906,11 @@ Console.WriteLine(" JointCreateFixed"); m_rotationalVelocity.Y = 0; m_rotationalVelocity.Z = 0; _zeroFlag = true; - return; - } - } // end Move() + return; + } + */ + } // end root prims + + } // end Move() } // end class } -- cgit v1.1 From 5f60eb136e274d94806adf6645c3ed3a69ed28e0 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 8 Jun 2010 21:12:01 +0100 Subject: Improve instructions for [Groups] setup in OpenSim.ini.example --- bin/OpenSim.ini.example | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 37c0192..aeece9c 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -1290,39 +1290,42 @@ [Groups] Enabled = false - ; This is the current groups stub in Region.CoreModules.Avatar.Groups + ; This is the current groups stub in Region.CoreModules.Avatar.Groups. All the other settings below only really + ; apply to the Flotsam/SimianGrid GroupsModule Module = Default - ; The PHP code for the server is available from the Flotsam project for you to deploy - ; to your own server. The Flotsam project is located at http://code.google.com/p/flotsam/ - ; + ; This module can use a PHP XmlRpc server from the Flotsam project at http://code.google.com/p/flotsam/ + ; or from the SimianGrid project at http://code.google.com/p/openmetaverse ;Module = GroupsModule ; Enable Group Notices - ;NoticesEnabled = true + ;NoticesEnabled = true ; This makes the Groups modules very chatty on the console. DebugEnabled = false ; Specify which messaging module to use for groups messaging and if it's enabled ;MessagingModule = GroupsMessagingModule - ;MessagingEnabled = true + ;MessagingEnabled = true - ; Service connector to Groups Service [Select One] ServicesConnectorModule + ; Service connectors to the Groups Service. Select one depending on whether you're using a Flotsam XmlRpc backend or a SimianGrid backend + + ; SimianGrid Service for Groups + ;ServicesConnectorModule = SimianGroupsServicesConnector + ;GroupsServerURI = http://mygridserver.com:82/Grid/ - ; XmlRpc Service Connector to the Flotsam XmlRpc Groups Service settings + ; Flotsam XmlRpc Service for Groups ;ServicesConnectorModule = XmlRpcGroupsServicesConnector ;GroupsServerURI = http://yourxmlrpcserver.com/xmlrpc.php - ; XmlRpc Service Settings - ;XmlRpcServiceReadKey = 1234 - ;XmlRpcServiceWriteKey = 1234 + ; XmlRpc Security settings. These must match those set on your backend groups service. + ;XmlRpcServiceReadKey = 1234 + ;XmlRpcServiceWriteKey = 1234 ; Disables HTTP Keep-Alive for XmlRpcGroupsServicesConnector HTTP Requests, ; this is a work around fora problem discovered on some Windows based region servers. ; Only disable keep alive if you see a large number (dozens) of the following Exceptions: ; System.Net.WebException: The request was aborted: The request was canceled. - ; ; XmlRpcDisableKeepAlive = false -- cgit v1.1 From 491d898db8303c829d1e43f5c63afa05d6f6a445 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 9 Jun 2010 03:51:43 +0100 Subject: If a script is deleted before it gets compiled, don't even bother to try compiling it --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 98e77c0..f702e65 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -122,6 +122,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue(); IWorkItemResult m_CurrentCompile = null; + private Dictionary m_CompileDict = new Dictionary(); public string ScriptEngineName { @@ -492,6 +493,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine else { m_CompileQueue.Enqueue(parms); + lock (m_CompileDict) + { + m_CompileDict[itemID] = 0; + } if (m_CurrentCompile == null) { @@ -554,6 +559,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine bool postOnRez = (bool)p[4]; StateSource stateSource = (StateSource)p[5]; + lock(m_CompileDict) + { + if (!m_CompileDict.ContainsKey(itemID)) + return false; + m_CompileDict.Remove(itemID); + } + // Get the asset ID of the script, so we can check if we // already have it. @@ -794,6 +806,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine public void OnRemoveScript(uint localID, UUID itemID) { + // If it's not yet been compiled, make sure we don't try + lock (m_CompileDict) + { + if (m_CompileDict.ContainsKey(itemID)) + m_CompileDict.Remove(itemID); + } + lock (m_Scripts) { // Do we even have it? -- cgit v1.1 From 30d3ea3d4be1bed3001e2bda5890cce183c4f388 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 9 Jun 2010 17:00:24 +0100 Subject: Give attachments the same priority as other avatars in BestAvatarResponsiveness policy --- OpenSim/Region/Framework/Scenes/Prioritizer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index 4780cdd..7b7677b 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -210,7 +210,10 @@ namespace OpenSim.Region.Framework.Scenes { PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; if (physActor == null || !physActor.IsPhysical) - priority+=100; + priority += 100; + + if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) + priority = 1.0; } return priority; } -- cgit v1.1 From b3cf5ccf6d7fcfa2cb4a1405962b8fba73ae0119 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 11 Jun 2010 17:04:54 +0200 Subject: Clone cmGetAvatarList into osGetAvatarList for more generic use. --- .../Shared/Api/Implementation/OSSL_Api.cs | 27 ++++++++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | 1 + .../ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | 5 ++++ 3 files changed, 33 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index f2a2f32..0e86c86 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2206,5 +2206,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_LSL_Api.SetPrimitiveParamsEx(prim, rules); } + + /// + /// Like osGetAgents but returns enough info for a radar + /// + /// Strided list of the UUID, position and name of each avatar in the region + public LSL_List osGetAvatarList() + { + CheckThreatLevel(ThreatLevel.None, "osGetAvatarList"); + + LSL_List result = new LSL_List(); + World.ForEachScenePresence(delegate (ScenePresence avatar) + { + if (avatar != null && avatar.UUID != m_host.OwnerID) + { + if (avatar.IsChildAgent == false) + { + if (avatar.PhysicsActor != null && avatar.PhysicsActor.Position != null) + { + result.Add(avatar.UUID); + result.Add(avatar.PhysicsActor.Position); + result.Add(avatar.Name); + } + } + } + }); + return result; + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 1ab7f10..c8f3623 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -176,6 +176,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osCauseDamage(string avatar, double damage); LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); void osSetPrimitiveParams(LSL_Key prim, LSL_List rules); + LSL_List osGetAvatarList(); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 7af5d43..6cc5f51 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -687,5 +687,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osSetPrimitiveParams(prim, rules); } + + public LSL_List osGetAvatarList() + { + return m_OSSL_Functions.osGetAvatarList(); + } } } -- cgit v1.1 From 8d5cec5e0d8edb9fafce4df3235c05dbc46b9240 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 11 Jun 2010 17:08:18 +0200 Subject: Remove cmGetAvatarList() --- .../Shared/Api/Implementation/CM_Api.cs | 25 ---------------------- .../ScriptEngine/Shared/Api/Interface/ICM_Api.cs | 1 - .../ScriptEngine/Shared/Api/Runtime/CM_Stub.cs | 4 ---- 3 files changed, 30 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 4fb5c95..880ca1b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -113,31 +113,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Like osGetAgents but returns enough info for a radar - /// - /// Strided list of the UUID, position and name of each avatar in the region - public LSL_List cmGetAvatarList() - { - LSL_List result = new LSL_List(); - World.ForEachScenePresence(delegate (ScenePresence avatar) - { - if (avatar != null && avatar.UUID != m_host.OwnerID) - { - if (avatar.IsChildAgent == false) - { - if (avatar.PhysicsActor != null && avatar.PhysicsActor.Position != null) - { - result.Add(avatar.UUID); - result.Add(avatar.PhysicsActor.Position); - result.Add(avatar.Name); - } - } - } - }); - return result; - } - - /// /// Get the current Windlight scene /// /// List of windlight parameters diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs index fba27f9..f13b6e5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs @@ -44,6 +44,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_List cmGetWindlightScene(LSL_List rules); int cmSetWindlightScene(LSL_List rules); int cmSetWindlightSceneTargeted(LSL_List rules, key target); - LSL_List cmGetAvatarList(); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs index aaffbe4..c0edaae 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs @@ -72,9 +72,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_CM_Functions.cmSetWindlightSceneTargeted(rules, target); } - public LSL_List cmGetAvatarList() - { - return m_CM_Functions.cmGetAvatarList(); - } } } -- cgit v1.1 From 97d83c87ec27f355844016281ce1be156fe7cd3f Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 11 Jun 2010 17:23:06 +0200 Subject: Rename cm* function set to ls* (for LightShare) --- .../Shared/Api/Implementation/CM_Api.cs | 18 +++++++++--------- .../ScriptEngine/Shared/Api/Interface/ICM_Api.cs | 6 +++--- .../ScriptEngine/Shared/Api/Runtime/CM_Stub.cs | 21 ++++++++++++++++++--- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 880ca1b..9a99f5e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_localID = localID; m_itemID = itemID; - if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false)) + if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) m_CMFunctionsEnabled = true; m_comms = m_ScriptEngine.World.RequestModuleInterface(); @@ -116,11 +116,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Get the current Windlight scene /// /// List of windlight parameters - public LSL_List cmGetWindlightScene(LSL_List rules) + public LSL_List lsGetWindlightScene(LSL_List rules) { if (!m_CMFunctionsEnabled) { - CMShoutError("Careminster functions are not enabled."); + CMShoutError("LightShare functions are not enabled."); return new LSL_List(); } m_host.AddScriptLPS(1); @@ -440,16 +440,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// /// success: true or false - public int cmSetWindlightScene(LSL_List rules) + public int lsSetWindlightScene(LSL_List rules) { if (!m_CMFunctionsEnabled) { - CMShoutError("Careminster functions are not enabled."); + CMShoutError("LightShare functions are not enabled."); return 0; } if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) { - CMShoutError("cmSetWindlightScene can only be used by estate managers or owners."); + CMShoutError("lsSetWindlightScene can only be used by estate managers or owners."); return 0; } int success = 0; @@ -472,16 +472,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// /// success: true or false - public int cmSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) + public int lsSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) { if (!m_CMFunctionsEnabled) { - CMShoutError("Careminster functions are not enabled."); + CMShoutError("LightShare functions are not enabled."); return 0; } if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) { - CMShoutError("cmSetWindlightSceneTargeted can only be used by estate managers or owners."); + CMShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); return 0; } int success = 0; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs index f13b6e5..f47ae7d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs @@ -41,8 +41,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces public interface ICM_Api { // Windlight Functions - LSL_List cmGetWindlightScene(LSL_List rules); - int cmSetWindlightScene(LSL_List rules); - int cmSetWindlightSceneTargeted(LSL_List rules, key target); + LSL_List lsGetWindlightScene(LSL_List rules); + int lsSetWindlightScene(LSL_List rules); + int lsSetWindlightSceneTargeted(LSL_List rules, key target); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs index c0edaae..92c3d98 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs @@ -58,19 +58,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_CM_Functions = (ICM_Api)api; } + public LSL_List lsGetWindlightScene(LSL_List rules) + { + return m_CM_Functions.lsGetWindlightScene(rules); + } + + public int lsSetWindlightScene(LSL_List rules) + { + return m_CM_Functions.lsSetWindlightScene(rules); + } + + public int lsSetWindlightSceneTargeted(LSL_List rules, key target) + { + return m_CM_Functions.lsSetWindlightSceneTargeted(rules, target); + } + public LSL_List cmGetWindlightScene(LSL_List rules) { - return m_CM_Functions.cmGetWindlightScene(rules); + return m_CM_Functions.lsGetWindlightScene(rules); } public int cmSetWindlightScene(LSL_List rules) { - return m_CM_Functions.cmSetWindlightScene(rules); + return m_CM_Functions.lsSetWindlightScene(rules); } public int cmSetWindlightSceneTargeted(LSL_List rules, key target) { - return m_CM_Functions.cmSetWindlightSceneTargeted(rules, target); + return m_CM_Functions.lsSetWindlightSceneTargeted(rules, target); } } } -- cgit v1.1 From 10ef80cf153a9fd3d841a47a5033bb3c1344c39d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 11 Jun 2010 17:42:16 +0200 Subject: Rename CM files to LS --- .../Shared/Api/Implementation/CM_Api.cs | 504 --------------------- .../Shared/Api/Implementation/LS_Api.cs | 504 +++++++++++++++++++++ .../ScriptEngine/Shared/Api/Interface/ICM_Api.cs | 48 -- .../ScriptEngine/Shared/Api/Interface/ILS_Api.cs | 48 ++ .../ScriptEngine/Shared/Api/Runtime/CM_Stub.cs | 91 ---- .../ScriptEngine/Shared/Api/Runtime/LS_Stub.cs | 91 ++++ 6 files changed, 643 insertions(+), 643 deletions(-) delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILS_Api.cs delete mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs create mode 100644 OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs deleted file mode 100644 index 9a99f5e..0000000 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ /dev/null @@ -1,504 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.Remoting.Lifetime; -using OpenMetaverse; -using Nini.Config; -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.World.LightShare; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Region.ScriptEngine.Interfaces; -using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; - -using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; -using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; -using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; - -namespace OpenSim.Region.ScriptEngine.Shared.Api -{ - [Serializable] - public class CM_Api : MarshalByRefObject, ICM_Api, IScriptApi - { - internal IScriptEngine m_ScriptEngine; - internal SceneObjectPart m_host; - internal uint m_localID; - internal UUID m_itemID; - internal bool m_CMFunctionsEnabled = false; - internal IScriptModuleComms m_comms = null; - - public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) - { - m_ScriptEngine = ScriptEngine; - m_host = host; - m_localID = localID; - m_itemID = itemID; - - if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) - m_CMFunctionsEnabled = true; - - m_comms = m_ScriptEngine.World.RequestModuleInterface(); - if (m_comms == null) - m_CMFunctionsEnabled = false; - } - - public override Object InitializeLifetimeService() - { - ILease lease = (ILease)base.InitializeLifetimeService(); - - if (lease.CurrentState == LeaseState.Initial) - { - lease.InitialLeaseTime = TimeSpan.FromMinutes(0); - // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); - // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); - } - return lease; - } - - public Scene World - { - get { return m_ScriptEngine.World; } - } - - // - //Dumps an error message on the debug console. - // - - internal void CMShoutError(string message) - { - if (message.Length > 1023) - message = message.Substring(0, 1023); - - World.SimChat(Utils.StringToBytes(message), - ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); - - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); - } - - /// - /// Get the current Windlight scene - /// - /// List of windlight parameters - public LSL_List lsGetWindlightScene(LSL_List rules) - { - if (!m_CMFunctionsEnabled) - { - CMShoutError("LightShare functions are not enabled."); - return new LSL_List(); - } - m_host.AddScriptLPS(1); - RegionLightShareData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; - - LSL_List values = new LSL_List(); - int idx = 0; - while (idx < rules.Length) - { - uint rule = (uint)rules.GetLSLIntegerItem(idx); - LSL_List toadd = new LSL_List(); - - switch (rule) - { - case (int)ScriptBaseClass.WL_AMBIENT: - toadd.Add(new LSL_Rotation(wl.ambient.X, wl.ambient.Y, wl.ambient.Z, wl.ambient.W)); - break; - case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: - toadd.Add(new LSL_Vector(wl.bigWaveDirection.X, wl.bigWaveDirection.Y, 0.0f)); - break; - case (int)ScriptBaseClass.WL_BLUE_DENSITY: - toadd.Add(new LSL_Rotation(wl.blueDensity.X, wl.blueDensity.Y, wl.blueDensity.Z, wl.blueDensity.W)); - break; - case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: - toadd.Add(new LSL_Float(wl.blurMultiplier)); - break; - case (int)ScriptBaseClass.WL_CLOUD_COLOR: - toadd.Add(new LSL_Rotation(wl.cloudColor.X, wl.cloudColor.Y, wl.cloudColor.Z, wl.cloudColor.W)); - break; - case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: - toadd.Add(new LSL_Float(wl.cloudCoverage)); - break; - case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: - toadd.Add(new LSL_Vector(wl.cloudDetailXYDensity.X, wl.cloudDetailXYDensity.Y, wl.cloudDetailXYDensity.Z)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCALE: - toadd.Add(new LSL_Float(wl.cloudScale)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: - toadd.Add(new LSL_Float(wl.cloudScrollX)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: - toadd.Add(new LSL_Integer(wl.cloudScrollXLock ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: - toadd.Add(new LSL_Float(wl.cloudScrollY)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: - toadd.Add(new LSL_Integer(wl.cloudScrollYLock ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: - toadd.Add(new LSL_Vector(wl.cloudXYDensity.X, wl.cloudXYDensity.Y, wl.cloudXYDensity.Z)); - break; - case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: - toadd.Add(new LSL_Float(wl.densityMultiplier)); - break; - case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: - toadd.Add(new LSL_Float(wl.distanceMultiplier)); - break; - case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: - toadd.Add(new LSL_Integer(wl.drawClassicClouds ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_EAST_ANGLE: - toadd.Add(new LSL_Float(wl.eastAngle)); - break; - case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: - toadd.Add(new LSL_Float(wl.fresnelOffset)); - break; - case (int)ScriptBaseClass.WL_FRESNEL_SCALE: - toadd.Add(new LSL_Float(wl.fresnelScale)); - break; - case (int)ScriptBaseClass.WL_HAZE_DENSITY: - toadd.Add(new LSL_Float(wl.hazeDensity)); - break; - case (int)ScriptBaseClass.WL_HAZE_HORIZON: - toadd.Add(new LSL_Float(wl.hazeHorizon)); - break; - case (int)ScriptBaseClass.WL_HORIZON: - toadd.Add(new LSL_Rotation(wl.horizon.X, wl.horizon.Y, wl.horizon.Z, wl.horizon.W)); - break; - case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: - toadd.Add(new LSL_Vector(wl.littleWaveDirection.X, wl.littleWaveDirection.Y, 0.0f)); - break; - case (int)ScriptBaseClass.WL_MAX_ALTITUDE: - toadd.Add(new LSL_Integer(wl.maxAltitude)); - break; - case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: - toadd.Add(new LSL_Key(wl.normalMapTexture.ToString())); - break; - case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: - toadd.Add(new LSL_Vector(wl.reflectionWaveletScale.X, wl.reflectionWaveletScale.Y, wl.reflectionWaveletScale.Z)); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: - toadd.Add(new LSL_Float(wl.refractScaleAbove)); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: - toadd.Add(new LSL_Float(wl.refractScaleBelow)); - break; - case (int)ScriptBaseClass.WL_SCENE_GAMMA: - toadd.Add(new LSL_Float(wl.sceneGamma)); - break; - case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: - toadd.Add(new LSL_Float(wl.starBrightness)); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: - toadd.Add(new LSL_Float(wl.sunGlowFocus)); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: - toadd.Add(new LSL_Float(wl.sunGlowSize)); - break; - case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: - toadd.Add(new LSL_Rotation(wl.sunMoonColor.X, wl.sunMoonColor.Y, wl.sunMoonColor.Z, wl.sunMoonColor.W)); - break; - case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: - toadd.Add(new LSL_Float(wl.underwaterFogModifier)); - break; - case (int)ScriptBaseClass.WL_WATER_COLOR: - toadd.Add(new LSL_Vector(wl.waterColor.X, wl.waterColor.Y, wl.waterColor.Z)); - break; - case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: - toadd.Add(new LSL_Float(wl.waterFogDensityExponent)); - break; - } - - if (toadd.Length > 0) - { - values.Add(rule); - values.Add(toadd.Data[0]); - } - idx++; - } - - - return values; - - } - - private RegionLightShareData getWindlightProfileFromRules(LSL_List rules) - { - RegionLightShareData wl = (RegionLightShareData)m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.Clone(); - - LSL_List values = new LSL_List(); - int idx = 0; - while (idx < rules.Length) - { - uint rule = (uint)rules.GetLSLIntegerItem(idx); - LSL_Types.Quaternion iQ; - LSL_Types.Vector3 iV; - switch (rule) - { - case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: - idx++; - wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_AMBIENT: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_BLUE_DENSITY: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: - idx++; - wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: - idx++; - wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCALE: - idx++; - wl.cloudScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: - idx++; - wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: - idx++; - wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: - idx++; - wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: - idx++; - wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: - idx++; - wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: - idx++; - wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: - idx++; - wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_EAST_ANGLE: - idx++; - wl.eastAngle = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: - idx++; - wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_SCALE: - idx++; - wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_DENSITY: - idx++; - wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_HORIZON: - idx++; - wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HORIZON: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_MAX_ALTITUDE: - idx++; - wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; - break; - case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: - idx++; - wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); - break; - case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: - idx++; - iV = rules.GetVector3Item(idx); - wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: - idx++; - wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: - idx++; - wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SCENE_GAMMA: - idx++; - wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: - idx++; - wl.starBrightness = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: - idx++; - wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: - idx++; - wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: - idx++; - wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_WATER_COLOR: - idx++; - iV = rules.GetVector3Item(idx); - wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: - idx++; - wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); - break; - } - idx++; - } - return wl; - } - /// - /// Set the current Windlight scene - /// - /// - /// success: true or false - public int lsSetWindlightScene(LSL_List rules) - { - if (!m_CMFunctionsEnabled) - { - CMShoutError("LightShare functions are not enabled."); - return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - CMShoutError("lsSetWindlightScene can only be used by estate managers or owners."); - return 0; - } - int success = 0; - m_host.AddScriptLPS(1); - if (LightShareModule.EnableWindlight) - { - RegionLightShareData wl = getWindlightProfileFromRules(rules); - m_host.ParentGroup.Scene.StoreWindlightProfile(wl); - success = 1; - } - else - { - CMShoutError("Windlight module is disabled"); - return 0; - } - return success; - } - /// - /// Set the current Windlight scene to a target avatar - /// - /// - /// success: true or false - public int lsSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) - { - if (!m_CMFunctionsEnabled) - { - CMShoutError("LightShare functions are not enabled."); - return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - CMShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); - return 0; - } - int success = 0; - m_host.AddScriptLPS(1); - if (LightShareModule.EnableWindlight) - { - RegionLightShareData wl = getWindlightProfileFromRules(rules); - World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); - success = 1; - } - else - { - CMShoutError("Windlight module is disabled"); - return 0; - } - return success; - } - - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs new file mode 100644 index 0000000..fe71ed5 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -0,0 +1,504 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using OpenMetaverse; +using Nini.Config; +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.World.LightShare; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.ScriptEngine.Shared; +using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; +using OpenSim.Region.ScriptEngine.Shared.ScriptBase; +using OpenSim.Region.ScriptEngine.Interfaces; +using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; + +using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; +using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; +using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; +using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; +using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; + +namespace OpenSim.Region.ScriptEngine.Shared.Api +{ + [Serializable] + public class LS_Api : MarshalByRefObject, ILS_Api, IScriptApi + { + internal IScriptEngine m_ScriptEngine; + internal SceneObjectPart m_host; + internal uint m_localID; + internal UUID m_itemID; + internal bool m_LSFunctionsEnabled = false; + internal IScriptModuleComms m_comms = null; + + public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) + { + m_ScriptEngine = ScriptEngine; + m_host = host; + m_localID = localID; + m_itemID = itemID; + + if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) + m_LSFunctionsEnabled = true; + + m_comms = m_ScriptEngine.World.RequestModuleInterface(); + if (m_comms == null) + m_LSFunctionsEnabled = false; + } + + public override Object InitializeLifetimeService() + { + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.FromMinutes(0); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); + } + return lease; + } + + public Scene World + { + get { return m_ScriptEngine.World; } + } + + // + //Dumps an error message on the debug console. + // + + internal void LSShoutError(string message) + { + if (message.Length > 1023) + message = message.Substring(0, 1023); + + World.SimChat(Utils.StringToBytes(message), + ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); + } + + /// + /// Get the current Windlight scene + /// + /// List of windlight parameters + public LSL_List lsGetWindlightScene(LSL_List rules) + { + if (!m_LSFunctionsEnabled) + { + LSShoutError("LightShare functions are not enabled."); + return new LSL_List(); + } + m_host.AddScriptLPS(1); + RegionLightShareData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; + + LSL_List values = new LSL_List(); + int idx = 0; + while (idx < rules.Length) + { + uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_List toadd = new LSL_List(); + + switch (rule) + { + case (int)ScriptBaseClass.WL_AMBIENT: + toadd.Add(new LSL_Rotation(wl.ambient.X, wl.ambient.Y, wl.ambient.Z, wl.ambient.W)); + break; + case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: + toadd.Add(new LSL_Vector(wl.bigWaveDirection.X, wl.bigWaveDirection.Y, 0.0f)); + break; + case (int)ScriptBaseClass.WL_BLUE_DENSITY: + toadd.Add(new LSL_Rotation(wl.blueDensity.X, wl.blueDensity.Y, wl.blueDensity.Z, wl.blueDensity.W)); + break; + case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: + toadd.Add(new LSL_Float(wl.blurMultiplier)); + break; + case (int)ScriptBaseClass.WL_CLOUD_COLOR: + toadd.Add(new LSL_Rotation(wl.cloudColor.X, wl.cloudColor.Y, wl.cloudColor.Z, wl.cloudColor.W)); + break; + case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: + toadd.Add(new LSL_Float(wl.cloudCoverage)); + break; + case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: + toadd.Add(new LSL_Vector(wl.cloudDetailXYDensity.X, wl.cloudDetailXYDensity.Y, wl.cloudDetailXYDensity.Z)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCALE: + toadd.Add(new LSL_Float(wl.cloudScale)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: + toadd.Add(new LSL_Float(wl.cloudScrollX)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: + toadd.Add(new LSL_Integer(wl.cloudScrollXLock ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: + toadd.Add(new LSL_Float(wl.cloudScrollY)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: + toadd.Add(new LSL_Integer(wl.cloudScrollYLock ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: + toadd.Add(new LSL_Vector(wl.cloudXYDensity.X, wl.cloudXYDensity.Y, wl.cloudXYDensity.Z)); + break; + case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: + toadd.Add(new LSL_Float(wl.densityMultiplier)); + break; + case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: + toadd.Add(new LSL_Float(wl.distanceMultiplier)); + break; + case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: + toadd.Add(new LSL_Integer(wl.drawClassicClouds ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_EAST_ANGLE: + toadd.Add(new LSL_Float(wl.eastAngle)); + break; + case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: + toadd.Add(new LSL_Float(wl.fresnelOffset)); + break; + case (int)ScriptBaseClass.WL_FRESNEL_SCALE: + toadd.Add(new LSL_Float(wl.fresnelScale)); + break; + case (int)ScriptBaseClass.WL_HAZE_DENSITY: + toadd.Add(new LSL_Float(wl.hazeDensity)); + break; + case (int)ScriptBaseClass.WL_HAZE_HORIZON: + toadd.Add(new LSL_Float(wl.hazeHorizon)); + break; + case (int)ScriptBaseClass.WL_HORIZON: + toadd.Add(new LSL_Rotation(wl.horizon.X, wl.horizon.Y, wl.horizon.Z, wl.horizon.W)); + break; + case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: + toadd.Add(new LSL_Vector(wl.littleWaveDirection.X, wl.littleWaveDirection.Y, 0.0f)); + break; + case (int)ScriptBaseClass.WL_MAX_ALTITUDE: + toadd.Add(new LSL_Integer(wl.maxAltitude)); + break; + case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: + toadd.Add(new LSL_Key(wl.normalMapTexture.ToString())); + break; + case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: + toadd.Add(new LSL_Vector(wl.reflectionWaveletScale.X, wl.reflectionWaveletScale.Y, wl.reflectionWaveletScale.Z)); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: + toadd.Add(new LSL_Float(wl.refractScaleAbove)); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: + toadd.Add(new LSL_Float(wl.refractScaleBelow)); + break; + case (int)ScriptBaseClass.WL_SCENE_GAMMA: + toadd.Add(new LSL_Float(wl.sceneGamma)); + break; + case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: + toadd.Add(new LSL_Float(wl.starBrightness)); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: + toadd.Add(new LSL_Float(wl.sunGlowFocus)); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: + toadd.Add(new LSL_Float(wl.sunGlowSize)); + break; + case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: + toadd.Add(new LSL_Rotation(wl.sunMoonColor.X, wl.sunMoonColor.Y, wl.sunMoonColor.Z, wl.sunMoonColor.W)); + break; + case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: + toadd.Add(new LSL_Float(wl.underwaterFogModifier)); + break; + case (int)ScriptBaseClass.WL_WATER_COLOR: + toadd.Add(new LSL_Vector(wl.waterColor.X, wl.waterColor.Y, wl.waterColor.Z)); + break; + case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: + toadd.Add(new LSL_Float(wl.waterFogDensityExponent)); + break; + } + + if (toadd.Length > 0) + { + values.Add(rule); + values.Add(toadd.Data[0]); + } + idx++; + } + + + return values; + + } + + private RegionLightShareData getWindlightProfileFromRules(LSL_List rules) + { + RegionLightShareData wl = (RegionLightShareData)m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.Clone(); + + LSL_List values = new LSL_List(); + int idx = 0; + while (idx < rules.Length) + { + uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_Types.Quaternion iQ; + LSL_Types.Vector3 iV; + switch (rule) + { + case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: + idx++; + wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_AMBIENT: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_BLUE_DENSITY: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: + idx++; + wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: + idx++; + wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCALE: + idx++; + wl.cloudScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: + idx++; + wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: + idx++; + wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: + idx++; + wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: + idx++; + wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: + idx++; + wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: + idx++; + wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: + idx++; + wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_EAST_ANGLE: + idx++; + wl.eastAngle = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: + idx++; + wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_SCALE: + idx++; + wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_DENSITY: + idx++; + wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_HORIZON: + idx++; + wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HORIZON: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_MAX_ALTITUDE: + idx++; + wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; + break; + case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: + idx++; + wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); + break; + case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: + idx++; + iV = rules.GetVector3Item(idx); + wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: + idx++; + wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: + idx++; + wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SCENE_GAMMA: + idx++; + wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: + idx++; + wl.starBrightness = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: + idx++; + wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: + idx++; + wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: + idx++; + wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_WATER_COLOR: + idx++; + iV = rules.GetVector3Item(idx); + wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: + idx++; + wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); + break; + } + idx++; + } + return wl; + } + /// + /// Set the current Windlight scene + /// + /// + /// success: true or false + public int lsSetWindlightScene(LSL_List rules) + { + if (!m_LSFunctionsEnabled) + { + LSShoutError("LightShare functions are not enabled."); + return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); + return 0; + } + int success = 0; + m_host.AddScriptLPS(1); + if (LightShareModule.EnableWindlight) + { + RegionLightShareData wl = getWindlightProfileFromRules(rules); + m_host.ParentGroup.Scene.StoreWindlightProfile(wl); + success = 1; + } + else + { + LSShoutError("Windlight module is disabled"); + return 0; + } + return success; + } + /// + /// Set the current Windlight scene to a target avatar + /// + /// + /// success: true or false + public int lsSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) + { + if (!m_LSFunctionsEnabled) + { + LSShoutError("LightShare functions are not enabled."); + return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); + return 0; + } + int success = 0; + m_host.AddScriptLPS(1); + if (LightShareModule.EnableWindlight) + { + RegionLightShareData wl = getWindlightProfileFromRules(rules); + World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); + success = 1; + } + else + { + LSShoutError("Windlight module is disabled"); + return 0; + } + return success; + } + + } +} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs deleted file mode 100644 index f47ae7d..0000000 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System.Collections; -using OpenSim.Region.ScriptEngine.Interfaces; - -using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; -using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; -using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; - -namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces -{ - public interface ICM_Api - { - // Windlight Functions - LSL_List lsGetWindlightScene(LSL_List rules); - int lsSetWindlightScene(LSL_List rules); - int lsSetWindlightSceneTargeted(LSL_List rules, key target); - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILS_Api.cs new file mode 100644 index 0000000..9aa437b --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILS_Api.cs @@ -0,0 +1,48 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System.Collections; +using OpenSim.Region.ScriptEngine.Interfaces; + +using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; +using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; +using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; +using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; +using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; + +namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces +{ + public interface ILS_Api + { + // Windlight Functions + LSL_List lsGetWindlightScene(LSL_List rules); + int lsSetWindlightScene(LSL_List rules); + int lsSetWindlightSceneTargeted(LSL_List rules, key target); + } +} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs deleted file mode 100644 index 92c3d98..0000000 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Runtime.Remoting.Lifetime; -using System.Threading; -using System.Reflection; -using System.Collections; -using System.Collections.Generic; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.ScriptEngine.Interfaces; -using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; -using integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; -using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; -using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; -using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; - -namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase -{ - public partial class ScriptBaseClass : MarshalByRefObject - { - public ICM_Api m_CM_Functions; - - public void ApiTypeCM(IScriptApi api) - { - if (!(api is ICM_Api)) - return; - - m_CM_Functions = (ICM_Api)api; - } - - public LSL_List lsGetWindlightScene(LSL_List rules) - { - return m_CM_Functions.lsGetWindlightScene(rules); - } - - public int lsSetWindlightScene(LSL_List rules) - { - return m_CM_Functions.lsSetWindlightScene(rules); - } - - public int lsSetWindlightSceneTargeted(LSL_List rules, key target) - { - return m_CM_Functions.lsSetWindlightSceneTargeted(rules, target); - } - - public LSL_List cmGetWindlightScene(LSL_List rules) - { - return m_CM_Functions.lsGetWindlightScene(rules); - } - - public int cmSetWindlightScene(LSL_List rules) - { - return m_CM_Functions.lsSetWindlightScene(rules); - } - - public int cmSetWindlightSceneTargeted(LSL_List rules, key target) - { - return m_CM_Functions.lsSetWindlightSceneTargeted(rules, target); - } - } -} diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs new file mode 100644 index 0000000..8280ca5 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs @@ -0,0 +1,91 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Runtime.Remoting.Lifetime; +using System.Threading; +using System.Reflection; +using System.Collections; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.ScriptEngine.Interfaces; +using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; +using integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; +using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; +using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; +using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; +using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; +using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; + +namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase +{ + public partial class ScriptBaseClass : MarshalByRefObject + { + public ILS_Api m_LS_Functions; + + public void ApiTypeLS(IScriptApi api) + { + if (!(api is ILS_Api)) + return; + + m_LS_Functions = (ILS_Api)api; + } + + public LSL_List lsGetWindlightScene(LSL_List rules) + { + return m_LS_Functions.lsGetWindlightScene(rules); + } + + public int lsSetWindlightScene(LSL_List rules) + { + return m_LS_Functions.lsSetWindlightScene(rules); + } + + public int lsSetWindlightSceneTargeted(LSL_List rules, key target) + { + return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); + } + + public LSL_List cmGetWindlightScene(LSL_List rules) + { + return m_LS_Functions.lsGetWindlightScene(rules); + } + + public int cmSetWindlightScene(LSL_List rules) + { + return m_LS_Functions.lsSetWindlightScene(rules); + } + + public int cmSetWindlightSceneTargeted(LSL_List rules, key target) + { + return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); + } + } +} -- cgit v1.1 From ef93ac44528f5e3294e1674e33f100b19dee61f0 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 11 Jun 2010 17:48:33 +0200 Subject: Remove the cm* function namespace --- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs | 15 --------------- .../OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp | 2 +- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs index 8280ca5..f8dbe03 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs @@ -72,20 +72,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); } - - public LSL_List cmGetWindlightScene(LSL_List rules) - { - return m_LS_Functions.lsGetWindlightScene(rules); - } - - public int cmSetWindlightScene(LSL_List rules) - { - return m_LS_Functions.lsSetWindlightScene(rules); - } - - public int cmSetWindlightSceneTargeted(LSL_List rules, key target) - { - return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); - } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp index 23138ef..f02d2d9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp @@ -18,10 +18,10 @@ - + -- cgit v1.1 From be71a2e5bc321d82b373cd070681b5a6ffddc492 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 11 Jun 2010 17:52:19 +0200 Subject: Revert "Remove the cm* function namespace" This reverts commit ef93ac44528f5e3294e1674e33f100b19dee61f0. --- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs | 15 +++++++++++++++ .../OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs index f8dbe03..8280ca5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs @@ -72,5 +72,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); } + + public LSL_List cmGetWindlightScene(LSL_List rules) + { + return m_LS_Functions.lsGetWindlightScene(rules); + } + + public int cmSetWindlightScene(LSL_List rules) + { + return m_LS_Functions.lsSetWindlightScene(rules); + } + + public int cmSetWindlightSceneTargeted(LSL_List rules, key target) + { + return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp index f02d2d9..23138ef 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp @@ -18,10 +18,10 @@ + - -- cgit v1.1 From 8a084cb7e1998250c45781ed0cf04ca106ed0ada Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 11 Jun 2010 17:52:29 +0100 Subject: Remove a company name referecne from the example --- bin/OpenSim.ini.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 36937e4..a6ba72b 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -939,8 +939,8 @@ ; Allow the use of os* functions (some are dangerous) AllowOSFunctions = false - ; Allow the user of Careminster functions - AllowCareminsterFunctions = false + ; Allow the user of LightShare functions + AllowLightShareFunctions = false ; Threat level to allow, one of None, VeryLow, Low, Moderate, High, VeryHigh, Severe OSFunctionThreatLevel = VeryLow -- cgit v1.1 From 821b8a551700405059ae62c02ba1c6fd2ebf2a39 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 11 Jun 2010 18:43:02 +0100 Subject: remove SimianGrid Groups OpenSim.ini.example stuff that accidentally crept in through a cherry-pick --- bin/OpenSim.ini.example | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index aeece9c..c1c5639 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -1291,11 +1291,10 @@ Enabled = false ; This is the current groups stub in Region.CoreModules.Avatar.Groups. All the other settings below only really - ; apply to the Flotsam/SimianGrid GroupsModule + ; apply to the Flotsam GroupsModule Module = Default ; This module can use a PHP XmlRpc server from the Flotsam project at http://code.google.com/p/flotsam/ - ; or from the SimianGrid project at http://code.google.com/p/openmetaverse ;Module = GroupsModule ; Enable Group Notices @@ -1308,13 +1307,7 @@ ;MessagingModule = GroupsMessagingModule ;MessagingEnabled = true - ; Service connectors to the Groups Service. Select one depending on whether you're using a Flotsam XmlRpc backend or a SimianGrid backend - - ; SimianGrid Service for Groups - ;ServicesConnectorModule = SimianGroupsServicesConnector - ;GroupsServerURI = http://mygridserver.com:82/Grid/ - - ; Flotsam XmlRpc Service for Groups + ; Flotsam XmlRpc Service for Groups. Uncomment these settings and change accordingly if you are using this backend groups service ;ServicesConnectorModule = XmlRpcGroupsServicesConnector ;GroupsServerURI = http://yourxmlrpcserver.com/xmlrpc.php @@ -1410,4 +1403,4 @@ ; to use to send XMLRPC requests to that script ;XmlRpcRouterModule = "XmlRpcRouterModule" - ;XmlRpcPort = 20800 + oXmlRpcPort = 20800 -- cgit v1.1 From 85c20e149364dba6f171db1d2018c2149c6b102f Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Fri, 11 Jun 2010 19:40:09 +0100 Subject: revert group membership checking to older code pending resolution of reported performance problems --- .../Region/CoreModules/World/Permissions/PermissionsModule.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 53556ab..91ce362 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -414,6 +414,16 @@ namespace OpenSim.Region.CoreModules.World.Permissions //DateTime t1 = DateTime.Now; bool result = false; + ScenePresence sp = m_scene.GetScenePresence(userID); + if (sp != null) + { + IClientAPI client = sp.ControllingClient; + + result = ((groupID == client.ActiveGroupId) && (client.ActiveGroupPowers != 0) && + ((powers == 0) || ((client.ActiveGroupPowers & powers) == powers))); + } + + /* if (null != m_groupsModule) { GroupMembershipData gmd = m_groupsModule.GetMembershipData(groupID, userID); @@ -424,6 +434,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions result = true; } } + */ //m_log.DebugFormat("[PERMISSIONS]: Group member check took {0}", (DateTime.Now - t1).TotalMilliseconds); -- cgit v1.1 From 57a60282f5746a3aa73c0cac34059fbdbd319c0c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 12 Jun 2010 06:57:10 +0100 Subject: Don't filre CHANGED_INVENTORY if a prim comes in from storage --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index c4cff12..c3cdca8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -681,7 +681,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (TaskInventoryItem item in items) { m_items.Add(item.ItemID, item); - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); +// m_part.TriggerScriptChangedEvent(Changed.INVENTORY); } m_items.LockItemsForWrite(false); -- cgit v1.1 From e337c9130f8e25f81d9d9c9d98da8dee89f38aeb Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 12 Jun 2010 07:34:22 +0200 Subject: Make local teleports send CHANGED_TELEPORT --- .../CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 3 +++ .../Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 266621f..5e2c04c 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -180,6 +180,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); sp.Teleport(position); + + foreach (SceneObjectGroup grp in sp.Attachments) + sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT); } else // Another region possibly in another simulator { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp index 23138ef..f02d2d9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp @@ -18,10 +18,10 @@ - + -- cgit v1.1 From 03a48f87e418e79ca780b29a696e5e878213e7ef Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 12 Jun 2010 08:29:20 +0200 Subject: Preserving the link numbers is a serializer's highest duty. Prevent region crossings from screwing up complex attachments by preserving link numbers. --- .../Framework/Scenes/Serialization/SceneObjectSerializer.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index f7544ac..5bdaa17 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -221,7 +221,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization sr = new StringReader(parts[i].OuterXml); reader = new XmlTextReader(sr); SceneObjectPart part = SceneObjectPart.FromXml(reader); + + int originalLinkNum = part.LinkNum; + sceneObject.AddPart(part); + + // SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum. + // We override that here + if (originalLinkNum != 0) + part.LinkNum = originalLinkNum; + part.StoreUndoState(); reader.Close(); sr.Close(); -- cgit v1.1 From 3ea11fe2e6593fe0455a7c5bf842deca307f373e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 12 Jun 2010 04:35:51 -0700 Subject: Get rid of spamming SOG debug message --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 66ad14f..c7d21bb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2230,8 +2230,8 @@ namespace OpenSim.Region.Framework.Scenes ///
public void ScheduleGroupForFullUpdate() { - if (IsAttachment) - m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); + //if (IsAttachment) + // m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); checkAtTargets(); RootPart.ScheduleFullUpdate(); -- cgit v1.1 From f59e272643a92b20e7f7eb97f54a30c8b045725d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 13 Jun 2010 22:21:05 +0200 Subject: Introduce SOP.UpdateSitters() to update sitting avatars' chat position if needed --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 9 +++++++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c7d21bb..6f68029 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2174,6 +2174,7 @@ namespace OpenSim.Region.Framework.Scenes { m_rootPart.UpdateFlag = 1; lastPhysGroupPos = AbsolutePosition; + UpdateSitters(); } if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) @@ -3832,6 +3833,14 @@ namespace OpenSim.Region.Framework.Scenes } } + private void UpdateSitters() + { + foreach (SceneObjectPart part in Children.Values) + { + part.UpdateSitter(); + } + } + public override string ToString() { return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index e4a36ef..705e0a3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4720,5 +4720,13 @@ namespace OpenSim.Region.Framework.Scenes Inventory.UpdateInventoryItem(item); } } + + public void UpdateSitter() + { + if (m_sitTargetAvatar != UUID.Zero) + return; + + // Update sitting avatar chat position + } } } -- cgit v1.1 From 3d319d6c3ff2bded0f4b6c730f227a490dd2fb2e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 13 Jun 2010 22:23:07 +0200 Subject: Actually update the SP. EXPERIMENTAL --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 705e0a3..a83119e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4726,7 +4726,13 @@ namespace OpenSim.Region.Framework.Scenes if (m_sitTargetAvatar != UUID.Zero) return; + ScenePresence p = m_parentGroup.Scene.GetScenePresence(m_sitTargetAvatar); + if (p == null) + return; + // Update sitting avatar chat position + + p.AbsolutePosition = AbsolutePosition; } } } -- cgit v1.1 From 520b0e131c43e97d4a08c8ed93a32228ab61a99e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 13 Jun 2010 22:37:11 +0200 Subject: Try to make prims stop moving. Reset velocity, etc, unconditionally. Although the phys actor may be new, the prim fields could still be set and the slimupdates system would continue sending that data out. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index a83119e..be2bbc5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1738,7 +1738,7 @@ namespace OpenSim.Region.Framework.Scenes // which stops client-side interpolation of deactivated joint proxy objects. } - if (!UsePhysics && !isNew) + if (!UsePhysics) { // reset velocity to 0 on physics switch-off. Without that, the client thinks the // prim still has velocity and continues to interpolate its position along the old -- cgit v1.1 From 305876180690e5c236d6bda60a6173a16ad5edc8 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 13 Jun 2010 22:43:14 +0200 Subject: D.U.H. un-reverse a reversed condition --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index be2bbc5..c3e87b7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4723,7 +4723,7 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateSitter() { - if (m_sitTargetAvatar != UUID.Zero) + if (m_sitTargetAvatar == UUID.Zero) return; ScenePresence p = m_parentGroup.Scene.GetScenePresence(m_sitTargetAvatar); -- cgit v1.1 From d520360cb83bb3f7733228ff74cf083b0855b261 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 13 Jun 2010 23:01:15 +0200 Subject: Try it witht he root prim --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index c3e87b7..68681c9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4732,7 +4732,7 @@ namespace OpenSim.Region.Framework.Scenes // Update sitting avatar chat position - p.AbsolutePosition = AbsolutePosition; + p.AbsolutePosition = GroupPosition; } } } -- cgit v1.1 From 62763cc0fb80caae199ea03d2cb8d031924c111e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 14 Jun 2010 00:02:17 +0200 Subject: Report current position instead of position at the time we sat down --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 68681c9..91b7d35 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4732,7 +4732,7 @@ namespace OpenSim.Region.Framework.Scenes // Update sitting avatar chat position - p.AbsolutePosition = GroupPosition; + p.AbsolutePosition = GroupPosition + OffsetPosition + m_sitTargetPosition; } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b6f67f7..7a7816a 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -466,6 +466,13 @@ namespace OpenSim.Region.Framework.Scenes if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting! m_pos = actor.Position; + // If we're sitting, we need to update our position + if (m_parentID == 0) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); + m_parentPosition = part.AbsolutePosition; + } + return m_parentPosition + m_pos; } set -- cgit v1.1 From 093cc047cd42f4cc3d59f365aa70cc196855e83f Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 14 Jun 2010 00:03:43 +0200 Subject: Revert "Try it witht he root prim" This reverts commit d520360cb83bb3f7733228ff74cf083b0855b261. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 91b7d35..c3e87b7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4732,7 +4732,7 @@ namespace OpenSim.Region.Framework.Scenes // Update sitting avatar chat position - p.AbsolutePosition = GroupPosition + OffsetPosition + m_sitTargetPosition; + p.AbsolutePosition = AbsolutePosition; } } } -- cgit v1.1 From 5fda89fdb5ca6569239412b7b2d38163b8b3b5ab Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 14 Jun 2010 00:04:02 +0200 Subject: Revert "D.U.H." This reverts commit 305876180690e5c236d6bda60a6173a16ad5edc8. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index c3e87b7..be2bbc5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4723,7 +4723,7 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateSitter() { - if (m_sitTargetAvatar == UUID.Zero) + if (m_sitTargetAvatar != UUID.Zero) return; ScenePresence p = m_parentGroup.Scene.GetScenePresence(m_sitTargetAvatar); -- cgit v1.1 From f9b4f5f594caf609d255c585c4224f0455403908 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 14 Jun 2010 00:05:01 +0200 Subject: Revert "Introduce SOP.UpdateSitters() to update sitting avatars' chat position if" This reverts commit f59e272643a92b20e7f7eb97f54a30c8b045725d. --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 9 --------- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 14 -------------- 2 files changed, 23 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 6f68029..c7d21bb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2174,7 +2174,6 @@ namespace OpenSim.Region.Framework.Scenes { m_rootPart.UpdateFlag = 1; lastPhysGroupPos = AbsolutePosition; - UpdateSitters(); } if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) @@ -3833,14 +3832,6 @@ namespace OpenSim.Region.Framework.Scenes } } - private void UpdateSitters() - { - foreach (SceneObjectPart part in Children.Values) - { - part.UpdateSitter(); - } - } - public override string ToString() { return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index be2bbc5..b80a557 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4720,19 +4720,5 @@ namespace OpenSim.Region.Framework.Scenes Inventory.UpdateInventoryItem(item); } } - - public void UpdateSitter() - { - if (m_sitTargetAvatar != UUID.Zero) - return; - - ScenePresence p = m_parentGroup.Scene.GetScenePresence(m_sitTargetAvatar); - if (p == null) - return; - - // Update sitting avatar chat position - - p.AbsolutePosition = AbsolutePosition; - } } } -- cgit v1.1 From 1532dbca0ae54ee6427153d7beec95b8cb52e1e3 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 14 Jun 2010 00:12:39 +0200 Subject: Guard against a potential nullref --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 7a7816a..9c507c2 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -470,7 +470,8 @@ namespace OpenSim.Region.Framework.Scenes if (m_parentID == 0) { SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); - m_parentPosition = part.AbsolutePosition; + if (part != null) + m_parentPosition = part.AbsolutePosition; } return m_parentPosition + m_pos; -- cgit v1.1 From 9b30f446729e16c165551ecf0756dedb85d8b269 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 14 Jun 2010 02:28:31 +0200 Subject: D.U.H. #2. Inverted test. Again. Argh! --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 9c507c2..6d2cd88 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -467,7 +467,7 @@ namespace OpenSim.Region.Framework.Scenes m_pos = actor.Position; // If we're sitting, we need to update our position - if (m_parentID == 0) + if (m_parentID != 0) { SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); if (part != null) -- cgit v1.1 From 704da8c8238835c63e8ca560fc7778603e9f6795 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 14 Jun 2010 04:03:54 -0700 Subject: osGetAvatarList: Use AbsolutePosition instead of the position of the physics actor, or the avatar disappears when they sit down. --- .../Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 0e86c86..db43902 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2222,12 +2222,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (avatar.IsChildAgent == false) { - if (avatar.PhysicsActor != null && avatar.PhysicsActor.Position != null) - { - result.Add(avatar.UUID); - result.Add(avatar.PhysicsActor.Position); - result.Add(avatar.Name); - } + result.Add(avatar.UUID); + result.Add(avatar.AbsolutePosition); + result.Add(avatar.Name); } } }); -- cgit v1.1 From ef1496ca2d22ad3d24bc9b53830a49f5a9c550d8 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 14 Jun 2010 04:28:38 -0700 Subject: Add "alert dialog" for sending dialogs to users from the console --- OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index b5c3176..4e36c5d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -55,6 +55,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog m_scene.AddCommand( this, "alert general", "alert general ", "Send an alert to everyone", HandleAlertConsoleCommand); + + m_scene.AddCommand( + this, "alert dialog", "alert dialog ", "Send a dialog alert to everyone", HandleAlertConsoleCommand); + + } public void PostInitialise() {} @@ -181,6 +186,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog "[DIALOG]: Sending general alert in region {0} with message {1}", m_scene.RegionInfo.RegionName, message); SendGeneralAlert(message); } + else if (cmdparams[1] == "dialog") + { + string message = CombineParams(cmdparams, 2); + + m_log.InfoFormat( + "[DIALOG]: Sending dialog alert in region {0} with message {1}", m_scene.RegionInfo.RegionName, message); + SendNotificationToUsersInRegion(UUID.Zero, "System", message); + } else { string firstName = cmdparams[1]; -- cgit v1.1 From 117fd629d68ef8ab373b70fd5e9e6a643e8eaa65 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 16 Jun 2010 08:32:47 -0700 Subject: Allow llMapDestination to be used in any event if the host is an attachment. This fixes Mantis 0000098. --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 9f3e354..c332fd8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9470,8 +9470,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_itemID, 0); - if (detectedParams == null) return; // only works on the first detected avatar - + if (detectedParams == null) + { + if (m_host.IsAttachment == true) + { + detectedParams = new DetectParams(); + detectedParams.Key = m_host.OwnerID; + } + else + { + return; + } + } + ScenePresence avatar = World.GetScenePresence(detectedParams.Key); if (avatar != null) { @@ -9479,6 +9490,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); } + ScriptSleep(1000); } -- cgit v1.1 From b9c40320f108a84d7841cdc9e98009cf650f930e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Wed, 16 Jun 2010 09:20:20 -0700 Subject: Fix llAttachToAvatar. This addresses mantis 128 . --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index c332fd8..877c3cb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3065,9 +3065,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - if (m_host.ParentGroup.RootPart.AttachmentPoint == 0) - return; - TaskInventoryItem item; m_host.TaskInventory.LockItemsForRead(true); @@ -3093,11 +3090,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(m_host.OwnerID); + /* IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; if (attachmentsModule != null) + { attachmentsModule.AttachObject( - presence.ControllingClient, grp.LocalId, + presence.ControllingClient, grp.LocalId, (uint)attachment, Quaternion.Identity, Vector3.Zero, false); + } + */ + grp.AttachToAgent(m_host.OwnerID, (uint)attachment, Vector3.Zero, false); } } -- cgit v1.1 From d1c8b083b8d44417d67fb401646eaa7215ff0851 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 17 Jun 2010 04:15:07 -0700 Subject: Fix llRot2Euler with a mathematically sound implementation. The only difference between this an SL is that SL resolves a figure of negative PI into PI, and does the equivalent in the reverse (llEuler2Rot, -1.0 becomes 1.0); --- .../Shared/Api/Implementation/LSL_Api.cs | 46 +++++++++++++--------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 877c3cb..fe8c70e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -502,25 +502,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return remainder; } - // Old implementation of llRot2Euler, now normalized - - public LSL_Vector llRot2Euler(LSL_Rotation r) - { - m_host.AddScriptLPS(1); - //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke - LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); - double m = (t.x + t.y + t.z + t.s); - if (m == 0) return new LSL_Vector(); - double n = 2 * (r.y * r.s + r.x * r.z); - double p = m * m - n * n; - if (p > 0) - 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))), - NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), - NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s)))); - else if (n > 0) - return new LSL_Vector(0.0, Math.PI * 0.5, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); - else - return new LSL_Vector(0.0, -Math.PI * 0.5, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); + public LSL_Vector llRot2Euler(LSL_Rotation q1) + { + m_host.AddScriptLPS(1); + LSL_Vector eul = new LSL_Vector(); + + double sqw = q1.s*q1.s; + double sqx = q1.x*q1.x; + double sqy = q1.z*q1.z; + double sqz = q1.y*q1.y; + double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor + double test = q1.x*q1.z + q1.y*q1.s; + if (test > 0.4999*unit) { // singularity at north pole + eul.z = 2 * Math.Atan2(q1.x,q1.s); + eul.y = Math.PI/2; + eul.x = 0; + return eul; + } + if (test < -0.4999*unit) { // singularity at south pole + eul.z = -2 * Math.Atan2(q1.x,q1.s); + eul.y = -Math.PI/2; + eul.x = 0; + return eul; + } + eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw); + eul.y = Math.Asin(2*test/unit); + eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw); + return eul; } /* From wiki: -- cgit v1.1 From 958c6c6fde45e41433452f44bf8e2e925153a24d Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 17 Jun 2010 13:04:18 -0400 Subject: Add rez on water surface. --- OpenSim/Region/Framework/Scenes/Scene.cs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b58bfb8..a88b87f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1967,14 +1967,24 @@ namespace OpenSim.Region.Framework.Scenes /// public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) { + + float wheight = (float)RegionInfo.RegionSettings.WaterHeight; + Vector3 wpos = Vector3.Zero; + // Check for water surface intersection from above + if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) ) + { + float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z); + wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X)); + wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y)); + wpos.Z = wheight; + } + Vector3 pos = Vector3.Zero; if (RayEndIsIntersection == (byte)1) { pos = RayEnd; - return pos; } - - if (RayTargetID != UUID.Zero) + else if (RayTargetID != UUID.Zero) { SceneObjectPart target = GetSceneObjectPart(RayTargetID); @@ -1996,7 +2006,7 @@ namespace OpenSim.Region.Framework.Scenes EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); // Un-comment out the following line to Get Raytrace results printed to the console. - // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); + // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); float ScaleOffset = 0.5f; // If we hit something @@ -2019,13 +2029,10 @@ namespace OpenSim.Region.Framework.Scenes //pos.Z -= 0.25F; } - - return pos; } else { // We don't have a target here, so we're going to raytrace all the objects in the scene. - EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); // Un-comment the following line to print the raytrace results to the console. @@ -2034,13 +2041,12 @@ namespace OpenSim.Region.Framework.Scenes if (ei.HitTF) { pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); - } else + } + else { // fall back to our stupid functionality pos = RayEnd; } - - return pos; } } else @@ -2051,8 +2057,12 @@ namespace OpenSim.Region.Framework.Scenes //increase height so its above the ground. //should be getting the normal of the ground at the rez point and using that? pos.Z += scale.Z / 2f; - return pos; +// return pos; } + + // check against posible water intercept + if (wpos.Z > pos.Z) pos = wpos; + return pos; } -- cgit v1.1 From 6d8da699b275cf9a52214de3b22256533b7bb784 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 19 Jun 2010 07:00:01 -0700 Subject: Add "AvatarHeight/2" to the Home Position when set to avoid having the avatar fall through the ground when they TP home. --- OpenSim/Region/Framework/Scenes/Scene.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 97de147..dc58d84 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3235,6 +3235,16 @@ namespace OpenSim.Region.Framework.Scenes /// public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) { + //Add half the avatar's height so that the user doesn't fall through prims + ScenePresence presence; + if (TryGetScenePresence(remoteClient.AgentId, out presence)) + { + if (presence.Appearance != null) + { + position.Z = position.Z + (presence.Appearance.AvatarHeight / 2); + } + } + if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); -- cgit v1.1 From 49d7d8534ccd037f4690c5ac6aecd66a460960df Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 19 Jun 2010 10:06:09 -0700 Subject: Allow moving an avatar as part of a linkset using llSetLinkPrimitiveParams. This unlocks an awful lot of poseball-free content, and is a step towards resolving mantis #59. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 56 ++++++++++++- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 39 ++++++++- .../Shared/Api/Implementation/LSL_Api.cs | 97 ++++++++++++++++++++++ 3 files changed, 188 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c7d21bb..3e92954 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -110,8 +110,8 @@ namespace OpenSim.Region.Framework.Scenes private long m_minPersistTime = 0; private Random m_rand; private bool m_suspendUpdates; - - private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); + private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); + private List m_linkedAvatars = new List(); public bool areUpdatesSuspended { @@ -1116,6 +1116,47 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Add the avatar to this linkset (avatar is sat). + /// + /// + public void AddAvatar(UUID agentID) + { + ScenePresence presence; + if (m_scene.TryGetScenePresence(agentID, out presence)) + { + if (!m_linkedAvatars.Contains(presence)) + { + m_linkedAvatars.Add(presence); + } + } + } + + /// + /// Delete the avatar from this linkset (avatar is unsat). + /// + /// + public void DeleteAvatar(UUID agentID) + { + ScenePresence presence; + if (m_scene.TryGetScenePresence(agentID, out presence)) + { + if (m_linkedAvatars.Contains(presence)) + { + m_linkedAvatars.Remove(presence); + } + } + } + + /// + /// Returns the list of linked presences (avatars sat on this group) + /// + /// + public List GetLinkedAvatars() + { + return m_linkedAvatars; + } + + /// /// Attach this scene object to the given avatar. /// /// @@ -2974,6 +3015,17 @@ namespace OpenSim.Region.Framework.Scenes } } + + + /// + /// Gets the number of parts + /// + /// + public int GetPartCount() + { + return Children.Count; + } + /// /// Get the parts of this scene object /// diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index d4fc6cd..76267ab 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -219,6 +219,7 @@ namespace OpenSim.Region.Framework.Scenes //PauPaw:Proper PID Controler for autopilot************ private bool m_moveToPositionInProgress; private Vector3 m_moveToPositionTarget; + private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); private bool m_followCamAuto; @@ -537,10 +538,39 @@ namespace OpenSim.Region.Framework.Scenes } } + public Quaternion OffsetRotation + { + get { return m_offsetRotation; } + set { m_offsetRotation = value; } + } + public Quaternion Rotation { - get { return m_bodyRot; } - set { m_bodyRot = value; } + get { + if (m_parentID != 0) + { + if (m_offsetRotation != null) + { + return m_offsetRotation; + } + else + { + return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + + } + else + { + return m_bodyRot; + } + } + set { + m_bodyRot = value; + if (m_parentID != 0) + { + m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + } } public Quaternion PreviousRotation @@ -1795,6 +1825,7 @@ namespace OpenSim.Region.Framework.Scenes Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset! AbsolutePosition = avWorldStandUp; //KF: Fix stand up. part.IsOccupied = false; + part.ParentGroup.DeleteAvatar(ControllingClient.AgentId); } else { @@ -1804,6 +1835,7 @@ namespace OpenSim.Region.Framework.Scenes m_parentPosition = Vector3.Zero; m_parentID = 0; + m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); SendFullUpdateToAllClients(); m_requestedSitTargetID = 0; @@ -1904,6 +1936,7 @@ namespace OpenSim.Region.Framework.Scenes part.SetAvatarOnSitTarget(UUID); // set that Av will be on it offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one sitOrientation = avSitOrientation; // Change rotatione to the scripted one + OffsetRotation = avSitOrientation; autopilot = false; // Jump direct to scripted llSitPos() } else @@ -2311,6 +2344,7 @@ namespace OpenSim.Region.Framework.Scenes m_bodyRot = sitTargetOrient; m_parentPosition = part.AbsolutePosition; part.IsOccupied = true; + part.ParentGroup.AddAvatar(agentID); Console.WriteLine("Scripted Sit ofset {0}", m_pos); } else @@ -2341,6 +2375,7 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); m_parentPosition = part.AbsolutePosition; part.IsOccupied = true; + part.ParentGroup.AddAvatar(agentID); m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) + diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index fe8c70e..61c5add 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -219,6 +219,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + public List GetLinkAvatars(int linkType) + { + List ret = new List(); + if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) + return ret; + + List avs = m_host.ParentGroup.GetLinkedAvatars(); + + switch (linkType) + { + case ScriptBaseClass.LINK_SET: + return avs; + + case ScriptBaseClass.LINK_ROOT: + return ret; + + case ScriptBaseClass.LINK_ALL_OTHERS: + return avs; + + case ScriptBaseClass.LINK_ALL_CHILDREN: + return avs; + + case ScriptBaseClass.LINK_THIS: + return ret; + + default: + if (linkType < 0) + return ret; + + int partCount = m_host.ParentGroup.GetPartCount(); + + if (linkType <= partCount) + { + return ret; + } + else + { + linkType = linkType - partCount; + if (linkType > avs.Count) + { + return ret; + } + else + { + ret.Add(avs[linkType-1]); + return ret; + } + } + } + } + public List GetLinkParts(int linkType) { List ret = new List(); @@ -7152,6 +7203,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); + List avatars = GetLinkAvatars(linknumber); if (parts.Count>0) { try @@ -7165,6 +7217,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api parts[0].ParentGroup.areUpdatesSuspended = false; } } + if (avatars.Count > 0) + { + foreach (ScenePresence avatar in avatars) + SetPrimParams(avatar, rules); + } } public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) @@ -7172,6 +7229,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api llSetLinkPrimitiveParams(linknumber, rules); } + protected void SetPrimParams(ScenePresence av, LSL_List rules) + { + //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. + //We only support PRIM_POSITION and PRIM_ROTATION + + int idx = 0; + + while (idx < rules.Length) + { + int code = rules.GetLSLIntegerItem(idx++); + + int remain = rules.Length - idx; + + + + switch (code) + { + case (int)ScriptBaseClass.PRIM_POSITION: + if (remain < 1) + return; + LSL_Vector v; + v = rules.GetVector3Item(idx++); + av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); + av.SendFullUpdateToAllClients(); + + break; + + case (int)ScriptBaseClass.PRIM_ROTATION: + if (remain < 1) + return; + LSL_Rotation r; + r = rules.GetQuaternionItem(idx++); + av.OffsetRotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); + av.SendFullUpdateToAllClients(); + break; + } + } + + } + protected void SetPrimParams(SceneObjectPart part, LSL_List rules) { if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) -- cgit v1.1 From 76b59b8df776121708b7ff93312c25c341b19ea6 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 20 Jun 2010 06:23:08 +0200 Subject: Make dataserver() return a 0 when agent id offline, instead of a timeout --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 61c5add..5c6d382 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4232,22 +4232,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID uuid = (UUID)id; UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); + if (account == null) + return UUID.Zero.ToString(); + PresenceInfo pinfo = null; PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); if (pinfos != null && pinfos.Length > 0) pinfo = pinfos[0]; - if (pinfo == null) - return UUID.Zero.ToString(); - string reply = String.Empty; switch (data) { case 1: // DATA_ONLINE (0|1) - // TODO: implement fetching of this information - if (pinfo != null) + if (pinfo != null && pinfo.RegionID != UUID.Zero) reply = "1"; else reply = "0"; -- cgit v1.1 From 95c763201f6f777557bc1c88e4bcbfbfd0aeebda Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 20 Jun 2010 06:36:46 +0200 Subject: Set the offline flag in inventory offers --- .../CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 2f1e9dd..0d04491 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -241,6 +241,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer im.imSessionID = itemID.Guid; } + im.offline = 1; // Remember these + // Send the IM to the recipient. The item is already // in their inventory, so it will not be lost if // they are offline. -- cgit v1.1 From 797767da57be98da24bd91b61eb5b35fc242bb3c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 20 Jun 2010 07:16:19 +0200 Subject: Insert a space after the comma on the ToString methos of lsl vectors and rotations to match SL. --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 1ea52c5..212dbe3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -83,19 +83,19 @@ namespace OpenSim.Region.ScriptEngine.Shared public override string ToString() { - string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", x, y, z); + string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", x, y, z); return s; } public static explicit operator LSLString(Vector3 vec) { - string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); + string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z); return new LSLString(s); } public static explicit operator string(Vector3 vec) { - string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000}>", vec.x, vec.y, vec.z); + string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}>", vec.x, vec.y, vec.z); return s; } @@ -337,19 +337,19 @@ namespace OpenSim.Region.ScriptEngine.Shared public override string ToString() { - string st=String.Format(Culture.FormatProvider, "<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", x, y, z, s); + string st=String.Format(Culture.FormatProvider, "<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", x, y, z, s); return st; } public static explicit operator string(Quaternion r) { - string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); + string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s); return s; } public static explicit operator LSLString(Quaternion r) { - string s=String.Format("<{0:0.000000},{1:0.000000},{2:0.000000},{3:0.000000}>", r.x, r.y, r.z, r.s); + string s=String.Format("<{0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000}>", r.x, r.y, r.z, r.s); return new LSLString(s); } -- cgit v1.1 From 13a0b65a804349e41b8e692727068ac6580c0d35 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 20 Jun 2010 21:38:06 +0200 Subject: Modify avatar responsiveness policy to send roots before children --- OpenSim/Region/Framework/Scenes/Prioritizer.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index 7b7677b..b95b5f2 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -208,12 +208,19 @@ namespace OpenSim.Region.Framework.Scenes if (entity is SceneObjectPart) { - PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; - if (physActor == null || !physActor.IsPhysical) - priority += 100; - if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) + { priority = 1.0; + } + else + { + PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; + if (physActor == null || !physActor.IsPhysical) + priority += 100; + } + + if (((SceneObjectPart)entity).ParentGroup.RootPart != (SceneObjectPart)entity) + priority +=1; } return priority; } -- cgit v1.1 From a1416612a9f9e0d5cbe1c1f02d313e9be020226d Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 20 Jun 2010 14:45:04 -0700 Subject: Update all clients sitting on a linkset if a child prim is moved. This prevents avatars being "lost in the void" until they stand up when a child prim is moved that they're sitting on. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b80a557..78faa01 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -711,6 +711,12 @@ namespace OpenSim.Region.Framework.Scenes // Tell the physics engines that this prim changed. m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); } + + List avs = ParentGroup.GetLinkedAvatars(); + foreach (ScenePresence av in avs) + { + av.SendFullUpdateToAllClients(); + } } } } -- cgit v1.1 From fc715a092c9b48ddfbf75eb35e1a052885aecbff Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 20 Jun 2010 15:38:48 -0700 Subject: Fix the sit code to ensure that we use the root prim of a linkset as a reference in the case of an avatar sitting on a child prim. This fixes various camera issues and fixes mantis #0000059. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 76267ab..472c389 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1766,7 +1766,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_parentID != 0) { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); + SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); if (part != null) { part.TaskInventory.LockItemsForRead(true); @@ -2028,7 +2028,9 @@ namespace OpenSim.Region.Framework.Scenes //Console.WriteLine("Camera At ={0}", cameraAtOffset); //Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); - ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); + //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child + ControllingClient.SendSitResponse(part.ParentGroup.UUID, offsetr + part.OffsetPosition, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); + m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target // This calls HandleAgentSit twice, once from here, and the client calls // HandleAgentSit itself after it gets to the location @@ -2398,7 +2400,17 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); return; } } - m_parentID = m_requestedSitTargetID; + + //We want our offsets to reference the root prim, not the child we may have sat on + if (!part.IsRoot) + { + m_parentID = part.ParentGroup.RootPart.LocalId; + m_pos += part.OffsetPosition; + } + else + { + m_parentID = m_requestedSitTargetID; + } Velocity = Vector3.Zero; RemoveFromPhysicalScene(); -- cgit v1.1 From 9d251b1dc518522979b73fdadc0329067b669149 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 20 Jun 2010 15:57:01 -0700 Subject: Fix the StandUp position to calculate as if we're still using the child prim id. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 472c389..a376ab1 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1822,7 +1822,7 @@ namespace OpenSim.Region.Framework.Scenes //CW: If the part isn't null then we can set the current position if (part != null) { - Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset! + Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset! AbsolutePosition = avWorldStandUp; //KF: Fix stand up. part.IsOccupied = false; part.ParentGroup.DeleteAvatar(ControllingClient.AgentId); -- cgit v1.1 From 973537f819c361344273009364b53e73c05e0739 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 21 Jun 2010 17:06:05 +0200 Subject: Ensure no UUID.Zero region ID is ever written to presence. Add a Migration to add a LastSeen field of type "Timestamp" to Presence for MySQL --- OpenSim/Data/MySQL/MySQLPresenceData.cs | 4 +++- OpenSim/Data/MySQL/Resources/Presence.migrations | 8 ++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/MySQLPresenceData.cs b/OpenSim/Data/MySQL/MySQLPresenceData.cs index 71caa1a..7b0016b 100644 --- a/OpenSim/Data/MySQL/MySQLPresenceData.cs +++ b/OpenSim/Data/MySQL/MySQLPresenceData.cs @@ -78,6 +78,9 @@ namespace OpenSim.Data.MySQL if (pd.Length == 0) return false; + if (regionID == UUID.Zero) + return; + MySqlCommand cmd = new MySqlCommand(); cmd.CommandText = String.Format("update {0} set RegionID=?RegionID where `SessionID`=?SessionID", m_Realm); @@ -90,6 +93,5 @@ namespace OpenSim.Data.MySQL return true; } - } } diff --git a/OpenSim/Data/MySQL/Resources/Presence.migrations b/OpenSim/Data/MySQL/Resources/Presence.migrations index 91f7de5..1075a15 100644 --- a/OpenSim/Data/MySQL/Resources/Presence.migrations +++ b/OpenSim/Data/MySQL/Resources/Presence.migrations @@ -13,3 +13,11 @@ CREATE UNIQUE INDEX SessionID ON Presence(SessionID); CREATE INDEX UserID ON Presence(UserID); COMMIT; + +:VERSION 1 # -------------------------- + +BEGIN; + +ALTER TABLE `Presence` ADD COLUMN LastSeen timestamp; + +COMMIT; -- cgit v1.1 From ab023c6a292cbd014ab5d45b50d481b524c05df3 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 21 Jun 2010 18:06:46 +0200 Subject: Fix build break --- OpenSim/Data/MySQL/MySQLPresenceData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/MySQLPresenceData.cs b/OpenSim/Data/MySQL/MySQLPresenceData.cs index 7b0016b..9ef880c 100644 --- a/OpenSim/Data/MySQL/MySQLPresenceData.cs +++ b/OpenSim/Data/MySQL/MySQLPresenceData.cs @@ -79,7 +79,7 @@ namespace OpenSim.Data.MySQL return false; if (regionID == UUID.Zero) - return; + return false; MySqlCommand cmd = new MySqlCommand(); -- cgit v1.1 From 53905cf919bc0365ba2f77d1cf0c06d0239c0418 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 21 Jun 2010 22:15:33 +0200 Subject: Bump the migration version, ot it would never happen --- OpenSim/Data/MySQL/Resources/Presence.migrations | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/Resources/Presence.migrations b/OpenSim/Data/MySQL/Resources/Presence.migrations index 1075a15..be4030e 100644 --- a/OpenSim/Data/MySQL/Resources/Presence.migrations +++ b/OpenSim/Data/MySQL/Resources/Presence.migrations @@ -14,7 +14,7 @@ CREATE INDEX UserID ON Presence(UserID); COMMIT; -:VERSION 1 # -------------------------- +:VERSION 2 # -------------------------- BEGIN; -- cgit v1.1 From 3ea4e5ccbe123c2ba6d8c47b7e870bfd90754f20 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 21 Jun 2010 23:26:27 +0200 Subject: Correctly update the LastSeen field --- OpenSim/Data/MySQL/MySQLPresenceData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/MySQL/MySQLPresenceData.cs b/OpenSim/Data/MySQL/MySQLPresenceData.cs index 9ef880c..2390feb 100644 --- a/OpenSim/Data/MySQL/MySQLPresenceData.cs +++ b/OpenSim/Data/MySQL/MySQLPresenceData.cs @@ -83,7 +83,7 @@ namespace OpenSim.Data.MySQL MySqlCommand cmd = new MySqlCommand(); - cmd.CommandText = String.Format("update {0} set RegionID=?RegionID where `SessionID`=?SessionID", m_Realm); + cmd.CommandText = String.Format("update {0} set RegionID=?RegionID, LastSeen=NOW() where `SessionID`=?SessionID", m_Realm); cmd.Parameters.AddWithValue("?SessionID", sessionID.ToString()); cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); -- cgit v1.1 From 3428196631bb13f04d04208af9fd28a432805ccf Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 22 Jun 2010 02:33:20 +0200 Subject: Guard prioritizer agains null values as those produced by a bullet dying before it can be updated --- OpenSim/Region/Framework/Scenes/Prioritizer.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index b95b5f2..8cd0160 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -52,6 +52,9 @@ namespace OpenSim.Region.Framework.Scenes public double GetUpdatePriority(IClientAPI client, ISceneEntity entity) { double priority = 0; + + if (entity == null) + return 100000; switch (m_scene.UpdatePrioritizationScheme) { -- cgit v1.1 From 962dade15596d0aeff3baba0b0b85c17524766c6 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 22 Jun 2010 04:04:59 +0200 Subject: Cause collisions with the avatar to be sent to attachments. Currently ignores collision filter. Physics collisions are still dodgy, so we don't get the events we should be getting. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 140 +++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index a376ab1..654e9ce 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -228,6 +228,7 @@ namespace OpenSim.Region.Framework.Scenes private int m_updateCount = 0; //KF: Update Anims for a while private static readonly int UPDATE_COUNT = 10; // how many frames to update for private const int NumMovementsBetweenRayCast = 5; + private List m_lastColliders = new List(); private bool CameraConstraintActive; //private int m_moveToPositionStateStatus; @@ -3595,6 +3596,145 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); } } + List thisHitColliders = new List(); + List endedColliders = new List(); + List startedColliders = new List(); + + foreach (uint localid in coldata.Keys) + { + thisHitColliders.Add(localid); + if (!m_lastColliders.Contains(localid)) + { + startedColliders.Add(localid); + } + //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString()); + } + + // calculate things that ended colliding + foreach (uint localID in m_lastColliders) + { + if (!thisHitColliders.Contains(localID)) + { + endedColliders.Add(localID); + } + } + //add the items that started colliding this time to the last colliders list. + foreach (uint localID in startedColliders) + { + m_lastColliders.Add(localID); + } + // remove things that ended colliding from the last colliders list + foreach (uint localID in endedColliders) + { + m_lastColliders.Remove(localID); + } + + // do event notification + if (startedColliders.Count > 0) + { + ColliderArgs StartCollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in startedColliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = Scene.GetSceneObjectPart(localId); + string data = ""; + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + } + + if (colliding.Count > 0) + { + StartCollidingMessage.Colliders = colliding; + + foreach (SceneObjectGroup att in Attachments) + Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage); + } + } + + if (endedColliders.Count > 0) + { + ColliderArgs EndCollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in endedColliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = Scene.GetSceneObjectPart(localId); + string data = ""; + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + } + + if (colliding.Count > 0) + { + EndCollidingMessage.Colliders = colliding; + + foreach (SceneObjectGroup att in Attachments) + Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage); + } + } + + if (thisHitColliders.Count > 0) + { + ColliderArgs CollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in thisHitColliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = Scene.GetSceneObjectPart(localId); + string data = ""; + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + } + + if (colliding.Count > 0) + { + CollidingMessage.Colliders = colliding; + + foreach (SceneObjectGroup att in Attachments) + Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage); + } + } + if (m_invulnerable) return; -- cgit v1.1 From 5c02fb435db171daf6d1ef360340137b3b0fd467 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 22 Jun 2010 17:35:00 +0200 Subject: Security fix: Allow only textures to be fetched using HTTP texture cap --- OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs index f8e3d59..75efb79 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs @@ -131,6 +131,12 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps if (texture != null) { + if (texture.Type != (sbyte)AssetType.Texture) + { + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + httpResponse.Send(); + return null; + } SendTexture(httpRequest, httpResponse, texture); } else @@ -147,6 +153,12 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps if (texture != null) { + if (texture.Type != (sbyte)AssetType.Texture) + { + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + httpResponse.Send(); + return null; + } SendTexture(httpRequest, httpResponse, texture); } else -- cgit v1.1 From e94cf3d9b71206384d33b4cc02fb252dfc93aed7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 24 Jun 2010 03:35:42 +0100 Subject: And another conflict --- .../Region/Framework/Scenes/SceneObjectPartInventory.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 5be71df..2cde8f3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -310,7 +310,6 @@ namespace OpenSim.Region.Framework.Scenes } else { -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs if (m_part.ParentGroup.m_savedScriptState != null) RestoreSavedScriptState(item.OldItemID, item.ItemID); @@ -327,22 +326,6 @@ namespace OpenSim.Region.Framework.Scenes StoreScriptErrors(item.ItemID, null); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); -======= - lock (m_items) - { - if (m_part.ParentGroup.m_savedScriptState != null) - RestoreSavedScriptState(item.OldItemID, item.ItemID); - - m_items[item.ItemID].PermsMask = 0; - m_items[item.ItemID].PermsGranter = UUID.Zero; - - string script = Utils.BytesToString(asset.Data); - m_part.ParentGroup.Scene.EventManager.TriggerRezScript( - m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); - m_part.ParentGroup.AddActiveScriptCount(1); - m_part.ScheduleFullUpdate(); - } ->>>>>>> master:OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs } } } -- cgit v1.1 From 9d03271265684f7724d9a242340ca6942bab3592 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 24 Jun 2010 03:43:50 +0200 Subject: And another --- OpenSim/Region/Application/OpenSimBase.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index ae942f9..27cb137 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -408,8 +408,6 @@ namespace OpenSim scene.SnmpService.BootInfo("ScriptEngine started", scene); } -======= ->>>>>>> master:OpenSim/Region/Application/OpenSimBase.cs m_sceneManager.Add(scene); if (m_autoCreateClientStack) -- cgit v1.1 From 6c37a02c0fee5147437f1b133b3fb7d1c44f89ad Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 24 Jun 2010 06:02:44 +0200 Subject: bug fix. 0,0 is a vlid sim coordinate --- OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 9d6c9a9..ac8c291 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -656,7 +656,7 @@ namespace OpenSim.Region.CoreModules.World.Land int x; int y; - if (x_float > Constants.RegionSize || x_float <= 0 || y_float > Constants.RegionSize || y_float <= 0) + if (x_float > Constants.RegionSize || x_float < 0 || y_float > Constants.RegionSize || y_float < 0) return null; try -- cgit v1.1 From b012e963d7fac1b877cf1a4738967538f20332b2 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 24 Jun 2010 18:48:40 +0200 Subject: New viewers don't set the "save offline IM" flag anymore. Set it serverside so messages get saved --- .../CoreModules/Avatar/InstantMessage/InstantMessageModule.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs index ab141eb..2dc7384 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs @@ -156,6 +156,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage return; } + if (dialog == (byte)InstantMessageDialog.MessageFromAgent || + dialog == (byte)InstantMessageDialog.MessageFromObject) + { + im.offline = 1; + } + if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im, -- cgit v1.1 From 2cc1f14b0c938cff51b7bbf3f13a51b306f87e1b Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 24 Jun 2010 19:37:02 +0200 Subject: Replace the imSessionID, which is useless out of context, with the scope id in saved IMs --- .../CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index 9412735..5f9f518 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -204,6 +204,13 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if ((im.offline != 0) && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) { + // It's not delivered. Make sure the scope id is saved + // We don't need the imSessionID here anymore, overwrite it + Scene scene = FindScene(new UUID(im.fromAgentID)); + if (scene == null) + scene = m_SceneList[0]; + im.imSessionID = new Guid(scene.RegionInfo.ScopeID.ToString()); + bool success = SynchronousRestObjectPoster.BeginPostObject( "POST", m_RestURL+"/SaveMessage/", im); -- cgit v1.1 From cbca58401ab67035c8c9aa20a0cf4bccd8cc8bef Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 24 Jun 2010 20:46:24 +0200 Subject: Add the object owner UUID into the binary bucket of object to user IM --- .../Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs | 2 ++ OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index 5f9f518..a2dc91f 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -201,6 +201,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage private void UndeliveredMessage(GridInstantMessage im) { + if (im.dialog == 19) + im.offline = 1; // We want them pushed out to the server if ((im.offline != 0) && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 7d7320d..0abc828 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3272,7 +3272,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api msg.ParentEstateID = 0; //ParentEstateID; msg.Position = Vector3.Zero;// new Vector3(m_host.AbsolutePosition); msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; - msg.binaryBucket = new byte[0];// binaryBucket; + msg.binaryBucket = Util.StringToBytes256(m_host.OwnerID.ToString()); if (m_TransferModule != null) { -- cgit v1.1 From f186882c0fbe9675a000417e27354e323315de1a Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 24 Jun 2010 20:51:04 +0200 Subject: Also make prims send the proper position. I hate it when people comment out things just because they're "not yet used". Grrrr. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0abc828..fb191e6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3266,12 +3266,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api msg.message = message.Substring(0, 1024); else msg.message = message; - msg.dialog = (byte)19; // messgage from script ??? // dialog; + msg.dialog = (byte)19; // MessageFromObject msg.fromGroup = false;// fromGroup; msg.offline = (byte)0; //offline; - msg.ParentEstateID = 0; //ParentEstateID; - msg.Position = Vector3.Zero;// new Vector3(m_host.AbsolutePosition); - msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; + msg.ParentEstateID = World.RegionInfo.EstateSettings.EstateID; + msg.Position = new Vector3(m_host.AbsolutePosition); + msg.RegionID = World.RegionInfo.RegionID.Guid; msg.binaryBucket = Util.StringToBytes256(m_host.OwnerID.ToString()); if (m_TransferModule != null) -- cgit v1.1 From 8a0ec60c8f518a4c3bf3e91d02ad75a07ab40b76 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 25 Jun 2010 01:41:00 +0200 Subject: Unhook the dwell request from the land module (and therefore local storage) --- OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index ac8c291..91c8130 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -168,7 +168,7 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelGodForceOwner += ClientOnParcelGodForceOwner; client.OnParcelReclaim += ClientOnParcelReclaim; client.OnParcelInfoRequest += ClientOnParcelInfoRequest; - client.OnParcelDwellRequest += ClientOnParcelDwellRequest; +// client.OnParcelDwellRequest += ClientOnParcelDwellRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; client.OnPreAgentUpdate += ClientOnPreAgentUpdate; -- cgit v1.1 From afff74a8351586e0e7ecd7dd1cdfde1964830a6b Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 25 Jun 2010 01:44:17 +0200 Subject: Add DwellModule interface --- .../Region/Framework/Interfaces/IDwellModule.cs | 37 ++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 OpenSim/Region/Framework/Interfaces/IDwellModule.cs diff --git a/OpenSim/Region/Framework/Interfaces/IDwellModule.cs b/OpenSim/Region/Framework/Interfaces/IDwellModule.cs new file mode 100644 index 0000000..db50439 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IDwellModule.cs @@ -0,0 +1,37 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Interfaces +{ + public interface IDwellModule + { + int GetDwell(UUID parcelID); + } +} -- cgit v1.1 From 3101d530647cdf401b6078dacf6d7ceb063b049d Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Fri, 25 Jun 2010 05:25:41 -0700 Subject: Make "Allow other residents to edit terrain" default to FALSE --- OpenSim/Framework/LandData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs index 060e886..ef07438 100644 --- a/OpenSim/Framework/LandData.cs +++ b/OpenSim/Framework/LandData.cs @@ -62,7 +62,7 @@ namespace OpenSim.Framework private uint _flags = (uint) ParcelFlags.AllowFly | (uint) ParcelFlags.AllowLandmark | (uint) ParcelFlags.AllowAPrimitiveEntry | - (uint) ParcelFlags.AllowDeedToGroup | (uint) ParcelFlags.AllowTerraform | + (uint) ParcelFlags.AllowDeedToGroup | (uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts | (uint) ParcelFlags.SoundLocal; -- cgit v1.1 From 94ece2789d87d0c836bdaaddb825020968f737e6 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Fri, 25 Jun 2010 12:21:24 -0700 Subject: Add some libraries for XGitminster --- bin/DiffieHellman.dll | Bin 0 -> 53248 bytes bin/GitSharp.Core.dll | Bin 0 -> 558080 bytes bin/GitSharp.Core.pdb | Bin 0 -> 1906176 bytes bin/GitSharp.dll | Bin 0 -> 219648 bytes bin/GitSharp.pdb | Bin 0 -> 347648 bytes bin/ICSharpCode.SharpZipLib.dll | Bin 0 -> 188416 bytes bin/ICSharpCode.SharpZipLib.xml | 9055 +++++++++++++++++++++++++++++++++++++++ bin/Org.Mentalis.Security.dll | Bin 0 -> 184320 bytes bin/Tamir.SharpSSH.dll | Bin 0 -> 212992 bytes bin/Winterdom.IO.FileMap.dll | Bin 0 -> 9728 bytes bin/Winterdom.IO.FileMap.pdb | Bin 0 -> 24064 bytes 11 files changed, 9055 insertions(+) create mode 100644 bin/DiffieHellman.dll create mode 100644 bin/GitSharp.Core.dll create mode 100644 bin/GitSharp.Core.pdb create mode 100644 bin/GitSharp.dll create mode 100644 bin/GitSharp.pdb create mode 100644 bin/ICSharpCode.SharpZipLib.dll create mode 100644 bin/ICSharpCode.SharpZipLib.xml create mode 100644 bin/Org.Mentalis.Security.dll create mode 100644 bin/Tamir.SharpSSH.dll create mode 100644 bin/Winterdom.IO.FileMap.dll create mode 100644 bin/Winterdom.IO.FileMap.pdb diff --git a/bin/DiffieHellman.dll b/bin/DiffieHellman.dll new file mode 100644 index 0000000..aa31051 Binary files /dev/null and b/bin/DiffieHellman.dll differ diff --git a/bin/GitSharp.Core.dll b/bin/GitSharp.Core.dll new file mode 100644 index 0000000..5aad773 Binary files /dev/null and b/bin/GitSharp.Core.dll differ diff --git a/bin/GitSharp.Core.pdb b/bin/GitSharp.Core.pdb new file mode 100644 index 0000000..32ad5bb Binary files /dev/null and b/bin/GitSharp.Core.pdb differ diff --git a/bin/GitSharp.dll b/bin/GitSharp.dll new file mode 100644 index 0000000..99a91a7 Binary files /dev/null and b/bin/GitSharp.dll differ diff --git a/bin/GitSharp.pdb b/bin/GitSharp.pdb new file mode 100644 index 0000000..4c65b1f Binary files /dev/null and b/bin/GitSharp.pdb differ diff --git a/bin/ICSharpCode.SharpZipLib.dll b/bin/ICSharpCode.SharpZipLib.dll new file mode 100644 index 0000000..e565e3a Binary files /dev/null and b/bin/ICSharpCode.SharpZipLib.dll differ diff --git a/bin/ICSharpCode.SharpZipLib.xml b/bin/ICSharpCode.SharpZipLib.xml new file mode 100644 index 0000000..98cb51e --- /dev/null +++ b/bin/ICSharpCode.SharpZipLib.xml @@ -0,0 +1,9055 @@ + + + + ICSharpCode.SharpZipLib + + + + + FastZipEvents supports all events applicable to FastZip operations. + + + + + Delegate to invoke when processing directories. + + + + + Delegate to invoke when processing files. + + + + + Delegate to invoke during processing of files. + + + + + Delegate to invoke when processing for a file has been completed. + + + + + Delegate to invoke when processing directory failures. + + + + + Delegate to invoke when processing file failures. + + + + + Raise the directory failure event. + + The directory causing the failure. + The exception for this event. + A boolean indicating if execution should continue or not. + + + + Raises the file failure delegate. + + The file causing the failure. + The exception for this failure. + A boolean indicating if execution should continue or not. + + + + Fires the Process File delegate. + + The file being processed. + A boolean indicating if execution should continue or not. + + + + Fires the CompletedFile delegate + + The file whose processing has been completed. + A boolean indicating if execution should continue or not. + + + + Fires the process directory delegate. + + The directory being processed. + Flag indicating if the directory has matching files as determined by the current filter. + A of true if the operation should continue; false otherwise. + + + + The minimum timespan between events. + + The minimum period of time between events. + + + + + FastZip provides facilities for creating and extracting zip files. + + + + + Initialise a default instance of . + + + + + Initialise a new instance of + + The events to use during operations. + + + + Create a zip file. + + The name of the zip file to create. + The directory to source files from. + True to recurse directories, false for no recursion. + The file filter to apply. + The directory filter to apply. + + + + Create a zip file/archive. + + The name of the zip file to create. + The directory to obtain files and directories from. + True to recurse directories, false for no recursion. + The file filter to apply. + + + + Create a zip archive sending output to the passed. + + The stream to write archive data to. + The directory to source files from. + True to recurse directories, false for no recursion. + The file filter to apply. + The directory filter to apply. + + + + Extract the contents of a zip file. + + The zip file to extract from. + The directory to save extracted information in. + A filter to apply to files. + + + + Extract the contents of a zip file. + + The zip file to extract from. + The directory to save extracted information in. + The style of overwriting to apply. + A delegate to invoke when confirming overwriting. + A filter to apply to files. + A filter to apply to directories. + Flag indicating wether to restore the date and time for extracted files. + + + + Get/set a value indicating wether empty directories should be created. + + + + + Get / set the password value. + + + + + Get or set the active when creating Zip files. + + + + + + Get or set the active when creating Zip files. + + + + + Get/set a value indicating wether file dates and times should + be restored when extracting files from an archive. + + The default value is false. + + + + Get/set a value indicating wether file attributes should + be restored during extract operations + + + + + Defines the desired handling when overwriting files during extraction. + + + + + Prompt the user to confirm overwriting + + + + + Never overwrite files. + + + + + Always overwrite files. + + + + + Delegate called when confirming overwriting of files. + + + + + NameFilter is a string matching class which allows for both positive and negative + matching. + A filter is a sequence of independant regular expressions separated by semi-colons ';' + Each expression can be prefixed by a plus '+' sign or a minus '-' sign to denote the expression + is intended to include or exclude names. If neither a plus or minus sign is found include is the default + A given name is tested for inclusion before checking exclusions. Only names matching an include spec + and not matching an exclude spec are deemed to match the filter. + An empty filter matches any name. + + The following expression includes all name ending in '.dat' with the exception of 'dummy.dat' + "+\.dat$;-^dummy\.dat$" + + + + + Scanning filters support filtering of names. + + + + + Test a name to see if it 'matches' the filter. + + The name to test. + Returns true if the name matches the filter, false if it does not match. + + + + Construct an instance based on the filter expression passed + + The filter expression. + + + + Test a string to see if it is a valid regular expression. + + The expression to test. + True if expression is a valid false otherwise. + + + + Test an expression to see if it is valid as a filter. + + The filter expression to test. + True if the expression is valid, false otherwise. + + + + Convert this filter to its string equivalent. + + The string equivalent for this filter. + + + + Test a value to see if it is included by the filter. + + The value to test. + True if the value is included, false otherwise. + + + + Test a value to see if it is excluded by the filter. + + The value to test. + True if the value is excluded, false otherwise. + + + + Test a value to see if it matches the filter. + + The value to test. + True if the value matches, false otherwise. + + + + Compile this filter. + + + + + Huffman tree used for inflation + + + + + Literal length tree + + + + + Distance tree + + + + + Constructs a Huffman tree from the array of code lengths. + + + the array of code lengths + + + + + Reads the next symbol from input. The symbol is encoded using the + huffman tree. + + + input the input source. + + + the next symbol, or -1 if not enough input is available. + + + + + This class is general purpose class for writing data to a buffer. + + It allows you to write bits as well as bytes + Based on DeflaterPending.java + + author of the original java version : Jochen Hoenicke + + + + + Internal work buffer + + + + + construct instance using default buffer size of 4096 + + + + + construct instance using specified buffer size + + + size to use for internal buffer + + + + + Clear internal state/buffers + + + + + Write a byte to buffer + + + The value to write + + + + + Write a short value to buffer LSB first + + + The value to write. + + + + + write an integer LSB first + + The value to write. + + + + Write a block of data to buffer + + data to write + offset of first byte to write + number of bytes to write + + + + Align internal buffer on a byte boundary + + + + + Write bits to internal buffer + + source of bits + number of bits to write + + + + Write a short value to internal buffer most significant byte first + + value to write + + + + Flushes the pending buffer into the given output array. If the + output array is to small, only a partial flush is done. + + The output array. + The offset into output array. + The maximum number of bytes to store. + The number of bytes flushed. + + + + Convert internal buffer to byte array. + Buffer is empty on completion + + + The internal buffer contents converted to a byte array. + + + + + The number of bits written to the buffer + + + + + Indicates if buffer has been flushed + + + + + Used to advise clients of 'events' while processing archives + + + + + The TarArchive class implements the concept of a + 'Tape Archive'. A tar archive is a series of entries, each of + which represents a file system object. Each entry in + the archive consists of a header block followed by 0 or more data blocks. + Directory entries consist only of the header block, and are followed by entries + for the directory's contents. File entries consist of a + header followed by the number of blocks needed to + contain the file's contents. All entries are written on + block boundaries. Blocks are 512 bytes long. + + TarArchives are instantiated in either read or write mode, + based upon whether they are instantiated with an InputStream + or an OutputStream. Once instantiated TarArchives read/write + mode can not be changed. + + There is currently no support for random access to tar archives. + However, it seems that subclassing TarArchive, and using the + TarBuffer.CurrentRecord and TarBuffer.CurrentBlock + properties, this would be rather trivial. + + + + + Raises the ProgressMessage event + + The TarEntry for this event + message for this event. Null is no message + + + + Constructor for a default . + + + + + Initalise a TarArchive for input. + + The to use for input. + + + + Initialise a TarArchive for output. + + The to use for output. + + + + The InputStream based constructors create a TarArchive for the + purposes of extracting or listing a tar archive. Thus, use + these constructors when you wish to extract files from or list + the contents of an existing tar archive. + + The stream to retrieve archive data from. + Returns a new suitable for reading from. + + + + Create TarArchive for reading setting block factor + + Stream for tar archive contents + The blocking factor to apply + Returns a suitable for reading. + + + + Create a TarArchive for writing to, using the default blocking factor + + The to write to + Returns a suitable for writing. + + + + Create a TarArchive for writing to + + The stream to write to + The blocking factor to use for buffering. + Returns a suitable for writing. + + + + Set the flag that determines whether existing files are + kept, or overwritten during extraction. + + + If true, do not overwrite existing files. + + + + + Set the ascii file translation flag. + + + If true, translate ascii text files. + + + + + Set user and group information that will be used to fill in the + tar archive's entry headers. This information based on that available + for the linux operating system, which is not always available on other + operating systems. TarArchive allows the programmer to specify values + to be used in their place. + is set to true by this call. + + + The user id to use in the headers. + + + The user name to use in the headers. + + + The group id to use in the headers. + + + The group name to use in the headers. + + + + + Close the archive. + + + + + Perform the "list" command for the archive contents. + + NOTE That this method uses the progress event to actually list + the contents. If the progress display event is not set, nothing will be listed! + + + + + Perform the "extract" command and extract the contents of the archive. + + + The destination directory into which to extract. + + + + + Extract an entry from the archive. This method assumes that the + tarIn stream has been properly set with a call to GetNextEntry(). + + + The destination directory into which to extract. + + + The TarEntry returned by tarIn.GetNextEntry(). + + + + + Write an entry to the archive. This method will call the putNextEntry + and then write the contents of the entry, and finally call closeEntry() + for entries that are files. For directories, it will call putNextEntry(), + and then, if the recurse flag is true, process each entry that is a + child of the directory. + + + The TarEntry representing the entry to write to the archive. + + + If true, process the children of directory entries. + + + + + Write an entry to the archive. This method will call the putNextEntry + and then write the contents of the entry, and finally call closeEntry() + for entries that are files. For directories, it will call putNextEntry(), + and then, if the recurse flag is true, process each entry that is a + child of the directory. + + + The TarEntry representing the entry to write to the archive. + + + If true, process the children of directory entries. + + + + + Releases the unmanaged resources used by the FileStream and optionally releases the managed resources. + + true to release both managed and unmanaged resources; + false to release only unmanaged resources. + + + + Closes the archive and releases any associated resources. + + + + + Ensures that resources are freed and other cleanup operations are performed + when the garbage collector reclaims the . + + + + + Client hook allowing detailed information to be reported during processing + + + + + Get/set the ascii file translation flag. If ascii file translation + is true, then the file is checked to see if it a binary file or not. + If the flag is true and the test indicates it is ascii text + file, it will be translated. The translation converts the local + operating system's concept of line ends into the UNIX line end, + '\n', which is the defacto standard for a TAR archive. This makes + text files compatible with UNIX. + + + + + PathPrefix is added to entry names as they are written if the value is not null. + A slash character is appended after PathPrefix + + + + + RootPath is removed from entry names if it is found at the + beginning of the name. + + + + + Get or set a value indicating if overrides defined by SetUserInfo should be applied. + + If overrides are not applied then the values as set in each header will be used. + + + + Get the archive user id. + See ApplyUserInfoOverrides for detail + on how to allow setting values on a per entry basis. + + + The current user id. + + + + + Get the archive user name. + See ApplyUserInfoOverrides for detail + on how to allow setting values on a per entry basis. + + + The current user name. + + + + + Get the archive group id. + See ApplyUserInfoOverrides for detail + on how to allow setting values on a per entry basis. + + + The current group id. + + + + + Get the archive group name. + See ApplyUserInfoOverrides for detail + on how to allow setting values on a per entry basis. + + + The current group name. + + + + + Get the archive's record size. Tar archives are composed of + a series of RECORDS each containing a number of BLOCKS. + This allowed tar archives to match the IO characteristics of + the physical device being used. Archives are expected + to be properly "blocked". + + + The record size this archive is using. + + + + + An output stream that compresses into the BZip2 format + including file header chars into another stream. + + + + + Construct a default output stream with maximum block size + + The stream to write BZip data onto. + + + + Initialise a new instance of the + for the specified stream, using the given blocksize. + + The stream to write compressed data to. + The block size to use. + + Valid block sizes are in the range 1..9, with 1 giving + the lowest compression and 9 the highest. + + + + + Ensures that resources are freed and other cleanup operations + are performed when the garbage collector reclaims the BZip2OutputStream. + + + + + Sets the current position of this stream to the given value. + + The point relative to the offset from which to being seeking. + The reference point from which to begin seeking. + The new position in the stream. + + + + Sets the length of this stream to the given value. + + The new stream length. + + + + Read a byte from the stream advancing the position. + + The byte read cast to an int; -1 if end of stream. + + + + Read a block of bytes + + The buffer to read into. + The offset in the buffer to start storing data at. + The maximum number of bytes to read. + The total number of bytes read. This might be less than the number of bytes + requested if that number of bytes are not currently available, or zero + if the end of the stream is reached. + + + + Write a block of bytes to the stream + + The buffer containing data to write. + The offset of the first byte to write. + The number of bytes to write. + + + + Write a byte to the stream. + + The byte to write to the stream. + + + + End the current block and end compression. + Close the stream and free any resources + + + + + Get the number of bytes written to output. + + + + + Releases the unmanaged resources used by the and optionally releases the managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Flush output buffers + + + + + Get/set flag indicating ownership of underlying stream. + When the flag is true will close the underlying stream also. + + + + + Gets a value indicating whether the current stream supports reading + + + + + Gets a value indicating whether the current stream supports seeking + + + + + Gets a value indicating whether the current stream supports writing + + + + + Gets the length in bytes of the stream + + + + + Gets or sets the current position of this stream. + + + + + Get the number of bytes written to the output. + + + + + Represents exception conditions specific to Zip archive handling + + + + + SharpZipBaseException is the base exception class for the SharpZipLibrary. + All library exceptions are derived from this. + + NOTE: Not all exceptions thrown will be derived from this class. + A variety of other exceptions are possible for example + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initializes a new instance of the SharpZipBaseException class. + + + + + Initializes a new instance of the SharpZipBaseException class with a specified error message. + + A message describing the exception. + + + + Initializes a new instance of the SharpZipBaseException class with a specified + error message and a reference to the inner exception that is the cause of this exception. + + A message describing the exception. + The inner exception + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initializes a new instance of the ZipException class. + + + + + Initializes a new instance of the ZipException class with a specified error message. + + The error message that explains the reason for the exception. + + + + Initialise a new instance of ZipException. + + A message describing the error. + The exception that is the cause of the current exception. + + + + A helper class to simplify compressing and decompressing streams. + + + + + Decompress input writing + decompressed data to the output stream + + The stream containing data to decompress. + The stream to write decompressed data to. + Both streams are closed on completion + + + + Compress input stream sending + result to output stream + + The stream to compress. + The stream to write compressed data to. + The block size to use. + Both streams are closed on completion + + + + Initialise a default instance of this class. + + + + + Determines how entries are tested to see if they should use Zip64 extensions or not. + + + + + Zip64 will not be forced on entries during processing. + + An entry can have this overridden if required + + + + Zip64 should always be used. + + + + + #ZipLib will determine use based on entry values when added to archive. + + + + + The kind of compression used for an entry in an archive + + + + + A direct copy of the file contents is held in the archive + + + + + Common Zip compression method using a sliding dictionary + of up to 32KB and secondary compression from Huffman/Shannon-Fano trees + + + + + An extension to deflate with a 64KB window. Not supported by #Zip currently + + + + + Not supported by #Zip currently + + + + + WinZip special for AES encryption, Not supported by #Zip + + + + + Identifies the encryption algorithm used for an entry + + + + + No encryption has been used. + + + + + Encrypted using PKZIP 2.0 or 'classic' encryption. + + + + + DES encryption has been used. + + + + + RCS encryption has been used for encryption. + + + + + Triple DES encryption with 168 bit keys has been used for this entry. + + + + + Triple DES with 112 bit keys has been used for this entry. + + + + + AES 128 has been used for encryption. + + + + + AES 192 has been used for encryption. + + + + + AES 256 has been used for encryption. + + + + + RC2 corrected has been used for encryption. + + + + + Blowfish has been used for encryption. + + + + + Twofish has been used for encryption. + + + + + RCS has been used for encryption. + + + + + An unknown algorithm has been used for encryption. + + + + + Defines the contents of the general bit flags field for an archive entry. + + + + + Bit 0 if set indicates that the file is encrypted + + + + + Bits 1 and 2 - Two bits defining the compression method (only for Method 6 Imploding and 8,9 Deflating) + + + + + Bit 3 if set indicates a trailing data desciptor is appended to the entry data + + + + + Bit 4 is reserved for use with method 8 for enhanced deflation + + + + + Bit 5 if set indicates the file contains Pkzip compressed patched data. + Requires version 2.7 or greater. + + + + + Bit 6 if set strong encryption has been used for this entry. + + + + + Bit 7 is currently unused + + + + + Bit 8 is currently unused + + + + + Bit 9 is currently unused + + + + + Bit 10 is currently unused + + + + + Bit 11 if set indicates the filename and + comment fields for this file must be encoded using UTF-8. + + + + + Bit 12 is documented as being reserved by PKware for enhanced compression. + + + + + Bit 13 if set indicates that values in the local header are masked to hide + their actual values, and the central directory is encrypted. + + + Used when encrypting the central directory contents. + + + + + Bit 14 is documented as being reserved for use by PKware + + + + + Bit 15 is documented as being reserved for use by PKware + + + + + This class contains constants used for Zip format files + + + + + The version made by field for entries in the central header when created by this library + + + This is also the Zip version for the library when comparing against the version required to extract + for an entry. See . + + + + + The version made by field for entries in the central header when created by this library + + + This is also the Zip version for the library when comparing against the version required to extract + for an entry. See ZipInputStream.CanDecompressEntry. + + + + + The minimum version required to support strong encryption + + + + + The minimum version required to support strong encryption + + + + + The version required for Zip64 extensions + + + + + Size of local entry header (excluding variable length fields at end) + + + + + Size of local entry header (excluding variable length fields at end) + + + + + Size of Zip64 data descriptor + + + + + Size of data descriptor + + + + + Size of data descriptor + + + + + Size of central header entry (excluding variable fields) + + + + + Size of central header entry + + + + + Size of end of central record (excluding variable fields) + + + + + Size of end of central record (excluding variable fields) + + + + + Size of 'classic' cryptographic header stored before any entry data + + + + + Size of cryptographic header stored before entry data + + + + + Signature for local entry header + + + + + Signature for local entry header + + + + + Signature for spanning entry + + + + + Signature for spanning entry + + + + + Signature for temporary spanning entry + + + + + Signature for temporary spanning entry + + + + + Signature for data descriptor + + + This is only used where the length, Crc, or compressed size isnt known when the + entry is created and the output stream doesnt support seeking. + The local entry cannot be 'patched' with the correct values in this case + so the values are recorded after the data prefixed by this header, as well as in the central directory. + + + + + Signature for data descriptor + + + This is only used where the length, Crc, or compressed size isnt known when the + entry is created and the output stream doesnt support seeking. + The local entry cannot be 'patched' with the correct values in this case + so the values are recorded after the data prefixed by this header, as well as in the central directory. + + + + + Signature for central header + + + + + Signature for central header + + + + + Signature for Zip64 central file header + + + + + Signature for Zip64 central file header + + + + + Signature for Zip64 central directory locator + + + + + Signature for archive extra data signature (were headers are encrypted). + + + + + Central header digitial signature + + + + + Central header digitial signature + + + + + End of central directory record signature + + + + + End of central directory record signature + + + + + Convert a portion of a byte array to a string. + + + Data to convert to string + + + Number of bytes to convert starting from index 0 + + + data[0]..data[length - 1] converted to a string + + + + + Convert a byte array to string + + + Byte array to convert + + + dataconverted to a string + + + + + Convert a byte array to string + + The applicable general purpose bits flags + + Byte array to convert + + The number of bytes to convert. + + dataconverted to a string + + + + + Convert a byte array to string + + + Byte array to convert + + The applicable general purpose bits flags + + dataconverted to a string + + + + + Convert a string to a byte array + + + String to convert to an array + + Converted array + + + + Convert a string to a byte array + + The applicable general purpose bits flags + + String to convert to an array + + Converted array + + + + Initialise default instance of ZipConstants + + + Private to prevent instances being created. + + + + + Default encoding used for string conversion. 0 gives the default system OEM code page. + Dont use unicode encodings if you want to be Zip compatible! + Using the default code page isnt the full solution neccessarily + there are many variable factors, codepage 850 is often a good choice for + European users, however be careful about compatability. + + + + + This is a DeflaterOutputStream that writes the files into a zip + archive one after another. It has a special method to start a new + zip entry. The zip entries contains information about the file name + size, compressed size, CRC, etc. + + It includes support for Stored and Deflated entries. + This class is not thread safe. +
+
Author of the original java version : Jochen Hoenicke +
+ This sample shows how to create a zip file + + using System; + using System.IO; + + using ICSharpCode.SharpZipLib.Core; + using ICSharpCode.SharpZipLib.Zip; + + class MainClass + { + public static void Main(string[] args) + { + string[] filenames = Directory.GetFiles(args[0]); + byte[] buffer = new byte[4096]; + + using ( ZipOutputStream s = new ZipOutputStream(File.Create(args[1])) ) { + + s.SetLevel(9); // 0 - store only to 9 - means best compression + + foreach (string file in filenames) { + ZipEntry entry = new ZipEntry(file); + s.PutNextEntry(entry); + + using (FileStream fs = File.OpenRead(file)) { + StreamUtils.Copy(fs, s, buffer); + } + } + } + } + } + + +
+ + + A special stream deflating or compressing the bytes that are + written to it. It uses a Deflater to perform actual deflating.
+ Authors of the original java version : Tom Tromey, Jochen Hoenicke +
+
+ + + Creates a new DeflaterOutputStream with a default Deflater and default buffer size. + + + the output stream where deflated output should be written. + + + + + Creates a new DeflaterOutputStream with the given Deflater and + default buffer size. + + + the output stream where deflated output should be written. + + + the underlying deflater. + + + + + Creates a new DeflaterOutputStream with the given Deflater and + buffer size. + + + The output stream where deflated output is written. + + + The underlying deflater to use + + + The buffer size to use when deflating + + + bufsize is less than or equal to zero. + + + baseOutputStream does not support writing + + + deflater instance is null + + + + + Finishes the stream by calling finish() on the deflater. + + + Not all input is deflated + + + + + Encrypt a block of data + + + Data to encrypt. NOTE the original contents of the buffer are lost + + + Offset of first byte in buffer to encrypt + + + Number of bytes in buffer to encrypt + + + + + Initializes encryption keys based on given password + + The password. + + + + Deflates everything in the input buffers. This will call + def.deflate() until all bytes from the input buffers + are processed. + + + + + Sets the current position of this stream to the given value. Not supported by this class! + + The offset relative to the to seek. + The to seek from. + The new position in the stream. + Any access + + + + Sets the length of this stream to the given value. Not supported by this class! + + The new stream length. + Any access + + + + Read a byte from stream advancing position by one + + The byte read cast to an int. THe value is -1 if at the end of the stream. + Any access + + + + Read a block of bytes from stream + + The buffer to store read data in. + The offset to start storing at. + The maximum number of bytes to read. + The actual number of bytes read. Zero if end of stream is detected. + Any access + + + + Asynchronous reads are not supported a NotSupportedException is always thrown + + The buffer to read into. + The offset to start storing data at. + The number of bytes to read + The async callback to use. + The state to use. + Returns an + Any access + + + + Asynchronous writes arent supported, a NotSupportedException is always thrown + + The buffer to write. + The offset to begin writing at. + The number of bytes to write. + The to use. + The state object. + Returns an IAsyncResult. + Any access + + + + Flushes the stream by calling Flush on the deflater and then + on the underlying stream. This ensures that all bytes are flushed. + + + + + Calls and closes the underlying + stream when is true. + + + + + Writes a single byte to the compressed output stream. + + + The byte value. + + + + + Writes bytes from an array to the compressed stream. + + + The byte array + + + The offset into the byte array where to start. + + + The number of bytes to write. + + + + + This buffer is used temporarily to retrieve the bytes from the + deflater and write them to the underlying output stream. + + + + + The deflater which is used to deflate the stream. + + + + + Base stream the deflater depends on. + + + + + Get/set flag indicating ownership of the underlying stream. + When the flag is true will close the underlying stream also. + + + + + Allows client to determine if an entry can be patched after its added + + + + + Get/set the password used for encryption. + + When set to null or if the password is empty no encryption is performed + + + + Gets value indicating stream can be read from + + + + + Gets a value indicating if seeking is supported for this stream + This property always returns false + + + + + Get value indicating if this stream supports writing + + + + + Get current length of stream + + + + + Gets the current position within the stream. + + Any attempt to set position + + + + Creates a new Zip output stream, writing a zip archive. + + + The output stream to which the archive contents are written. + + + + + Set the zip file comment. + + + The comment text for the entire archive. + + + The converted comment is longer than 0xffff bytes. + + + + + Sets the compression level. The new level will be activated + immediately. + + The new compression level (1 to 9). + + Level specified is not supported. + + + + + + Get the current deflater compression level + + The current compression level + + + + Write an unsigned short in little endian byte order. + + + + + Write an int in little endian byte order. + + + + + Write an int in little endian byte order. + + + + + Starts a new Zip entry. It automatically closes the previous + entry if present. + All entry elements bar name are optional, but must be correct if present. + If the compression method is stored and the output is not patchable + the compression for that entry is automatically changed to deflate level 0 + + + the entry. + + + if entry passed is null. + + + if an I/O error occured. + + + if stream was finished + + + Too many entries in the Zip file
+ Entry name is too long
+ Finish has already been called
+
+
+ + + Closes the current entry, updating header and footer information as required + + + An I/O error occurs. + + + No entry is active. + + + + + Writes the given buffer to the current entry. + + The buffer containing data to write. + The offset of the first byte to write. + The number of bytes to write. + Archive size is invalid + No entry is active. + + + + Finishes the stream. This will write the central directory at the + end of the zip file and flush the stream. + + + This is automatically called when the stream is closed. + + + An I/O error occurs. + + + Comment exceeds the maximum length
+ Entry name exceeds the maximum length +
+
+ + + The entries for the archive. + + + + + Used to track the crc of data added to entries. + + + + + The current entry being added. + + + + + Used to track the size of data for an entry during writing. + + + + + Offset to be recorded for each entry in the central header. + + + + + Comment for the entire archive recorded in central header. + + + + + Flag indicating that header patching is required for the current entry. + + + + + Position to patch crc + + + + + Position to patch size. + + + + + Gets a flag value of true if the central header has been added for this archive; false if it has not been added. + + No further entries can be added once this has been done. + + + + Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + + Older archivers may not understand Zip64 extensions. + If backwards compatability is an issue be careful when adding entries to an archive. + Setting this property to off is workable but less desirable as in those circumstances adding a file + larger then 4GB will fail. + + + + INameTransform defines how file system names are transformed for use with archives. + + + + + Given a file name determine the transformed value. + + The name to transform. + The transformed file name. + + + + Given a directory name determine the transformed value. + + The name to transform. + The transformed directory name + + + + This class contains constants used for deflation. + + + + + Set to true to enable debugging + + + + + Written to Zip file to identify a stored block + + + + + Identifies static tree in Zip file + + + + + Identifies dynamic tree in Zip file + + + + + Header flag indicating a preset dictionary for deflation + + + + + Sets internal buffer sizes for Huffman encoding + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + This class stores the pending output of the Deflater. + + author of the original java version : Jochen Hoenicke + + + + + Construct instance with default buffer size + + + + + PathFilter filters directories and files using a form of regular expressions + by full path name. + See NameFilter for more detail on filtering. + + + + + Initialise a new instance of . + + The filter expression to apply. + + + + Test a name to see if it matches the filter. + + The name to test. + True if the name matches, false otherwise. + + + + ExtendedPathFilter filters based on name, file size, and the last write time of the file. + + Provides an example of how to customise filtering. + + + + Initialise a new instance of ExtendedPathFilter. + + The filter to apply. + The minimum file size to include. + The maximum file size to include. + + + + Initialise a new instance of ExtendedPathFilter. + + The filter to apply. + The minimum to include. + The maximum to include. + + + + Initialise a new instance of ExtendedPathFilter. + + The filter to apply. + The minimum file size to include. + The maximum file size to include. + The minimum to include. + The maximum to include. + + + + Test a filename to see if it matches the filter. + + The filename to test. + True if the filter matches, false otherwise. + + + + Get/set the minimum size for a file that will match this filter. + + + + + Get/set the maximum size for a file that will match this filter. + + + + + Get/set the minimum value that will match for this filter. + + Files with a LastWrite time less than this value are excluded by the filter. + + + + Get/set the maximum value that will match for this filter. + + Files with a LastWrite time greater than this value are excluded by the filter. + + + + NameAndSizeFilter filters based on name and file size. + + A sample showing how filters might be extended. + + + + Initialise a new instance of NameAndSizeFilter. + + The filter to apply. + The minimum file size to include. + The maximum file size to include. + + + + Test a filename to see if it matches the filter. + + The filename to test. + True if the filter matches, false otherwise. + + + + Get/set the minimum size for a file that will match this filter. + + + + + Get/set the maximum size for a file that will match this filter. + + + + + BZip2Exception represents exceptions specific to Bzip2 algorithm + + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initialise a new instance of BZip2Exception. + + + + + Initialise a new instance of BZip2Exception with its message set to message. + + The message describing the error. + + + + Initialise an instance of BZip2Exception + + A message describing the error. + The exception that is the cause of the current exception. + + + + GZipException represents a Gzip specific exception + + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initialise a new instance of GZipException + + + + + Initialise a new instance of GZipException with its message string. + + A that describes the error. + + + + Initialise a new instance of . + + A that describes the error. + The that caused this exception. + + + + Contains the output from the Inflation process. + We need to have a window so that we can refer backwards into the output stream + to repeat stuff.
+ Author of the original java version : John Leuner +
+
+ + + Write a byte to this output window + + value to write + + if window is full + + + + + Append a byte pattern already in the window itself + + length of pattern to copy + distance from end of window pattern occurs + + If the repeated data overflows the window + + + + + Copy from input manipulator to internal window + + source of data + length of data to copy + the number of bytes copied + + + + Copy dictionary to window + + source dictionary + offset of start in source dictionary + length of dictionary + + If window isnt empty + + + + + Get remaining unfilled space in window + + Number of bytes left in window + + + + Get bytes available for output in window + + Number of bytes filled + + + + Copy contents of window to output + + buffer to copy to + offset to start at + number of bytes to count + The number of bytes copied + + If a window underflow occurs + + + + + Reset by clearing window so GetAvailable returns 0 + + + + + Defines internal values for both compression and decompression + + + + + When multiplied by compression parameter (1-9) gives the block size for compression + 9 gives the best compresssion but uses the most memory. + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Random numbers used to randomise repetitive blocks + + + + + This filter stream is used to compress a stream into a "GZIP" stream. + The "GZIP" format is described in RFC 1952. + + author of the original java version : John Leuner + + This sample shows how to gzip a file + + using System; + using System.IO; + + using ICSharpCode.SharpZipLib.GZip; + using ICSharpCode.SharpZipLib.Core; + + class MainClass + { + public static void Main(string[] args) + { + using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz"))) + using (FileStream fs = File.OpenRead(args[0])) { + byte[] writeData = new byte[4096]; + Streamutils.Copy(s, fs, writeData); + } + } + } + } + + + + + + CRC-32 value for uncompressed data + + + + + Creates a GzipOutputStream with the default buffer size + + + The stream to read data (to be compressed) from + + + + + Creates a GZipOutputStream with the specified buffer size + + + The stream to read data (to be compressed) from + + + Size of the buffer to use + + + + + Sets the active compression level (1-9). The new level will be activated + immediately. + + The compression level to set. + + Level specified is not supported. + + + + + + Get the current compression level. + + The current compression level. + + + + Write given buffer to output updating crc + + Buffer to write + Offset of first byte in buf to write + Number of bytes to write + + + + Writes remaining compressed output data to the output stream + and closes it. + + + + + Finish compression and write any footer information required to stream + + + + + Arguments used with KeysRequiredEvent + + + + + Initialise a new instance of + + The name of the file for which keys are required. + + + + Initialise a new instance of + + The name of the file for which keys are required. + The current key value. + + + + Get the name of the file for which keys are required. + + + + + Get/set the key value + + + + + The strategy to apply to testing. + + + + + Find the first error only. + + + + + Find all possible errors. + + + + + The operation in progress reported by a during testing. + + TestArchive + + + + Setting up testing. + + + + + Testing an individual entries header + + + + + Testing an individual entries data + + + + + Testing an individual entry has completed. + + + + + Running miscellaneous tests + + + + + Testing is complete + + + + + Status returned returned by during testing. + + TestArchive + + + + Initialise a new instance of + + The this status applies to. + + + + Get the current in progress. + + + + + Get the this status is applicable to. + + + + + Get the current/last entry tested. + + + + + Get the number of errors detected so far. + + + + + Get the number of bytes tested so far for the current entry. + + + + + Get a value indicating wether the last entry test was valid. + + + + + Delegate invoked during testing if supplied indicating current progress and status. + + If the message is non-null an error has occured. If the message is null + the operation as found in status has started. + + + + The possible ways of applying updates to an archive. + + + + + Perform all updates on temporary files ensuring that the original file is saved. + + + + + Update the archive directly, which is faster but less safe. + + + + + This class represents a Zip archive. You can ask for the contained + entries, or get an input stream for a file entry. The entry is + automatically decompressed. + + You can also update the archive adding or deleting entries. + + This class is thread safe for input: You can open input streams for arbitrary + entries in different threads. +
+
Author of the original java version : Jochen Hoenicke +
+ + + using System; + using System.Text; + using System.Collections; + using System.IO; + + using ICSharpCode.SharpZipLib.Zip; + + class MainClass + { + static public void Main(string[] args) + { + using (ZipFile zFile = new ZipFile(args[0])) { + Console.WriteLine("Listing of : " + zFile.Name); + Console.WriteLine(""); + Console.WriteLine("Raw Size Size Date Time Name"); + Console.WriteLine("-------- -------- -------- ------ ---------"); + foreach (ZipEntry e in zFile) { + if ( e.IsFile ) { + DateTime d = e.DateTime; + Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize, + d.ToString("dd-MM-yy"), d.ToString("HH:mm"), + e.Name); + } + } + } + } + } + + +
+ + + Event handler for handling encryption keys. + + + + + Handles getting of encryption keys when required. + + The file for which encryption keys are required. + + + + Opens a Zip file with the given name for reading. + + The name of the file to open. + + An i/o error occurs + + + The file doesn't contain a valid zip archive. + + + + + Opens a Zip file reading the given . + + The to read archive data from. + + An i/o error occurs. + + + The file doesn't contain a valid zip archive. + + + + + Opens a Zip file reading the given . + + The to read archive data from. + + An i/o error occurs + + + The file doesn't contain a valid zip archive.
+ The stream provided cannot seek +
+
+ + + Initialises a default instance with no entries and no file storage. + + + + + Finalize this instance. + + + + + Closes the ZipFile. If the stream is owned then this also closes the underlying input stream. + Once closed, no further instance methods should be called. + + + An i/o error occurs. + + + + + Create a new whose data will be stored in a file. + + The name of the archive to create. + Returns the newly created + + + + Create a new whose data will be stored on a stream. + + The stream providing data storage. + Returns the newly created + + + + Gets an enumerator for the Zip entries in this Zip file. + + Returns an for this archive. + + The Zip file has been closed. + + + + + Return the index of the entry with a matching name + + Entry name to find + If true the comparison is case insensitive + The index position of the matching entry or -1 if not found + + The Zip file has been closed. + + + + + Searches for a zip entry in this archive with the given name. + String comparisons are case insensitive + + + The name to find. May contain directory components separated by slashes ('/'). + + + A clone of the zip entry, or null if no entry with that name exists. + + + The Zip file has been closed. + + + + + Gets an input stream for reading the given zip entry data in an uncompressed form. + Normally the should be an entry returned by GetEntry(). + + The to obtain a data for + An input containing data for this + + The ZipFile has already been closed + + + The compression method for the entry is unknown + + + The entry is not found in the ZipFile + + + + + Creates an input stream reading a zip entry + + The index of the entry to obtain an input stream for. + + An input containing data for this + + + The ZipFile has already been closed + + + The compression method for the entry is unknown + + + The entry is not found in the ZipFile + + + + + Test an archive for integrity/validity + + Perform low level data Crc check + true if all tests pass, false otherwise + Testing will terminate on the first error found. + + + + Test an archive for integrity/validity + + Perform low level data Crc check + The to apply. + The handler to call during testing. + true if all tests pass, false otherwise + + + + Test a local header against that provided from the central directory + + + The entry to test against + + The type of tests to carry out. + The offset of the entries data in the file + + + + Begin updating this archive. + + The archive storage for use during the update. + The data source to utilise during updating. + + + + Begin updating to this archive. + + The storage to use during the update. + + + + Begin updating this archive. + + + + + + + + Commit current updates, updating this archive. + + + + + + + Abort updating leaving the archive unchanged. + + + + + + + Set the file comment to be recorded when the current update is commited. + + The comment to record. + + + + Add a new entry to the archive. + + The name of the file to add. + The compression method to use. + Ensure Unicode text is used for name and comment for this entry. + + + + Add a new entry to the archive. + + The name of the file to add. + The compression method to use. + + + + Add a file to the archive. + + The name of the file to add. + + + + Add a file entry with data. + + The source of the data for this entry. + The name to give to the entry. + + + + Add a file entry with data. + + The source of the data for this entry. + The name to give to the entry. + The compression method to use. + + + + Add a file entry with data. + + The source of the data for this entry. + The name to give to the entry. + The compression method to use. + Ensure Unicode text is used for name and comments for this entry. + + + + Add a that contains no data. + + The entry to add. + This can be used to add directories, volume labels, or empty file entries. + + + + Add a directory entry to the archive. + + The directory to add. + + + + Delete an entry by name + + The filename to delete + True if the entry was found and deleted; false otherwise. + + + + Delete a from the archive. + + The entry to delete. + + + + Write an unsigned short in little endian byte order. + + + + + Write an int in little endian byte order. + + + + + Write an unsigned int in little endian byte order. + + + + + Write a long in little endian byte order. + + + + + Get a raw memory buffer. + + Returns a raw memory buffer. + + + + Get the size of the source descriptor for a . + + The update to get the size for. + The descriptor size, zero if there isnt one. + + + + Get an output stream for the specified + + The entry to get an output stream for. + The output stream obtained for the entry. + + + + Releases the unmanaged resources used by the this instance and optionally releases the managed resources. + + true to release both managed and unmanaged resources; + false to release only unmanaged resources. + + + + Read an unsigned short in little endian byte order. + + Returns the value read. + + The stream ends prematurely + + + + + Read a uint in little endian byte order. + + Returns the value read. + + An i/o error occurs. + + + The file ends prematurely + + + + + Search for and read the central directory of a zip file filling the entries array. + + + An i/o error occurs. + + + The central directory is malformed or cannot be found + + + + + Locate the data for a given entry. + + + The start offset of the data. + + + The stream ends prematurely + + + The local header signature is invalid, the entry and central header file name lengths are different + or the local and entry compression methods dont match + + + + + Get/set the encryption key value. + + + + + Password to be used for encrypting/decrypting files. + + Set to null if no password is required. + + + + Get a value indicating wether encryption keys are currently available. + + + + + Get/set a flag indicating if the underlying stream is owned by the ZipFile instance. + If the flag is true then the stream will be closed when Close is called. + + + The default value is true in all cases. + + + + + Get a value indicating wether + this archive is embedded in another file or not. + + + + + Get a value indicating that this archive is a new one. + + + + + Gets the comment for the zip file. + + + + + Gets the name of this zip file. + + + + + Gets the number of entries in this zip file. + + + The Zip file has been closed. + + + + + Get the number of entries contained in this . + + + + + Indexer property for ZipEntries + + + + + Get / set the to apply to names when updating. + + + + + Get/set the used to generate values + during updates. + + + + + Get /set the buffer size to be used when updating this zip file. + + + + + Get a value indicating an update has been started. + + + + + Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + + + + + Delegate for handling keys/password setting during compresion/decompression. + + + + + The kind of update to apply. + + + + + Class used to sort updates. + + + + + Compares two objects and returns a value indicating whether one is + less than, equal to or greater than the other. + + First object to compare + Second object to compare. + Compare result. + + + + Represents a pending update to a Zip file. + + + + + Copy an existing entry. + + The existing entry to copy. + + + + Get the for this update. + + This is the source or original entry. + + + + Get the that will be written to the updated/new file. + + + + + Get the command for this update. + + + + + Get the filename if any for this update. Null if none exists. + + + + + Get/set the location of the size patch for this update. + + + + + Get /set the location of the crc patch for this update. + + + + + Represents a string from a which is stored as an array of bytes. + + + + + Initialise a with a string. + + The textual string form. + + + + Initialise a using a string in its binary 'raw' form. + + + + + + Reset the comment to its initial state. + + + + + Implicit conversion of comment to a string. + + The to convert to a string. + The textual equivalent for the input value. + + + + Get a value indicating the original source of data for this instance. + True if the source was a string; false if the source was binary data. + + + + + Get the length of the comment when represented as raw bytes. + + + + + Get the comment in its 'raw' form as plain bytes. + + + + + An enumerator for Zip entries + + + + + An is a stream that you can write uncompressed data + to and flush, but cannot read, seek or do anything else to. + + + + + Close this stream instance. + + + + + Write any buffered data to underlying storage. + + + + + Gets a value indicating whether the current stream supports reading. + + + + + Gets a value indicating whether the current stream supports writing. + + + + + Gets a value indicating whether the current stream supports seeking. + + + + + Get the length in bytes of the stream. + + + + + Gets or sets the position within the current stream. + + + + + A is an + whose data is only a part or subsection of a file. + + + + + This filter stream is used to decompress data compressed using the "deflate" + format. The "deflate" format is described in RFC 1951. + + This stream may form the basis for other decompression filters, such + as the GZipInputStream. + + Author of the original java version : John Leuner. + + + + + Create an InflaterInputStream with the default decompressor + and a default buffer size of 4KB. + + + The InputStream to read bytes from + + + + + Create an InflaterInputStream with the specified decompressor + and a default buffer size of 4KB. + + + The source of input data + + + The decompressor used to decompress data read from baseInputStream + + + + + Create an InflaterInputStream with the specified decompressor + and the specified buffer size. + + + The InputStream to read bytes from + + + The decompressor to use + + + Size of the buffer to use + + + + + Skip specified number of bytes of uncompressed data + + + Number of bytes to skip + + + The number of bytes skipped, zero if the end of + stream has been reached + + + Number of bytes to skip is less than zero + + + + + Clear any cryptographic state. + + + + + Fills the buffer with more data to decompress. + + + Stream ends early + + + + + Flushes the baseInputStream + + + + + Sets the position within the current stream + Always throws a NotSupportedException + + The relative offset to seek to. + The defining where to seek from. + The new position in the stream. + Any access + + + + Set the length of the current stream + Always throws a NotSupportedException + + The new length value for the stream. + Any access + + + + Writes a sequence of bytes to stream and advances the current position + This method always throws a NotSupportedException + + Thew buffer containing data to write. + The offset of the first byte to write. + The number of bytes to write. + Any access + + + + Writes one byte to the current stream and advances the current position + Always throws a NotSupportedException + + The byte to write. + Any access + + + + Entry point to begin an asynchronous write. Always throws a NotSupportedException. + + The buffer to write data from + Offset of first byte to write + The maximum number of bytes to write + The method to be called when the asynchronous write operation is completed + A user-provided object that distinguishes this particular asynchronous write request from other requests + An IAsyncResult that references the asynchronous write + Any access + + + + Closes the input stream. When + is true the underlying stream is also closed. + + + + + Reads decompressed data into the provided buffer byte array + + + The array to read and decompress data into + + + The offset indicating where the data should be placed + + + The number of bytes to decompress + + The number of bytes read. Zero signals the end of stream + + Inflater needs a dictionary + + + + + Decompressor for this stream + + + + + Input buffer for this stream. + + + + + Base stream the inflater reads from. + + + + + The compressed size + + + + + Flag indicating wether this instance has been closed or not. + + + + + Flag indicating wether this instance is designated the stream owner. + When closing if this flag is true the underlying stream is closed. + + + + + Get/set flag indicating ownership of underlying stream. + When the flag is true will close the underlying stream also. + + + The default value is true. + + + + + Returns 0 once the end of the stream (EOF) has been reached. + Otherwise returns 1. + + + + + Gets a value indicating whether the current stream supports reading + + + + + Gets a value of false indicating seeking is not supported for this stream. + + + + + Gets a value of false indicating that this stream is not writeable. + + + + + A value representing the length of the stream in bytes. + + + + + The current position within the stream. + Throws a NotSupportedException when attempting to set the position + + Attempting to set the position + + + + Initialise a new instance of the class. + + The underlying stream to use for IO. + The start of the partial data. + The length of the partial data. + + + + Skip the specified number of input bytes. + + The maximum number of input bytes to skip. + The actuial number of input bytes skipped. + + + + Read a byte from this stream. + + Returns the byte read or -1 on end of stream. + + + + Close this partial input stream. + + + The underlying stream is not closed. Close the parent ZipFile class to do that. + + + + + Provides a static way to obtain a source of data for an entry. + + + + + Get a source of data by creating a new stream. + + Returns a to use for compression input. + Ideally a new stream is created and opened to achieve this, to avoid locking problems. + + + + Represents a source of data that can dynamically provide + multiple data sources based on the parameters passed. + + + + + Get a data source. + + The to get a source for. + The name for data if known. + Returns a to use for compression input. + Ideally a new stream is created and opened to achieve this, to avoid locking problems. + + + + Default implementation of a for use with files stored on disk. + + + + + Initialise a new instnace of + + The name of the file to obtain data from. + + + + Get a providing data. + + Returns a provising data. + + + + Default implementation of for files stored on disk. + + + + + Initialise a default instance of . + + + + + Get a providing data for an entry. + + The entry to provide data for. + The file name for data if known. + Returns a stream providing data; or null if not available + + + + Defines facilities for data storage when updating Zip Archives. + + + + + Get an empty that can be used for temporary output. + + Returns a temporary output + + + + + Convert a temporary output stream to a final stream. + + The resulting final + + + + + Make a temporary copy of the original stream. + + The to copy. + Returns a temporary output that is a copy of the input. + + + + Return a stream suitable for performing direct updates on the original source. + + The current stream. + Returns a stream suitable for direct updating. + This may be the current stream passed. + + + + Dispose of this instance. + + + + + Get the to apply during updates. + + + + + An abstract suitable for extension by inheritance. + + + + + Initializes a new instance of the class. + + The update mode. + + + + Gets a temporary output + + Returns the temporary output stream. + + + + + Converts the temporary to its final form. + + Returns a that can be used to read + the final storage for the archive. + + + + + Make a temporary copy of a . + + The to make a copy of. + Returns a temporary output that is a copy of the input. + + + + Return a stream suitable for performing direct updates on the original source. + + The to open for direct update. + Returns a stream suitable for direct updating. + + + + Disposes this instance. + + + + + Gets the update mode applicable. + + The update mode. + + + + An implementation suitable for hard disks. + + + + + Initializes a new instance of the class. + + The file. + The update mode. + + + + Initializes a new instance of the class. + + The file. + + + + Gets a temporary output for performing updates on. + + Returns the temporary output stream. + + + + Converts a temporary to its final form. + + Returns a that can be used to read + the final storage for the archive. + + + + Make a temporary copy of a stream. + + The to copy. + Returns a temporary output that is a copy of the input. + + + + Return a stream suitable for performing direct updates on the original source. + + The current stream. + Returns a stream suitable for direct updating. + If the stream is not null this is used as is. + + + + Disposes this instance. + + + + + An implementation suitable for in memory streams. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The to use + This constructor is for testing as memory streams dont really require safe mode. + + + + Gets the temporary output + + Returns the temporary output stream. + + + + Converts the temporary to its final form. + + Returns a that can be used to read + the final storage for the archive. + + + + Make a temporary copy of the original stream. + + The to copy. + Returns a temporary output that is a copy of the input. + + + + Return a stream suitable for performing direct updates on the original source. + + The original source stream + Returns a stream suitable for direct updating. + If the passed is not null this is used; + otherwise a new is returned. + + + + Disposes this instance. + + + + + Get the stream returned by if this was in fact called. + + + + + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. + + + + + Interface to compute a data checksum used by checked input/output streams. + A data checksum can be updated by one byte or with a byte array. After each + update the value of the current checksum can be returned by calling + getValue. The complete checksum object can also be reset + so it can be used again with new data. + + + + + Resets the data checksum as if no update was ever called. + + + + + Adds one byte to the data checksum. + + + the data value to add. The high byte of the int is ignored. + + + + + Updates the data checksum with the bytes taken from the array. + + + buffer an array of bytes + + + + + Adds the byte array to the data checksum. + + + The buffer which contains the data + + + The offset in the buffer where the data starts + + + the number of data bytes to add. + + + + + Returns the data checksum computed so far. + + + + + The crc data checksum so far. + + + + + Resets the CRC32 data checksum as if no update was ever called. + + + + + Updates the checksum with the int bval. + + + the byte is taken as the lower 8 bits of value + + + + + Updates the checksum with the bytes taken from the array. + + + buffer an array of bytes + + + + + Adds the byte array to the data checksum. + + + The buffer which contains the data + + + The offset in the buffer where the data starts + + + The number of data bytes to update the CRC with. + + + + + Returns the CRC32 data checksum computed so far. + + + + + Basic implementation of + + + + + Defines factory methods for creating new values. + + + + + Create a for a file given its name + + The name of the file to create an entry for. + Returns a file entry based on the passed. + + + + Create a for a file given its name + + The name of the file to create an entry for. + If true get details from the file system if the file exists. + Returns a file entry based on the passed. + + + + Create a for a directory given its name + + The name of the directory to create an entry for. + Returns a directory entry based on the passed. + + + + Create a for a directory given its name + + The name of the directory to create an entry for. + If true get details from the file system for this directory if it exists. + Returns a directory entry based on the passed. + + + + Get/set the applicable. + + + + + Initialise a new instance of the class. + + A default , and the LastWriteTime for files is used. + + + + Initialise a new instance of using the specified + + The time setting to use when creating Zip entries. + + + + Initialise a new instance of using the specified + + The time to set all values to. + + + + Make a new for a file. + + The name of the file to create a new entry for. + Returns a new based on the . + + + + Make a new from a name. + + The name of the file to create a new entry for. + If true entry detail is retrieved from the file system if the file exists. + Returns a new based on the . + + + + Make a new for a directory. + + The raw untransformed name for the new directory + Returns a new representing a directory. + + + + Make a new for a directory. + + The raw untransformed name for the new directory + If true entry detail is retrieved from the file system if the file exists. + Returns a new representing a directory. + + + + Get / set the to be used when creating new values. + + + Setting this property to null will cause a default name transform to be used. + + + + + Get / set the in use. + + + + + Get / set the value to use when is set to + + + + + A bitmask defining the attributes to be retrieved from the actual file. + + The default is to get all possible attributes from the actual file. + + + + A bitmask defining which attributes are to be set on. + + By default no attributes are set on. + + + + Get set a value indicating wether unidoce text should be set on. + + + + + Defines the possible values to be used for the . + + + + + Use the recorded LastWriteTime value for the file. + + + + + Use the recorded LastWriteTimeUtc value for the file + + + + + Use the recorded CreateTime value for the file. + + + + + Use the recorded CreateTimeUtc value for the file. + + + + + Use the recorded LastAccessTime value for the file. + + + + + Use the recorded LastAccessTimeUtc value for the file. + + + + + Use a fixed value. + + The actual value used can be + specified via the constructor or + using the with the setting set + to which will use the when this class was constructed. + The property can also be used to set this value. + + + + PkzipClassic embodies the classic or original encryption facilities used in Pkzip archives. + While it has been superceded by more recent and more powerful algorithms, its still in use and + is viable for preventing casual snooping + + + + + Generates new encryption keys based on given seed + + The seed value to initialise keys with. + A new key value. + + + + PkzipClassicCryptoBase provides the low level facilities for encryption + and decryption using the PkzipClassic algorithm. + + + + + Transform a single byte + + + The transformed value + + + + + Set the key schedule for encryption/decryption. + + The data use to set the keys from. + + + + Update encryption keys + + + + + Reset the internal state. + + + + + PkzipClassic CryptoTransform for encryption. + + + + + Initialise a new instance of + + The key block to use. + + + + Transforms the specified region of the specified byte array. + + The input for which to compute the transform. + The offset into the byte array from which to begin using data. + The number of bytes in the byte array to use as data. + The computed transform. + + + + Transforms the specified region of the input byte array and copies + the resulting transform to the specified region of the output byte array. + + The input for which to compute the transform. + The offset into the input byte array from which to begin using data. + The number of bytes in the input byte array to use as data. + The output to which to write the transform. + The offset into the output byte array from which to begin writing data. + The number of bytes written. + + + + Cleanup internal state. + + + + + Gets a value indicating whether the current transform can be reused. + + + + + Gets the size of the input data blocks in bytes. + + + + + Gets the size of the output data blocks in bytes. + + + + + Gets a value indicating whether multiple blocks can be transformed. + + + + + PkzipClassic CryptoTransform for decryption. + + + + + Initialise a new instance of . + + The key block to decrypt with. + + + + Transforms the specified region of the specified byte array. + + The input for which to compute the transform. + The offset into the byte array from which to begin using data. + The number of bytes in the byte array to use as data. + The computed transform. + + + + Transforms the specified region of the input byte array and copies + the resulting transform to the specified region of the output byte array. + + The input for which to compute the transform. + The offset into the input byte array from which to begin using data. + The number of bytes in the input byte array to use as data. + The output to which to write the transform. + The offset into the output byte array from which to begin writing data. + The number of bytes written. + + + + Cleanup internal state. + + + + + Gets a value indicating whether the current transform can be reused. + + + + + Gets the size of the input data blocks in bytes. + + + + + Gets the size of the output data blocks in bytes. + + + + + Gets a value indicating whether multiple blocks can be transformed. + + + + + Defines a wrapper object to access the Pkzip algorithm. + This class cannot be inherited. + + + + + Generate an initial vector. + + + + + Generate a new random key. + + + + + Create an encryptor. + + The key to use for this encryptor. + Initialisation vector for the new encryptor. + Returns a new PkzipClassic encryptor + + + + Create a decryptor. + + Keys to use for this new decryptor. + Initialisation vector for the new decryptor. + Returns a new decryptor. + + + + Get / set the applicable block size in bits. + + The only valid block size is 8. + + + + Get an array of legal key sizes. + + + + + Get an array of legal block sizes. + + + + + Get / set the key value applicable. + + + + + This class represents an entry in a Tar archive. It consists + of the entry's header, as well as the entry's File. Entries + can be instantiated in one of three ways, depending on how + they are to be used. +

+ TarEntries that are created from the header bytes read from + an archive are instantiated with the TarEntry( byte[] ) + constructor. These entries will be used when extracting from + or listing the contents of an archive. These entries have their + header filled in using the header bytes. They also set the File + to null, since they reference an archive entry not a file.

+

+ TarEntries that are created from files that are to be written + into an archive are instantiated with the CreateEntryFromFile(string) + pseudo constructor. These entries have their header filled in using + the File's information. They also keep a reference to the File + for convenience when writing entries.

+

+ Finally, TarEntries can be constructed from nothing but a name. + This allows the programmer to construct the entry by hand, for + instance when only an InputStream is available for writing to + the archive, and the header information is constructed from + other information. In this case the header fields are set to + defaults and the File is set to null.

+ +
+
+ + + Initialise a default instance of . + + + + + Construct an entry from an archive's header bytes. File is set + to null. + + + The header bytes from a tar archive entry. + + + + + Construct a TarEntry using the header provided + + Header details for entry + + + + Clone this tar entry. + + Returns a clone of this entry. + + + + Construct an entry with only a name. + This allows the programmer to construct the entry's header "by hand". + + The name to use for the entry + Returns the newly created + + + + Construct an entry for a file. File is set to file, and the + header is constructed from information from the file. + + The file name that the entry represents. + Returns the newly created + + + + Determine if the two entries are equal. Equality is determined + by the header names being equal. + + The to compare with the current Object. + + True if the entries are equal; false if not. + + + + + Derive a Hash value for the current + + A Hash code for the current + + + + Determine if the given entry is a descendant of this entry. + Descendancy is determined by the name of the descendant + starting with this entry's name. + + + Entry to be checked as a descendent of this. + + + True if entry is a descendant of this. + + + + + Convenience method to set this entry's group and user ids. + + + This entry's new user id. + + + This entry's new group id. + + + + + Convenience method to set this entry's group and user names. + + + This entry's new user name. + + + This entry's new group name. + + + + + Fill in a TarHeader with information from a File. + + + The TarHeader to fill in. + + + The file from which to get the header information. + + + + + Get entries for all files present in this entries directory. + If this entry doesnt represent a directory zero entries are returned. + + + An array of TarEntry's for this entry's children. + + + + + Write an entry's header information to a header buffer. + + + The tar entry header buffer to fill in. + + + + + Convenience method that will modify an entry's name directly + in place in an entry header buffer byte array. + + + The buffer containing the entry header to modify. + + + The new name to place into the header buffer. + + + + + Fill in a TarHeader given only the entry's name. + + + The TarHeader to fill in. + + + The tar entry name. + + + + + The name of the file this entry represents or null if the entry is not based on a file. + + + + + The entry's header information. + + + + + Get this entry's header. + + + This entry's TarHeader. + + + + + Get/Set this entry's name. + + + + + Get/set this entry's user id. + + + + + Get/set this entry's group id. + + + + + Get/set this entry's user name. + + + + + Get/set this entry's group name. + + + + + Get/Set the modification time for this entry + + + + + Get this entry's file. + + + This entry's file. + + + + + Get/set this entry's recorded file size. + + + + + Return true if this entry represents a directory, false otherwise + + + True if this entry is a directory. + + + + + This filter stream is used to decompress a "GZIP" format stream. + The "GZIP" format is described baseInputStream RFC 1952. + + author of the original java version : John Leuner + + This sample shows how to unzip a gzipped file + + using System; + using System.IO; + + using ICSharpCode.SharpZipLib.Core; + using ICSharpCode.SharpZipLib.GZip; + + class MainClass + { + public static void Main(string[] args) + { + using (Stream inStream = new GZipInputStream(File.OpenRead(args[0]))) + using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + byte[] buffer = new byte[4096]; + StreamUtils.Copy(inStream, outStream, buffer); + } + } + } + + + + + + CRC-32 value for uncompressed data + + + + + Indicates end of stream + + + + + Creates a GZipInputStream with the default buffer size + + + The stream to read compressed data from (baseInputStream GZIP format) + + + + + Creates a GZIPInputStream with the specified buffer size + + + The stream to read compressed data from (baseInputStream GZIP format) + + + Size of the buffer to use + + + + + Reads uncompressed data into an array of bytes + + + The buffer to read uncompressed data into + + + The offset indicating where the data should be placed + + + The number of uncompressed bytes to be read + + Returns the number of bytes actually read. + + + + Provides simple " utilities. + + + + + Read from a ensuring all the required data is read. + + The stream to read. + The buffer to fill. + + + + Read from a " ensuring all the required data is read. + + The stream to read data from. + The buffer to store data in. + The offset at which to begin storing data. + The number of bytes of data to store. + + + + Copy the contents of one to another. + + The stream to source data from. + The stream to write data to. + The buffer to use during copying. + The progress handler delegate to use. + The minimum between progress updates. + The source for this event. + The name to use with the event. + + + + Copy the contents of one to another. + + The stream to source data from. + The stream to write data to. + The buffer to use during copying. + + + + Initialise an instance of + + + + + This is the DeflaterHuffman class. + + This class is not thread safe. This is inherent in the API, due + to the split of Deflate and SetInput. + + author of the original java version : Jochen Hoenicke + + + + + Pending buffer to use + + + + + Construct instance with pending buffer + + Pending buffer to use + + + + Reset internal state + + + + + Write all trees to pending buffer + + The number/rank of treecodes to send. + + + + Compress current buffer writing data to pending buffer + + + + + Flush block to output with no compression + + Data to write + Index of first byte to write + Count of bytes to write + True if this is the last block + + + + Flush block to output with compression + + Data to flush + Index of first byte to flush + Count of bytes to flush + True if this is the last block + + + + Get value indicating if internal buffer is full + + true if buffer is full + + + + Add literal to buffer + + Literal value to add to buffer. + Value indicating internal buffer is full + + + + Add distance code and length to literal and distance trees + + Distance code + Length + Value indicating if internal buffer is full + + + + Reverse the bits of a 16 bit value. + + Value to reverse bits + Value with bits reversed + + + + Resets the internal state of the tree + + + + + Check that all frequencies are zero + + + At least one frequency is non-zero + + + + + Set static codes and length + + new codes + length for new codes + + + + Build dynamic codes and lengths + + + + + Get encoded length + + Encoded length, the sum of frequencies * lengths + + + + Scan a literal or distance tree to determine the frequencies of the codes + in the bit length tree. + + + + + Write tree values + + Tree to write + + + + This class contains constants used for gzip. + + + + + Magic number found at start of GZIP header + + + + + Flag bit mask for text + + + + + Flag bitmask for Crc + + + + + Flag bit mask for extra + + + + + flag bitmask for name + + + + + flag bit mask indicating comment is present + + + + + Initialise default instance. + + Constructor is private to prevent instances being created. + + + + TarExceptions are used for exceptions specific to tar classes and code. + + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initialises a new instance of the TarException class. + + + + + Initialises a new instance of the TarException class with a specified message. + + The message that describes the error. + + + + + + A message describing the error. + The exception that is the cause of the current exception. + + + + Bzip2 checksum algorithm + + + + + Initialise a default instance of + + + + + Reset the state of Crc. + + + + + Update the Crc value. + + data update is based on + + + + Update Crc based on a block of data + + The buffer containing data to update the crc with. + + + + Update Crc based on a portion of a block of data + + block of data + index of first byte to use + number of bytes to use + + + + Get the current Crc value. + + + + + This is an InflaterInputStream that reads the files baseInputStream an zip archive + one after another. It has a special method to get the zip entry of + the next file. The zip entry contains information about the file name + size, compressed size, Crc, etc. + It includes support for Stored and Deflated entries. +
+
Author of the original java version : Jochen Hoenicke +
+ + This sample shows how to read a zip file + + using System; + using System.Text; + using System.IO; + + using ICSharpCode.SharpZipLib.Zip; + + class MainClass + { + public static void Main(string[] args) + { + using ( ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]))) { + + ZipEntry theEntry; + while ((theEntry = s.GetNextEntry()) != null) { + int size = 2048; + byte[] data = new byte[2048]; + + Console.Write("Show contents (y/n) ?"); + if (Console.ReadLine() == "y") { + while (true) { + size = s.Read(data, 0, data.Length); + if (size > 0) { + Console.Write(new ASCIIEncoding().GetString(data, 0, size)); + } else { + break; + } + } + } + } + } + } + } + + +
+ + + The current reader this instance. + + + + + Creates a new Zip input stream, for reading a zip archive. + + The underlying providing data. + + + + Advances to the next entry in the archive + + + The next entry in the archive or null if there are no more entries. + + + If the previous entry is still open CloseEntry is called. + + + Input stream is closed + + + Password is not set, password is invalid, compression method is invalid, + version required to extract is not supported + + + + + Read data descriptor at the end of compressed data. + + + + + Complete cleanup as the final part of closing. + + True if the crc value should be tested + + + + Closes the current zip entry and moves to the next one. + + + The stream is closed + + + The Zip stream ends early + + + + + Reads a byte from the current zip entry. + + + The byte or -1 if end of stream is reached. + + + + + Handle attempts to read by throwing an . + + The destination array to store data in. + The offset at which data read should be stored. + The maximum number of bytes to read. + Returns the number of bytes actually read. + + + + Handle attempts to read from this entry by throwing an exception + + + + + Perform the initial read on an entry which may include + reading encryption headers and setting up inflation. + + The destination to fill with data read. + The offset to start reading at. + The maximum number of bytes to read. + The actual number of bytes read. + + + + Read a block of bytes from the stream. + + The destination for the bytes. + The index to start storing data. + The number of bytes to attempt to read. + Returns the number of bytes read. + Zero bytes read means end of stream. + + + + Reads a block of bytes from the current zip entry. + + + The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream. + + + An i/o error occured. + + + The deflated stream is corrupted. + + + The stream is not open. + + + + + Closes the zip input stream + + + + + Optional password used for encryption when non-null + + A password for all encrypted entries in this + + + + Gets a value indicating if there is a current entry and it can be decompressed + + + The entry can only be decompressed if the library supports the zip features required to extract it. + See the ZipEntry Version property for more details. + + + + + Returns 1 if there is an entry available + Otherwise returns 0. + + + + + Returns the current size that can be read from the current entry if available + + Thrown if the entry size is not known. + Thrown if no entry is currently available. + + + + ZipNameTransform transforms names as per the Zip file naming convention. + + The use of absolute names is supported although its use is not valid + according to Zip naming conventions, and should not be used if maximum compatability is desired. + + + + Initialize a new instance of + + + + + Initialize a new instance of + + The string to trim from front of paths if found. + + + + Static constructor. + + + + + Transform a directory name according to the Zip file naming conventions. + + The directory name to transform. + The transformed name. + + + + Transform a windows file name according to the Zip file naming conventions. + + The file name to transform. + The transformed name. + + + + Force a name to be valid by replacing invalid characters with a fixed value + + The name to force valid + The replacement character to use. + Returns a valid name + + + + Test a name to see if it is a valid name for a zip entry. + + The name to test. + If true checking is relaxed about windows file names and absolute paths. + Returns true if the name is a valid zip name; false otherwise. + Zip path names are actually in Unix format, and should only contain relative paths. + This means that any path stored should not contain a drive or + device letter, or a leading slash. All slashes should forward slashes '/'. + An empty name is valid for a file where the input comes from standard input. + A null name is not considered valid. + + + + + Test a name to see if it is a valid name for a zip entry. + + The name to test. + Returns true if the name is a valid zip name; false otherwise. + Zip path names are actually in unix format, + and should only contain relative paths if a path is present. + This means that the path stored should not contain a drive or + device letter, or a leading slash. All slashes should forward slashes '/'. + An empty name is valid where the input comes from standard input. + A null name is not considered valid. + + + + + Get/set the path prefix to be trimmed from paths if present. + + The prefix is trimmed before any conversion from + a windows path is done. + + + + This exception is used to indicate that there is a problem + with a TAR archive header. + + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initialise a new instance of the InvalidHeaderException class. + + + + + Initialises a new instance of the InvalidHeaderException class with a specified message. + + Message describing the exception cause. + + + + Initialise a new instance of InvalidHeaderException + + Message describing the problem. + The exception that is the cause of the current exception. + + + + This class allows us to retrieve a specified number of bits from + the input buffer, as well as copy big byte blocks. + + It uses an int buffer to store up to 31 bits for direct + manipulation. This guarantees that we can get at least 16 bits, + but we only need at most 15, so this is all safe. + + There are some optimizations in this class, for example, you must + never peek more than 8 bits more than needed, and you must first + peek bits before you may drop them. This is not a general purpose + class but optimized for the behaviour of the Inflater. + + authors of the original java version : John Leuner, Jochen Hoenicke + + + + + Constructs a default StreamManipulator with all buffers empty + + + + + Get the next sequence of bits but don't increase input pointer. bitCount must be + less or equal 16 and if this call succeeds, you must drop + at least n - 8 bits in the next call. + + The number of bits to peek. + + the value of the bits, or -1 if not enough bits available. */ + + + + + Drops the next n bits from the input. You should have called PeekBits + with a bigger or equal n before, to make sure that enough bits are in + the bit buffer. + + The number of bits to drop. + + + + Gets the next n bits and increases input pointer. This is equivalent + to followed by , except for correct error handling. + + The number of bits to retrieve. + + the value of the bits, or -1 if not enough bits available. + + + + + Skips to the next byte boundary. + + + + + Copies bytes from input buffer to output buffer starting + at output[offset]. You have to make sure, that the buffer is + byte aligned. If not enough bytes are available, copies fewer + bytes. + + + The buffer to copy bytes to. + + + The offset in the buffer at which copying starts + + + The length to copy, 0 is allowed. + + + The number of bytes copied, 0 if no bytes were available. + + + Length is less than zero + + + Bit buffer isnt byte aligned + + + + + Resets state and empties internal buffers + + + + + Add more input for consumption. + Only call when IsNeedingInput returns true + + data to be input + offset of first byte of input + number of bytes of input to add. + + + + Gets the number of bits available in the bit buffer. This must be + only called when a previous PeekBits() returned -1. + + + the number of bits available. + + + + + Gets the number of bytes available. + + + The number of bytes available. + + + + + Returns true when SetInput can be called + + + + + Strategies for deflater + + + + + The default strategy + + + + + This strategy will only allow longer string repetitions. It is + useful for random data with a small character set. + + + + + This strategy will not look for string repetitions at all. It + only encodes with Huffman trees (which means, that more common + characters get a smaller encoding. + + + + + Low level compression engine for deflate algorithm which uses a 32K sliding window + with secondary compression from Huffman/Shannon-Fano codes. + + + + + Construct instance with pending buffer + + + Pending buffer to use + > + + + + Deflate drives actual compression of data + + True to flush input buffers + Finish deflation with the current input. + Returns true if progress has been made. + + + + Sets input data to be deflated. Should only be called when NeedsInput() + returns true + + The buffer containing input data. + The offset of the first byte of data. + The number of bytes of data to use as input. + + + + Determines if more input is needed. + + Return true if input is needed via SetInput + + + + Set compression dictionary + + The buffer containing the dictionary data + The offset in the buffer for the first byte of data + The length of the dictionary data. + + + + Reset internal state + + + + + Reset Adler checksum + + + + + Set the deflate level (0-9) + + The value to set the level to. + + + + Fill the window + + + + + Inserts the current string in the head hash and returns the previous + value for this hash. + + The previous hash value + + + + Find the best (longest) string in the window matching the + string starting at strstart. + + Preconditions: + + strstart + MAX_MATCH <= window.length. + + + True if a match greater than the minimum length is found + + + + Hashtable, hashing three characters to an index for window, so + that window[index]..window[index+2] have this hash code. + Note that the array should really be unsigned short, so you need + to and the values with 0xffff. + + + + + prev[index & WMASK] points to the previous index that has the + same hash code as the string starting at index. This way + entries with the same hash code are in a linked list. + Note that the array should really be unsigned short, so you need + to and the values with 0xffff. + + + + + Points to the current character in the window. + + + + + lookahead is the number of characters starting at strstart in + window that are valid. + So window[strstart] until window[strstart+lookahead-1] are valid + characters. + + + + + This array contains the part of the uncompressed stream that + is of relevance. The current character is indexed by strstart. + + + + + The current compression function. + + + + + The input data for compression. + + + + + The total bytes of input read. + + + + + The offset into inputBuf, where input data starts. + + + + + The end offset of the input data. + + + + + The adler checksum + + + + + Get current value of Adler checksum + + + + + Total data processed + + + + + Get/set the deflate strategy + + + + + The TarBuffer class implements the tar archive concept + of a buffered input stream. This concept goes back to the + days of blocked tape drives and special io devices. In the + C# universe, the only real function that this class + performs is to ensure that files have the correct "record" + size, or other tars will complain. +

+ You should never have a need to access this class directly. + TarBuffers are created by Tar IO Streams. +

+
+
+ + + The size of a block in a tar archive in bytes. + + This is 512 bytes. + + + + The number of blocks in a default record. + + + The default value is 20 blocks per record. + + + + + The size in bytes of a default record. + + + The default size is 10KB. + + + + + Get the TAR Buffer's record size. + + The record size in bytes. + This is equal to the multiplied by the + + + + Get the TAR Buffer's block factor + + The block factor; the number of blocks per record. + + + + Construct a default TarBuffer + + + + + Create TarBuffer for reading with default BlockFactor + + Stream to buffer + A new suitable for input. + + + + Construct TarBuffer for reading inputStream setting BlockFactor + + Stream to buffer + Blocking factor to apply + A new suitable for input. + + + + Construct TarBuffer for writing with default BlockFactor + + output stream for buffer + A new suitable for output. + + + + Construct TarBuffer for writing Tar output to streams. + + Output stream to write to. + Blocking factor to apply + A new suitable for output. + + + + Initialization common to all constructors. + + + + + Determine if an archive block indicates End of Archive. End of + archive is indicated by a block that consists entirely of null bytes. + All remaining blocks for the record should also be null's + However some older tars only do a couple of null blocks (Old GNU tar for one) + and also partial records + + The data block to check. + Returns true if the block is an EOF block; false otherwise. + + + + Skip over a block on the input stream. + + + + + Read a block from the input stream. + + + The block of data read. + + + + + Read a record from data stream. + + + false if End-Of-File, else true. + + + + + Get the current block number, within the current record, zero based. + + + The current zero based block number. + + + The absolute block number = (record number * block factor) + block number. + + + + + Get the current record number. + + + The current zero based record number. + + + + + Write a block of data to the archive. + + + The data to write to the archive. + + + + + Write an archive record to the archive, where the record may be + inside of a larger array buffer. The buffer must be "offset plus + record size" long. + + + The buffer containing the record data to write. + + + The offset of the record data within buffer. + + + + + Write a TarBuffer record to the archive. + + + + + Flush the current record if it has any data in it. + + + + + Close the TarBuffer. If this is an output buffer, also flush the + current block before closing. + + + + + Get the record size for this buffer + + The record size in bytes. + This is equal to the multiplied by the + + + + Get the Blocking factor for the buffer + + This is the number of block in each record. + + + + Get the current block number, within the current record, zero based. + + + + + Get the current record number. + + + The current zero based record number. + + + + + This class encapsulates the Tar Entry Header used in Tar Archives. + The class also holds a number of tar constants, used mostly in headers. + + + + + The length of the name field in a header buffer. + + + + + The length of the mode field in a header buffer. + + + + + The length of the user id field in a header buffer. + + + + + The length of the group id field in a header buffer. + + + + + The length of the checksum field in a header buffer. + + + + + Offset of checksum in a header buffer. + + + + + The length of the size field in a header buffer. + + + + + The length of the magic field in a header buffer. + + + + + The length of the version field in a header buffer. + + + + + The length of the modification time field in a header buffer. + + + + + The length of the user name field in a header buffer. + + + + + The length of the group name field in a header buffer. + + + + + The length of the devices field in a header buffer. + + + + + The "old way" of indicating a normal file. + + + + + Normal file type. + + + + + Link file type. + + + + + Symbolic link file type. + + + + + Character device file type. + + + + + Block device file type. + + + + + Directory file type. + + + + + FIFO (pipe) file type. + + + + + Contiguous file type. + + + + + Posix.1 2001 global extended header + + + + + Posix.1 2001 extended header + + + + + Solaris access control list file type + + + + + GNU dir dump file type + This is a dir entry that contains the names of files that were in the + dir at the time the dump was made + + + + + Solaris Extended Attribute File + + + + + Inode (metadata only) no file content + + + + + Identifies the next file on the tape as having a long link name + + + + + Identifies the next file on the tape as having a long name + + + + + Continuation of a file that began on another volume + + + + + For storing filenames that dont fit in the main header (old GNU) + + + + + GNU Sparse file + + + + + GNU Tape/volume header ignore on extraction + + + + + The magic tag representing a POSIX tar archive. (includes trailing NULL) + + + + + The magic tag representing an old GNU tar archive where version is included in magic and overwrites it + + + + + Initialise a default TarHeader instance + + + + + Get the name of this entry. + + The entry's name. + + + + Create a new that is a copy of the current instance. + + A new that is a copy of the current instance. + + + + Parse TarHeader information from a header buffer. + + + The tar entry header buffer to get information from. + + + + + 'Write' header information to buffer provided, updating the check sum. + + output buffer for header information + + + + Get a hash code for the current object. + + A hash code for the current object. + + + + Determines if this instance is equal to the specified object. + + The object to compare with. + true if the objects are equal, false otherwise. + + + + Set defaults for values used when constructing a TarHeader instance. + + Value to apply as a default for userId. + Value to apply as a default for userName. + Value to apply as a default for groupId. + Value to apply as a default for groupName. + + + + Parse an octal string from a header buffer. + + The header buffer from which to parse. + The offset into the buffer from which to parse. + The number of header bytes to parse. + The long equivalent of the octal string. + + + + Parse a name from a header buffer. + + + The header buffer from which to parse. + + + The offset into the buffer from which to parse. + + + The number of header bytes to parse. + + + The name parsed. + + + + + Add name to the buffer as a collection of bytes + + The name to add + The offset of the first character + The buffer to add to + The index of the first byte to add + The number of characters/bytes to add + The next free index in the buffer + + + + Add name to the buffer as a collection of bytes + + The name to add + The offset of the first character + The buffer to add to + The index of the first byte to add + The number of characters/bytes to add + The next free index in the buffer + + + + Add an entry name to the buffer + + + The name to add + + + The buffer to add to + + + The offset into the buffer from which to start adding + + + The number of header bytes to add + + + The index of the next free byte in the buffer + + + + + Add an entry name to the buffer + + The name to add + The buffer to add to + The offset into the buffer from which to start adding + The number of header bytes to add + The index of the next free byte in the buffer + + + + Add a string to a buffer as a collection of ascii bytes. + + The string to add + The offset of the first character to add. + The buffer to add to. + The offset to start adding at. + The number of ascii characters to add. + The next free index in the buffer. + + + + Put an octal representation of a value into a buffer + + + the value to be converted to octal + + + buffer to store the octal string + + + The offset into the buffer where the value starts + + + The length of the octal string to create + + + The offset of the character next byte after the octal string + + + + + Put an octal representation of a value into a buffer + + Value to be convert to octal + The buffer to update + The offset into the buffer to store the value + The length of the octal string + Index of next byte + + + + Add the checksum integer to header buffer. + + + The header buffer to set the checksum for + The offset into the buffer for the checksum + The number of header bytes to update. + It's formatted differently from the other fields: it has 6 digits, a + null, then a space -- rather than digits, a space, then a null. + The final space is already there, from checksumming + + The modified buffer offset + + + + Compute the checksum for a tar entry header. + The checksum field must be all spaces prior to this happening + + The tar entry's header buffer. + The computed checksum. + + + + Make a checksum for a tar entry ignoring the checksum contents. + + The tar entry's header buffer. + The checksum for the buffer + + + + Get/set the name for this tar entry. + + Thrown when attempting to set the property to null. + + + + Get/set the entry's Unix style permission mode. + + + + + The entry's user id. + + + This is only directly relevant to unix systems. + The default is zero. + + + + + Get/set the entry's group id. + + + This is only directly relevant to linux/unix systems. + The default value is zero. + + + + + Get/set the entry's size. + + Thrown when setting the size to less than zero. + + + + Get/set the entry's modification time. + + + The modification time is only accurate to within a second. + + Thrown when setting the date time to less than 1/1/1970. + + + + Get the entry's checksum. This is only valid/updated after writing or reading an entry. + + + + + Get value of true if the header checksum is valid, false otherwise. + + + + + Get/set the entry's type flag. + + + + + The entry's link name. + + Thrown when attempting to set LinkName to null. + + + + Get/set the entry's magic tag. + + Thrown when attempting to set Magic to null. + + + + The entry's version. + + Thrown when attempting to set Version to null. + + + + The entry's user name. + + + + + Get/set the entry's group name. + + + This is only directly relevant to unix systems. + + + + + Get/set the entry's major device number. + + + + + Get/set the entry's minor device number. + + + + + Event arguments for scanning. + + + + + Initialise a new instance of + + The file or directory name. + + + + The fie or directory name for this event. + + + + + Get set a value indicating if scanning should continue or not. + + + + + Event arguments during processing of a single file or directory. + + + + + Initialise a new instance of + + The file or directory name if known. + The number of bytes processed so far + The total number of bytes to process, 0 if not known + + + + The name for this event if known. + + + + + Get set a value indicating wether scanning should continue or not. + + + + + Get a percentage representing how much of the has been processed + + 0.0 to 100.0 percent; 0 if target is not known. + + + + The number of bytes processed so far + + + + + The number of bytes to process. + + Target may be 0 or negative if the value isnt known. + + + + Event arguments for directories. + + + + + Initialize an instance of . + + The name for this directory. + Flag value indicating if any matching files are contained in this directory. + + + + Get a value indicating if the directory contains any matching files or not. + + + + + Arguments passed when scan failures are detected. + + + + + Initialise a new instance of + + The name to apply. + The exception to use. + + + + The applicable name. + + + + + The applicable exception. + + + + + Get / set a value indicating wether scanning should continue. + + + + + Delegate invoked before starting to process a directory. + + + + + Delegate invoked before starting to process a file. + + The source of the event + The event arguments. + + + + Delegate invoked during processing of a file or directory + + The source of the event + The event arguments. + + + + Delegate invoked when a file has been completely processed. + + The source of the event + The event arguments. + + + + Delegate invoked when a directory failure is detected. + + The source of the event + The event arguments. + + + + Delegate invoked when a file failure is detected. + + The source of the event + The event arguments. + + + + FileSystemScanner provides facilities scanning of files and directories. + + + + + Initialise a new instance of + + The file filter to apply when scanning. + + + + Initialise a new instance of + + The file filter to apply. + The directory filter to apply. + + + + Initialise a new instance of + + The file filter to apply. + + + + Initialise a new instance of + + The file filter to apply. + The directory filter to apply. + + + + Delegate to invoke when a directory is processed. + + + + + Delegate to invoke when a file is processed. + + + + + Delegate to invoke when processing for a file has finished. + + + + + Delegate to invoke when a directory failure is detected. + + + + + Delegate to invoke when a file failure is detected. + + + + + Raise the DirectoryFailure event. + + The directory name. + The exception detected. + + + + Raise the FileFailure event. + + The file name. + The exception detected. + + + + Raise the ProcessFile event. + + The file name. + + + + Raise the complete file event + + The file name + + + + Raise the ProcessDirectory event. + + The directory name. + Flag indicating if the directory has matching files. + + + + Scan a directory. + + The base directory to scan. + True to recurse subdirectories, false to scan a single directory. + + + + The file filter currently in use. + + + + + The directory filter currently in use. + + + + + Flag indicating if scanning should continue running. + + + + + An input buffer customised for use by + + + The buffer supports decryption of incoming data. + + + + + Initialise a new instance of with a default buffer size + + The stream to buffer. + + + + Initialise a new instance of + + The stream to buffer. + The size to use for the buffer + A minimum buffer size of 1KB is permitted. Lower sizes are treated as 1KB. + + + + Call passing the current clear text buffer contents. + + The inflater to set input for. + + + + Fill the buffer from the underlying input stream. + + + + + Read a buffer directly from the input stream + + The buffer to fill + Returns the number of bytes read. + + + + Read a buffer directly from the input stream + + The buffer to read into + The offset to start reading data into. + The number of bytes to read. + Returns the number of bytes read. + + + + Read clear text data from the input stream. + + The buffer to add data to. + The offset to start adding data at. + The number of bytes to read. + Returns the number of bytes actually read. + + + + Read a from the input stream. + + Returns the byte read. + + + + Read an in little endian byte order. + + The short value read case to an int. + + + + Read an in little endian byte order. + + The int value read. + + + + Read a in little endian byte order. + + The long value read. + + + + Get the length of bytes bytes in the + + + + + Get the contents of the raw data buffer. + + This may contain encrypted data. + + + + Get the number of useable bytes in + + + + + Get the contents of the clear text buffer. + + + + + Get/set the number of bytes available + + + + + Get/set the to apply to any data. + + Set this value to null to have no transform applied. + + + + The TarOutputStream writes a UNIX tar archive as an OutputStream. + Methods are provided to put entries, and then write their contents + by writing to this stream using write(). + + public + + + + Construct TarOutputStream using default block factor + + stream to write to + + + + Construct TarOutputStream with user specified block factor + + stream to write to + blocking factor + + + + set the position within the current stream + + The offset relative to the to seek to + The to seek from. + The new position in the stream. + + + + Set the length of the current stream + + The new stream length. + + + + Read a byte from the stream and advance the position within the stream + by one byte or returns -1 if at the end of the stream. + + The byte value or -1 if at end of stream + + + + read bytes from the current stream and advance the position within the + stream by the number of bytes read. + + The buffer to store read bytes in. + The index into the buffer to being storing bytes at. + The desired number of bytes to read. + The total number of bytes read, or zero if at the end of the stream. + The number of bytes may be less than the count + requested if data is not avialable. + + + + All buffered data is written to destination + + + + + Ends the TAR archive without closing the underlying OutputStream. + The result is that the EOF block of nulls is written. + + + + + Ends the TAR archive and closes the underlying OutputStream. + + This means that Finish() is called followed by calling the + TarBuffer's Close(). + + + + Get the record size being used by this stream's TarBuffer. + + + The TarBuffer record size. + + + + + Put an entry on the output stream. This writes the entry's + header and positions the output stream for writing + the contents of the entry. Once this method is called, the + stream is ready for calls to write() to write the entry's + contents. Once the contents are written, closeEntry() + MUST be called to ensure that all buffered data + is completely written to the output stream. + + + The TarEntry to be written to the archive. + + + + + Close an entry. This method MUST be called for all file + entries that contain data. The reason is that we must + buffer data written to the stream in order to satisfy + the buffer's block based writes. Thus, there may be + data fragments still being assembled that must be written + to the output stream before this entry is closed and the + next entry written. + + + + + Writes a byte to the current tar archive entry. + This method simply calls Write(byte[], int, int). + + + The byte to be written. + + + + + Writes bytes to the current tar archive entry. This method + is aware of the current entry and will throw an exception if + you attempt to write bytes past the length specified for the + current entry. The method is also (painfully) aware of the + record buffering required by TarBuffer, and manages buffers + that are not a multiple of recordsize in length, including + assembling records from small buffers. + + + The buffer to write to the archive. + + + The offset in the buffer from which to get bytes. + + + The number of bytes to write. + + + + + Write an EOF (end of archive) block to the tar archive. + An EOF block consists of all zeros. + + + + + bytes written for this entry so far + + + + + current 'Assembly' buffer length + + + + + Flag indicating wether this instance has been closed or not. + + + + + Size for the current entry + + + + + single block working buffer + + + + + 'Assembly' buffer used to assemble data before writing + + + + + TarBuffer used to provide correct blocking factor + + + + + the destination stream for the archive contents + + + + + true if the stream supports reading; otherwise, false. + + + + + true if the stream supports seeking; otherwise, false. + + + + + true if stream supports writing; otherwise, false. + + + + + length of stream in bytes + + + + + gets or sets the position within the current stream. + + + + + Get the record size being used by this stream's TarBuffer. + + + + + Get a value indicating wether an entry is open, requiring more data to be written. + + + + + This is the Deflater class. The deflater class compresses input + with the deflate algorithm described in RFC 1951. It has several + compression levels and three different strategies described below. + + This class is not thread safe. This is inherent in the API, due + to the split of deflate and setInput. + + author of the original java version : Jochen Hoenicke + + + + + The best and slowest compression level. This tries to find very + long and distant string repetitions. + + + + + The worst but fastest compression level. + + + + + The default compression level. + + + + + This level won't compress at all but output uncompressed blocks. + + + + + The compression method. This is the only method supported so far. + There is no need to use this constant at all. + + + + + Creates a new deflater with default compression level. + + + + + Creates a new deflater with given compression level. + + + the compression level, a value between NO_COMPRESSION + and BEST_COMPRESSION, or DEFAULT_COMPRESSION. + + if lvl is out of range. + + + + Creates a new deflater with given compression level. + + + the compression level, a value between NO_COMPRESSION + and BEST_COMPRESSION. + + + true, if we should suppress the Zlib/RFC1950 header at the + beginning and the adler checksum at the end of the output. This is + useful for the GZIP/PKZIP formats. + + if lvl is out of range. + + + + Resets the deflater. The deflater acts afterwards as if it was + just created with the same compression level and strategy as it + had before. + + + + + Flushes the current input block. Further calls to deflate() will + produce enough output to inflate everything in the current input + block. This is not part of Sun's JDK so I have made it package + private. It is used by DeflaterOutputStream to implement + flush(). + + + + + Finishes the deflater with the current input block. It is an error + to give more input after this method was called. This method must + be called to force all bytes to be flushed. + + + + + Sets the data which should be compressed next. This should be only + called when needsInput indicates that more input is needed. + If you call setInput when needsInput() returns false, the + previous input that is still pending will be thrown away. + The given byte array should not be changed, before needsInput() returns + true again. + This call is equivalent to setInput(input, 0, input.length). + + + the buffer containing the input data. + + + if the buffer was finished() or ended(). + + + + + Sets the data which should be compressed next. This should be + only called when needsInput indicates that more input is needed. + The given byte array should not be changed, before needsInput() returns + true again. + + + the buffer containing the input data. + + + the start of the data. + + + the number of data bytes of input. + + + if the buffer was Finish()ed or if previous input is still pending. + + + + + Sets the compression level. There is no guarantee of the exact + position of the change, but if you call this when needsInput is + true the change of compression level will occur somewhere near + before the end of the so far given input. + + + the new compression level. + + + + + Get current compression level + + Returns the current compression level + + + + Sets the compression strategy. Strategy is one of + DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact + position where the strategy is changed, the same as for + SetLevel() applies. + + + The new compression strategy. + + + + + Deflates the current input block with to the given array. + + + The buffer where compressed data is stored + + + The number of compressed bytes added to the output, or 0 if either + IsNeedingInput() or IsFinished returns true or length is zero. + + + + + Deflates the current input block to the given array. + + + Buffer to store the compressed data. + + + Offset into the output array. + + + The maximum number of bytes that may be stored. + + + The number of compressed bytes added to the output, or 0 if either + needsInput() or finished() returns true or length is zero. + + + If Finish() was previously called. + + + If offset or length don't match the array length. + + + + + Sets the dictionary which should be used in the deflate process. + This call is equivalent to setDictionary(dict, 0, dict.Length). + + + the dictionary. + + + if SetInput () or Deflate () were already called or another dictionary was already set. + + + + + Sets the dictionary which should be used in the deflate process. + The dictionary is a byte array containing strings that are + likely to occur in the data which should be compressed. The + dictionary is not stored in the compressed output, only a + checksum. To decompress the output you need to supply the same + dictionary again. + + + The dictionary data + + + The index where dictionary information commences. + + + The number of bytes in the dictionary. + + + If SetInput () or Deflate() were already called or another dictionary was already set. + + + + + Compression level. + + + + + If true no Zlib/RFC1950 headers or footers are generated + + + + + The current state. + + + + + The total bytes of output written. + + + + + The pending output. + + + + + The deflater engine. + + + + + Gets the current adler checksum of the data that was processed so far. + + + + + Gets the number of input bytes processed so far. + + + + + Gets the number of output bytes so far. + + + + + Returns true if the stream was finished and no more output bytes + are available. + + + + + Returns true, if the input buffer is empty. + You should then call setInput(). + NOTE: This method can also return true when the stream + was finished. + + + + + The TarInputStream reads a UNIX tar archive as an InputStream. + methods are provided to position at each successive entry in + the archive, and the read each entry as a normal input stream + using read(). + + + + + Construct a TarInputStream with default block factor + + stream to source data from + + + + Construct a TarInputStream with user specified block factor + + stream to source data from + block factor to apply to archive + + + + Flushes the baseInputStream + + + + + Set the streams position. This operation is not supported and will throw a NotSupportedException + + The offset relative to the origin to seek to. + The to start seeking from. + The new position in the stream. + Any access + + + + Sets the length of the stream + This operation is not supported and will throw a NotSupportedException + + The new stream length. + Any access + + + + Writes a block of bytes to this stream using data from a buffer. + This operation is not supported and will throw a NotSupportedException + + The buffer containing bytes to write. + The offset in the buffer of the frist byte to write. + The number of bytes to write. + Any access + + + + Writes a byte to the current position in the file stream. + This operation is not supported and will throw a NotSupportedException + + The byte value to write. + Any access + + + + Reads a byte from the current tar archive entry. + + A byte cast to an int; -1 if the at the end of the stream. + + + + Reads bytes from the current tar archive entry. + + This method is aware of the boundaries of the current + entry in the archive and will deal with them appropriately + + + The buffer into which to place bytes read. + + + The offset at which to place bytes read. + + + The number of bytes to read. + + + The number of bytes read, or 0 at end of stream/EOF. + + + + + Closes this stream. Calls the TarBuffer's close() method. + The underlying stream is closed by the TarBuffer. + + + + + Set the entry factory for this instance. + + The factory for creating new entries + + + + Get the record size being used by this stream's TarBuffer. + + + TarBuffer record size. + + + + + Skip bytes in the input buffer. This skips bytes in the + current entry's data, not the entire archive, and will + stop at the end of the current entry's data if the number + to skip extends beyond that point. + + + The number of bytes to skip. + + + + + Since we do not support marking just yet, we do nothing. + + + The limit to mark. + + + + + Since we do not support marking just yet, we do nothing. + + + + + Get the next entry in this tar archive. This will skip + over any remaining data in the current entry, if there + is one, and place the input stream at the header of the + next entry, and read the header and instantiate a new + TarEntry from the header bytes and return that entry. + If there are no more entries in the archive, null will + be returned to indicate that the end of the archive has + been reached. + + + The next TarEntry in the archive, or null. + + + + + Copies the contents of the current tar archive entry directly into + an output stream. + + + The OutputStream into which to write the entry's data. + + + + + Flag set when last block has been read + + + + + Size of this entry as recorded in header + + + + + Number of bytes read for this entry so far + + + + + Buffer used with calls to Read() + + + + + Working buffer + + + + + Current entry being read + + + + + Factory used to create TarEntry or descendant class instance + + + + + Stream used as the source of input data. + + + + + Gets a value indicating whether the current stream supports reading + + + + + Gets a value indicating whether the current stream supports seeking + This property always returns false. + + + + + Gets a value indicating if the stream supports writing. + This property always returns false. + + + + + The length in bytes of the stream + + + + + Gets or sets the position within the stream. + Setting the Position is not supported and throws a NotSupportedExceptionNotSupportedException + + Any attempt to set position + + + + Get the record size being used by this stream's TarBuffer. + + + + + Get the available data that can be read from the current + entry in the archive. This does not indicate how much data + is left in the entire archive, only in the current entry. + This value is determined from the entry's size header field + and the amount of data already read from the current entry. + + + The number of available bytes for the current entry. + + + + + Return a value of true if marking is supported; false otherwise. + + Currently marking is not supported, the return value is always false. + + + + This interface is provided, along with the method , to allow + the programmer to have their own subclass instantiated for the + entries return from . + + + + + Create an entry based on name alone + + + Name of the new EntryPointNotFoundException to create + + created TarEntry or descendant class + + + + Create an instance based on an actual file + + + Name of file to represent in the entry + + + Created TarEntry or descendant class + + + + + Create a tar entry based on the header information passed + + + Buffer containing header information to base entry on + + + Created TarEntry or descendant class + + + + + Standard entry factory class creating instances of the class TarEntry + + + + + Create a based on named + + The name to use for the entry + A new + + + + Create a tar entry with details obtained from file + + The name of the file to retrieve details from. + A new + + + + Create an entry based on details in header + + The buffer containing entry details. + A new + + + + Defines known values for the property. + + + + + Host system = MSDOS + + + + + Host system = Amiga + + + + + Host system = Open VMS + + + + + Host system = Unix + + + + + Host system = VMCms + + + + + Host system = Atari ST + + + + + Host system = OS2 + + + + + Host system = Macintosh + + + + + Host system = ZSystem + + + + + Host system = Cpm + + + + + Host system = Windows NT + + + + + Host system = MVS + + + + + Host system = VSE + + + + + Host system = Acorn RISC + + + + + Host system = VFAT + + + + + Host system = Alternate MVS + + + + + Host system = BEOS + + + + + Host system = Tandem + + + + + Host system = OS400 + + + + + Host system = OSX + + + + + Host system = WinZIP AES + + + + + This class represents an entry in a zip archive. This can be a file + or a directory + ZipFile and ZipInputStream will give you instances of this class as + information about the members in an archive. ZipOutputStream + uses an instance of this class when creating an entry in a Zip file. +
+
Author of the original java version : Jochen Hoenicke +
+
+ + + Creates a zip entry with the given name. + + + The name for this entry. Can include directory components. + The convention for names is 'unix' style paths with relative names only. + There are with no device names and path elements are separated by '/' characters. + + + The name passed is null + + + + + Creates a zip entry with the given name and version required to extract + + + The name for this entry. Can include directory components. + The convention for names is 'unix' style paths with no device names and + path elements separated by '/' characters. This is not enforced see CleanName + on how to ensure names are valid if this is desired. + + + The minimum 'feature version' required this entry + + + The name passed is null + + + + + Initializes an entry with the given name and made by information + + Name for this entry + Version and HostSystem Information + Minimum required zip feature version required to extract this entry + Compression method for this entry. + + The name passed is null + + + versionRequiredToExtract should be 0 (auto-calculate) or > 10 + + + This constructor is used by the ZipFile class when reading from the central header + It is not generally useful, use the constructor specifying the name only. + + + + + Creates a deep copy of the given zip entry. + + + The entry to copy. + + + + + Test the external attributes for this to + see if the external attributes are Dos based (including WINNT and variants) + and match the values + + The attributes to test. + Returns true if the external attributes are known to be DOS/Windows + based and have the same attributes set as the value passed. + + + + Force this entry to be recorded using Zip64 extensions. + + + + + Get a value indicating wether Zip64 extensions were forced. + + A value of true if Zip64 extensions have been forced on; false if not. + + + + Process extra data fields updating the entry based on the contents. + + True if the extra data fields should be handled + for a local header, rather than for a central header. + + + + + Test entry to see if data can be extracted. + + Returns true if data can be extracted for this entry; false otherwise. + + + + Creates a copy of this zip entry. + + An that is a copy of the current instance. + + + + Gets a string representation of this ZipEntry. + + A readable textual representation of this + + + + Test a compression method to see if this library + supports extracting data compressed with that method + + The compression method to test. + Returns true if the compression method is supported; false otherwise + + + + Cleans a name making it conform to Zip file conventions. + Devices names ('c:\') and UNC share names ('\\server\share') are removed + and forward slashes ('\') are converted to back slashes ('/'). + Names are made relative by trimming leading slashes which is compatible + with the ZIP naming convention. + + The name to clean + The 'cleaned' name. + + The Zip name transform class is more flexible. + + + + + Get a value indicating wether the entry has a CRC value available. + + + + + Get/Set flag indicating if entry is encrypted. + A simple helper routine to aid interpretation of flags + + This is an assistant that interprets the flags property. + + + + Get / set a flag indicating wether entry name and comment text are + encoded in unicode UTF8. + + This is an assistant that interprets the flags property. + + + + Value used during password checking for PKZIP 2.0 / 'classic' encryption. + + + + + Get/Set general purpose bit flag for entry + + + General purpose bit flag
+
+ Bit 0: If set, indicates the file is encrypted
+ Bit 1-2 Only used for compression type 6 Imploding, and 8, 9 deflating
+ Imploding:
+ Bit 1 if set indicates an 8K sliding dictionary was used. If clear a 4k dictionary was used
+ Bit 2 if set indicates 3 Shannon-Fanno trees were used to encode the sliding dictionary, 2 otherwise
+
+ Deflating:
+ Bit 2 Bit 1
+ 0 0 Normal compression was used
+ 0 1 Maximum compression was used
+ 1 0 Fast compression was used
+ 1 1 Super fast compression was used
+
+ Bit 3: If set, the fields crc-32, compressed size + and uncompressed size are were not able to be written during zip file creation + The correct values are held in a data descriptor immediately following the compressed data.
+ Bit 4: Reserved for use by PKZIP for enhanced deflating
+ Bit 5: If set indicates the file contains compressed patch data
+ Bit 6: If set indicates strong encryption was used.
+ Bit 7-10: Unused or reserved
+ Bit 11: If set the name and comments for this entry are in unicode.
+ Bit 12-15: Unused or reserved
+
+ + +
+ + + Get/Set index of this entry in Zip file + + This is only valid when the entry is part of a + + + + Get/set offset for use in central header + + + + + Get/Set external file attributes as an integer. + The values of this are operating system dependant see + HostSystem for details + + + + + Get the version made by for this entry or zero if unknown. + The value / 10 indicates the major version number, and + the value mod 10 is the minor version number + + + + + Get a value indicating this entry is for a DOS/Windows system. + + + + + Gets the compatability information for the external file attribute + If the external file attributes are compatible with MS-DOS and can be read + by PKZIP for DOS version 2.04g then this value will be zero. Otherwise the value + will be non-zero and identify the host system on which the attributes are compatible. + + + + The values for this as defined in the Zip File format and by others are shown below. The values are somewhat + misleading in some cases as they are not all used as shown. You should consult the relevant documentation + to obtain up to date and correct information. The modified appnote by the infozip group is + particularly helpful as it documents a lot of peculiarities. The document is however a little dated. + + 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) + 1 - Amiga + 2 - OpenVMS + 3 - Unix + 4 - VM/CMS + 5 - Atari ST + 6 - OS/2 HPFS + 7 - Macintosh + 8 - Z-System + 9 - CP/M + 10 - Windows NTFS + 11 - MVS (OS/390 - Z/OS) + 12 - VSE + 13 - Acorn Risc + 14 - VFAT + 15 - Alternate MVS + 16 - BeOS + 17 - Tandem + 18 - OS/400 + 19 - OS/X (Darwin) + 99 - WinZip AES + remainder - unused + + + + + + Get minimum Zip feature version required to extract this entry + + + Minimum features are defined as:
+ 1.0 - Default value
+ 1.1 - File is a volume label
+ 2.0 - File is a folder/directory
+ 2.0 - File is compressed using Deflate compression
+ 2.0 - File is encrypted using traditional encryption
+ 2.1 - File is compressed using Deflate64
+ 2.5 - File is compressed using PKWARE DCL Implode
+ 2.7 - File is a patch data set
+ 4.5 - File uses Zip64 format extensions
+ 4.6 - File is compressed using BZIP2 compression
+ 5.0 - File is encrypted using DES
+ 5.0 - File is encrypted using 3DES
+ 5.0 - File is encrypted using original RC2 encryption
+ 5.0 - File is encrypted using RC4 encryption
+ 5.1 - File is encrypted using AES encryption
+ 5.1 - File is encrypted using corrected RC2 encryption
+ 5.1 - File is encrypted using corrected RC2-64 encryption
+ 6.1 - File is encrypted using non-OAEP key wrapping
+ 6.2 - Central directory encryption (not confirmed yet)
+ 6.3 - File is compressed using LZMA
+ 6.3 - File is compressed using PPMD+
+ 6.3 - File is encrypted using Blowfish
+ 6.3 - File is encrypted using Twofish
+
+ +
+ + + Get a value indicating wether this entry can be decompressed by the library. + + This is based on the and + wether the compression method is supported. + + + + Gets a value indicating if the entry requires Zip64 extensions + to store the full entry values. + + A value of true if a local header requires Zip64 extensions; false if not. + + + + Get a value indicating wether the central directory entry requires Zip64 extensions to be stored. + + + + + Get/Set DosTime value. + + + The MS-DOS date format can only represent dates between 1/1/1980 and 12/31/2107. + + + + + Gets/Sets the time of last modification of the entry. + + + The property is updated to match this as far as possible. + + + + + Returns the entry name. + + + The unix naming convention is followed. + Path components in the entry should always separated by forward slashes ('/'). + Dos device names like C: should also be removed. + See the class, or + + + + + Gets/Sets the size of the uncompressed data. + + + The size or -1 if unknown. + + Setting the size before adding an entry to an archive can help + avoid compatability problems with some archivers which dont understand Zip64 extensions. + + + + Gets/Sets the size of the compressed data. + + + The compressed entry size or -1 if unknown. + + + + + Gets/Sets the crc of the uncompressed data. + + + Crc is not in the range 0..0xffffffffL + + + The crc value or -1 if unknown. + + + + + Gets/Sets the compression method. Only Deflated and Stored are supported. + + + The compression method for this entry + + + + + + + Gets/Sets the extra data. + + + Extra data is longer than 64KB (0xffff) bytes. + + + Extra data or null if not set. + + + + + Gets/Sets the entry comment. + + + If comment is longer than 0xffff. + + + The comment or null if not set. + + + A comment is only available for entries when read via the class. + The class doesnt have the comment data available. + + + + + Gets a value indicating if the entry is a directory. + however. + + + A directory is determined by an entry name with a trailing slash '/'. + The external file attributes can also indicate an entry is for a directory. + Currently only dos/windows attributes are tested in this manner. + The trailing slash convention should always be followed. + + + + + Get a value of true if the entry appears to be a file; false otherwise + + + This only takes account of DOS/Windows attributes. Other operating systems are ignored. + For linux and others the result may be incorrect. + + + + + ExtraData tagged value interface. + + + + + Set the contents of this instance from the data passed. + + The data to extract contents from. + The offset to begin extracting data from. + The number of bytes to extract. + + + + Get the data representing this instance. + + Returns the data for this instance. + + + + Get the ID for this tagged data value. + + + + + A raw binary tagged value + + + + + Initialise a new instance. + + The tag ID. + + + + Set the data from the raw values provided. + + The raw data to extract values from. + The index to start extracting values from. + The number of bytes available. + + + + Get the binary data representing this instance. + + The raw binary data representing this instance. + + + + The tag ID for this instance. + + + + + Get the ID for this tagged data value. + + + + + Get /set the binary data representing this instance. + + The raw binary data representing this instance. + + + + Class representing extended unix date time values. + + + + + Set the data from the raw values provided. + + The raw data to extract values from. + The index to start extracting values from. + The number of bytes available. + + + + Get the binary data representing this instance. + + The raw binary data representing this instance. + + + + Test a value to see if is valid and can be represented here. + + The value to test. + Returns true if the value is valid and can be represented; false if not. + The standard Unix time is a signed integer data type, directly encoding the Unix time number, + which is the number of seconds since 1970-01-01. + Being 32 bits means the values here cover a range of about 136 years. + The minimum representable time is 1901-12-13 20:45:52, + and the maximum representable time is 2038-01-19 03:14:07. + + + + + Get the ID + + + + + Get /set the Modification Time + + + + + + + Get / set the Access Time + + + + + + + Get / Set the Create Time + + + + + + + Get/set the values to include. + + + + + Flags indicate which values are included in this instance. + + + + + The modification time is included + + + + + The access time is included + + + + + The create time is included. + + + + + Class handling NT date time values. + + + + + Set the data from the raw values provided. + + The raw data to extract values from. + The index to start extracting values from. + The number of bytes available. + + + + Get the binary data representing this instance. + + The raw binary data representing this instance. + + + + Test a valuie to see if is valid and can be represented here. + + The value to test. + Returns true if the value is valid and can be represented; false if not. + + NTFS filetimes are 64-bit unsigned integers, stored in Intel + (least significant byte first) byte order. They determine the + number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", + which is "01-Jan-1601 00:00:00 UTC". 28 May 60056 is the upper limit + + + + + Get the ID for this tagged data value. + + + + + Get/set the last modification time. + + + + + Get /set the create time + + + + + Get /set the last access time. + + + + + A factory that creates tagged data instances. + + + + + Get data for a specific tag value. + + The tag ID to find. + The data to search. + The offset to begin extracting data from. + The number of bytes to extract. + The located value found, or null if not found. + + + + + A class to handle the extra data field for Zip entries + + + Extra data contains 0 or more values each prefixed by a header tag and length. + They contain zero or more bytes of actual data. + The data is held internally using a copy on write strategy. This is more efficient but + means that for extra data created by passing in data can have the values modified by the caller + in some circumstances. + + + + + Initialise a default instance. + + + + + Initialise with known extra data. + + The extra data. + + + + Get the raw extra data value + + Returns the raw byte[] extra data this instance represents. + + + + Clear the stored data. + + + + + Get a read-only for the associated tag. + + The tag to locate data for. + Returns a containing tag data or null if no tag was found. + + + + Get the tagged data for a tag. + + The tag to search for. + Returns a tagged value or null if none found. + + + + Find an extra data value + + The identifier for the value to find. + Returns true if the value was found; false otherwise. + + + + Add a new entry to extra data. + + The value to add. + + + + Add a new entry to extra data + + The ID for this entry. + The data to add. + If the ID already exists its contents are replaced. + + + + Start adding a new entry. + + Add data using , , , or . + The new entry is completed and actually added by calling + + + + + Add entry data added since using the ID passed. + + The identifier to use for this entry. + + + + Add a byte of data to the pending new entry. + + The byte to add. + + + + + Add data to a pending new entry. + + The data to add. + + + + + Add a short value in little endian order to the pending new entry. + + The data to add. + + + + + Add an integer value in little endian order to the pending new entry. + + The data to add. + + + + + Add a long value in little endian order to the pending new entry. + + The data to add. + + + + + Delete an extra data field. + + The identifier of the field to delete. + Returns true if the field was found and deleted. + + + + Read a long in little endian form from the last found data value + + Returns the long value read. + + + + Read an integer in little endian form from the last found data value. + + Returns the integer read. + + + + Read a short value in little endian form from the last found data value. + + Returns the short value read. + + + + Read a byte from an extra data + + The byte value read or -1 if the end of data has been reached. + + + + Skip data during reading. + + The number of bytes to skip. + + + + Internal form of that reads data at any location. + + Returns the short value read. + + + + Dispose of this instance. + + + + + Gets the current extra data length. + + + + + Get the length of the last value found by + + This is only value if has previsouly returned true. + + + + Get the index for the current read value. + + This is only valid if has previously returned true. + Initially it will be the index of the first byte of actual data. The value is updated after calls to + , and . + + + + Get the number of bytes remaining to be read for the current value; + + + + + Holds data pertinent to a data descriptor. + + + + + Get /set the compressed size of data. + + + + + Get / set the uncompressed size of data + + + + + Get /set the crc value. + + + + + This class assists with writing/reading from Zip files. + + + + + Initialise an instance of this class. + + The name of the file to open. + + + + Initialise a new instance of . + + The stream to use. + + + + Close the stream. + + + The underlying stream is closed only if is true. + + + + + Locates a block with the desired . + + The signature to find. + Location, marking the end of block. + Minimum size of the block. + The maximum variable data. + Eeturns the offset of the first byte after the signature; -1 if not found + + + + Write Zip64 end of central directory records (File header and locator). + + The number of entries in the central directory. + The size of entries in the central directory. + The offset of the dentral directory. + + + + Write the required records to end the central directory. + + The number of entries in the directory. + The size of the entries in the directory. + The start of the central directory. + The archive comment. (This can be null). + + + + Read an unsigned short in little endian byte order. + + Returns the value read. + + An i/o error occurs. + + + The file ends prematurely + + + + + Read an int in little endian byte order. + + Returns the value read. + + An i/o error occurs. + + + The file ends prematurely + + + + + Read a long in little endian byte order. + + The value read. + + + + Write an unsigned short in little endian byte order. + + The value to write. + + + + Write a ushort in little endian byte order. + + The value to write. + + + + Write an int in little endian byte order. + + The value to write. + + + + Write a uint in little endian byte order. + + The value to write. + + + + Write a long in little endian byte order. + + The value to write. + + + + Write a ulong in little endian byte order. + + The value to write. + + + + Write a data descriptor. + + The entry to write a descriptor for. + Returns the number of descriptor bytes written. + + + + Read data descriptor at the end of compressed data. + + if set to true [zip64]. + The data to fill in. + Returns the number of bytes read in the descriptor. + + + + Get / set a value indicating wether the the underlying stream is owned or not. + + If the stream is owned it is closed when this instance is closed. + + + + Inflater is used to decompress data that has been compressed according + to the "deflate" standard described in rfc1951. + + By default Zlib (rfc1950) headers and footers are expected in the input. + You can use constructor public Inflater(bool noHeader) passing true + if there is no Zlib header information + + The usage is as following. First you have to set some input with + SetInput(), then Inflate() it. If inflate doesn't + inflate any bytes there may be three reasons: +
    +
  • IsNeedingInput() returns true because the input buffer is empty. + You have to provide more input with SetInput(). + NOTE: IsNeedingInput() also returns true when, the stream is finished. +
  • +
  • IsNeedingDictionary() returns true, you have to provide a preset + dictionary with SetDictionary().
  • +
  • IsFinished returns true, the inflater has finished.
  • +
+ Once the first output byte is produced, a dictionary will not be + needed at a later stage. + + author of the original java version : John Leuner, Jochen Hoenicke +
+
+ + + These are the possible states for an inflater + + + + + Copy lengths for literal codes 257..285 + + + + + Extra bits for literal codes 257..285 + + + + + Copy offsets for distance codes 0..29 + + + + + Extra bits for distance codes + + + + + This variable contains the current state. + + + + + The adler checksum of the dictionary or of the decompressed + stream, as it is written in the header resp. footer of the + compressed stream. + Only valid if mode is DECODE_DICT or DECODE_CHKSUM. + + + + + The number of bits needed to complete the current state. This + is valid, if mode is DECODE_DICT, DECODE_CHKSUM, + DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. + + + + + True, if the last block flag was set in the last block of the + inflated stream. This means that the stream ends after the + current block. + + + + + The total number of inflated bytes. + + + + + The total number of bytes set with setInput(). This is not the + value returned by the TotalIn property, since this also includes the + unprocessed input. + + + + + This variable stores the noHeader flag that was given to the constructor. + True means, that the inflated stream doesn't contain a Zlib header or + footer. + + + + + Creates a new inflater or RFC1951 decompressor + RFC1950/Zlib headers and footers will be expected in the input data + + + + + Creates a new inflater. + + + True if no RFC1950/Zlib header and footer fields are expected in the input data + + This is used for GZIPed/Zipped input. + + For compatibility with + Sun JDK you should provide one byte of input more than needed in + this case. + + + + + Resets the inflater so that a new stream can be decompressed. All + pending input and output will be discarded. + + + + + Decodes a zlib/RFC1950 header. + + + False if more input is needed. + + + The header is invalid. + + + + + Decodes the dictionary checksum after the deflate header. + + + False if more input is needed. + + + + + Decodes the huffman encoded symbols in the input stream. + + + false if more input is needed, true if output window is + full or the current block ends. + + + if deflated stream is invalid. + + + + + Decodes the adler checksum after the deflate stream. + + + false if more input is needed. + + + If checksum doesn't match. + + + + + Decodes the deflated stream. + + + false if more input is needed, or if finished. + + + if deflated stream is invalid. + + + + + Sets the preset dictionary. This should only be called, if + needsDictionary() returns true and it should set the same + dictionary, that was used for deflating. The getAdler() + function returns the checksum of the dictionary needed. + + + The dictionary. + + + + + Sets the preset dictionary. This should only be called, if + needsDictionary() returns true and it should set the same + dictionary, that was used for deflating. The getAdler() + function returns the checksum of the dictionary needed. + + + The dictionary. + + + The index into buffer where the dictionary starts. + + + The number of bytes in the dictionary. + + + No dictionary is needed. + + + The adler checksum for the buffer is invalid + + + + + Sets the input. This should only be called, if needsInput() + returns true. + + + the input. + + + + + Sets the input. This should only be called, if needsInput() + returns true. + + + The source of input data + + + The index into buffer where the input starts. + + + The number of bytes of input to use. + + + No input is needed. + + + The index and/or count are wrong. + + + + + Inflates the compressed stream to the output buffer. If this + returns 0, you should check, whether IsNeedingDictionary(), + IsNeedingInput() or IsFinished() returns true, to determine why no + further output is produced. + + + the output buffer. + + + The number of bytes written to the buffer, 0 if no further + output can be produced. + + + if buffer has length 0. + + + if deflated stream is invalid. + + + + + Inflates the compressed stream to the output buffer. If this + returns 0, you should check, whether needsDictionary(), + needsInput() or finished() returns true, to determine why no + further output is produced. + + + the output buffer. + + + the offset in buffer where storing starts. + + + the maximum number of bytes to output. + + + the number of bytes written to the buffer, 0 if no further output can be produced. + + + if count is less than 0. + + + if the index and / or count are wrong. + + + if deflated stream is invalid. + + + + + Returns true, if the input buffer is empty. + You should then call setInput(). + NOTE: This method also returns true when the stream is finished. + + + + + Returns true, if a preset dictionary is needed to inflate the input. + + + + + Returns true, if the inflater has finished. This means, that no + input is needed and no output can be produced. + + + + + Gets the adler checksum. This is either the checksum of all + uncompressed bytes returned by inflate(), or if needsDictionary() + returns true (and thus no output was yet produced) this is the + adler checksum of the expected dictionary. + + + the adler checksum. + + + + + Gets the total number of output bytes returned by Inflate(). + + + the total number of output bytes. + + + + + Gets the total number of processed compressed input bytes. + + + The total number of bytes of processed input bytes. + + + + + Gets the number of unprocessed input bytes. Useful, if the end of the + stream is reached and you want to further process the bytes after + the deflate stream. + + + The number of bytes of the input which have not been processed. + + + + + An input stream that decompresses files in the BZip2 format + + + + + Construct instance for reading from stream + + Data source + + + + Flushes the stream. + + + + + Set the streams position. This operation is not supported and will throw a NotSupportedException + + A byte offset relative to the parameter. + A value of type indicating the reference point used to obtain the new position. + The new position of the stream. + Any access + + + + Sets the length of this stream to the given value. + This operation is not supported and will throw a NotSupportedExceptionortedException + + The new length for the stream. + Any access + + + + Writes a block of bytes to this stream using data from a buffer. + This operation is not supported and will throw a NotSupportedException + + The buffer to source data from. + The offset to start obtaining data from. + The number of bytes of data to write. + Any access + + + + Writes a byte to the current position in the file stream. + This operation is not supported and will throw a NotSupportedException + + The value to write. + Any access + + + + Read a sequence of bytes and advances the read position by one byte. + + Array of bytes to store values in + Offset in array to begin storing data + The maximum number of bytes to read + The total number of bytes read into the buffer. This might be less + than the number of bytes requested if that number of bytes are not + currently available or zero if the end of the stream is reached. + + + + + Closes the stream, releasing any associated resources. + + + + + Read a byte from stream advancing position + + byte read or -1 on end of stream + + + + Get/set flag indicating ownership of underlying stream. + When the flag is true will close the underlying stream also. + + + + + Gets a value indicating if the stream supports reading + + + + + Gets a value indicating whether the current stream supports seeking. + + + + + Gets a value indicating whether the current stream supports writing. + This property always returns false + + + + + Gets the length in bytes of the stream. + + + + + Gets or sets the streams position. + Setting the position is not supported and will throw a NotSupportException + + Any attempt to set the position + + + + Computes Adler32 checksum for a stream of data. An Adler32 + checksum is not as reliable as a CRC32 checksum, but a lot faster to + compute. + + The specification for Adler32 may be found in RFC 1950. + ZLIB Compressed Data Format Specification version 3.3) + + + From that document: + + "ADLER32 (Adler-32 checksum) + This contains a checksum value of the uncompressed data + (excluding any dictionary data) computed according to Adler-32 + algorithm. This algorithm is a 32-bit extension and improvement + of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 + standard. + + Adler-32 is composed of two sums accumulated per byte: s1 is + the sum of all bytes, s2 is the sum of all s1 values. Both sums + are done modulo 65521. s1 is initialized to 1, s2 to zero. The + Adler-32 checksum is stored as s2*65536 + s1 in most- + significant-byte first (network) order." + + "8.2. The Adler-32 algorithm + + The Adler-32 algorithm is much faster than the CRC32 algorithm yet + still provides an extremely low probability of undetected errors. + + The modulo on unsigned long accumulators can be delayed for 5552 + bytes, so the modulo operation time is negligible. If the bytes + are a, b, c, the second sum is 3a + 2b + c + 3, and so is position + and order sensitive, unlike the first sum, which is just a + checksum. That 65521 is prime is important to avoid a possible + large class of two-byte errors that leave the check unchanged. + (The Fletcher checksum uses 255, which is not prime and which also + makes the Fletcher check insensitive to single byte changes 0 - + 255.) + + The sum s1 is initialized to 1 instead of zero to make the length + of the sequence part of s2, so that the length does not have to be + checked separately. (Any sequence of zeroes has a Fletcher + checksum of zero.)" + + + + + + + largest prime smaller than 65536 + + + + + Creates a new instance of the Adler32 class. + The checksum starts off with a value of 1. + + + + + Resets the Adler32 checksum to the initial value. + + + + + Updates the checksum with a byte value. + + + The data value to add. The high byte of the int is ignored. + + + + + Updates the checksum with an array of bytes. + + + The source of the data to update with. + + + + + Updates the checksum with the bytes taken from the array. + + + an array of bytes + + + the start of the data used for this update + + + the number of bytes to use for this update + + + + + Returns the Adler32 data checksum computed so far. + + +
+
diff --git a/bin/Org.Mentalis.Security.dll b/bin/Org.Mentalis.Security.dll new file mode 100644 index 0000000..bac39dd Binary files /dev/null and b/bin/Org.Mentalis.Security.dll differ diff --git a/bin/Tamir.SharpSSH.dll b/bin/Tamir.SharpSSH.dll new file mode 100644 index 0000000..c2f67a8 Binary files /dev/null and b/bin/Tamir.SharpSSH.dll differ diff --git a/bin/Winterdom.IO.FileMap.dll b/bin/Winterdom.IO.FileMap.dll new file mode 100644 index 0000000..f3965d6 Binary files /dev/null and b/bin/Winterdom.IO.FileMap.dll differ diff --git a/bin/Winterdom.IO.FileMap.pdb b/bin/Winterdom.IO.FileMap.pdb new file mode 100644 index 0000000..8368cfc Binary files /dev/null and b/bin/Winterdom.IO.FileMap.pdb differ -- cgit v1.1 From e0d533dc4ea95f88ed647fa9243325499e122e45 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Fri, 25 Jun 2010 12:55:02 -0700 Subject: Add [Git] section to OpenSim.ini.example for Gitminster --- bin/OpenSim.ini.example | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index c21dc98..d08cf1d 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -883,6 +883,9 @@ PriceObjectScaleFactor = 10 PriceParcelRent = 1 +[Git] +Enabled = 1 +RepoPath = "/git" [SVN] Enabled = false -- cgit v1.1 From 3ef70b55e9e8a69afc6dc27e01a294193e03e6d6 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Fri, 25 Jun 2010 12:58:13 -0700 Subject: Whoops, enabled = true not enabled = 1 --- bin/OpenSim.ini.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index d08cf1d..180c100 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -884,7 +884,7 @@ PriceParcelRent = 1 [Git] -Enabled = 1 +Enabled = true RepoPath = "/git" [SVN] -- cgit v1.1 From 8daa149c367d6d3f51d41663d6e518af3354addd Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Fri, 25 Jun 2010 13:03:00 -0700 Subject: Remove the prepending slash from the default git repo name --- bin/OpenSim.ini.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 180c100..6fdfcf2 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -885,7 +885,7 @@ [Git] Enabled = true -RepoPath = "/git" +RepoPath = "git" [SVN] Enabled = false -- cgit v1.1 From 96e649189f24b6261d0bcdd6aa7f5a078b8d3f7f Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Fri, 25 Jun 2010 14:25:39 -0700 Subject: Add two events: OnAttachToBackup and OnDetachFromBackup. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 26 ++++++++++++++++++++++ .../Region/Framework/Scenes/SceneObjectGroup.cs | 4 ++++ 2 files changed, 30 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 80f9114..904e38a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -43,6 +43,10 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); + public delegate void AttachToBackupDelegate(SceneObjectGroup sog); + + public delegate void DetachFromBackupDelegate(SceneObjectGroup sog); + public delegate void ObjectCreateDelegate(EntityBase obj); public delegate void ObjectDeleteDelegate(EntityBase obj); @@ -61,6 +65,8 @@ namespace OpenSim.Region.Framework.Scenes private PhysicsCrash handlerPhysicsCrash = null; public event ObjectDuplicateDelegate OnObjectDuplicate; + public event AttachToBackupDelegate OnAttachToBackup; + public event DetachFromBackupDelegate OnDetachFromBackup; public event ObjectCreateDelegate OnObjectCreate; public event ObjectDeleteDelegate OnObjectRemove; @@ -388,10 +394,14 @@ namespace OpenSim.Region.Framework.Scenes m_numPrim += sceneObject.Children.Count; if (attachToBackup) + { sceneObject.AttachToBackup(); + } if (OnObjectCreate != null) + { OnObjectCreate(sceneObject); + } lock (m_dictionary_lock) { @@ -458,6 +468,22 @@ namespace OpenSim.Region.Framework.Scenes } } + public void FireAttachToBackup(SceneObjectGroup obj) + { + if (OnAttachToBackup != null) + { + OnAttachToBackup(obj); + } + } + + public void FireDetachFromBackup(SceneObjectGroup obj) + { + if (OnDetachFromBackup != null) + { + OnDetachFromBackup(obj); + } + } + /// /// Process all pending updates /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 3e92954..e18dfd2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -658,6 +658,8 @@ namespace OpenSim.Region.Framework.Scenes ///
public virtual void AttachToBackup() { + m_scene.SceneGraph.FireAttachToBackup(this); + if (InSceneBackup) { //m_log.DebugFormat( @@ -2703,6 +2705,8 @@ namespace OpenSim.Region.Framework.Scenes /// public virtual void DetachFromBackup() { + m_scene.SceneGraph.FireDetachFromBackup(this); + if (m_isBackedUp) m_scene.EventManager.OnBackup -= ProcessBackup; -- cgit v1.1 From f64d1cb3967b5352921b296348f618a62fdfa622 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Fri, 25 Jun 2010 14:39:15 -0700 Subject: Add new event: OnChangedBackup --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 11 +++++++++++ OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index ce7b0eb..81ef54f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -47,6 +47,8 @@ namespace OpenSim.Region.Framework.Scenes public delegate void DetachFromBackupDelegate(SceneObjectGroup sog); + public delegate void ChangedBackupDelegate(SceneObjectGroup sog); + public delegate void ObjectCreateDelegate(EntityBase obj); public delegate void ObjectDeleteDelegate(EntityBase obj); @@ -67,6 +69,7 @@ namespace OpenSim.Region.Framework.Scenes public event ObjectDuplicateDelegate OnObjectDuplicate; public event AttachToBackupDelegate OnAttachToBackup; public event DetachFromBackupDelegate OnDetachFromBackup; + public event ChangedBackupDelegate OnChangeBackup; public event ObjectCreateDelegate OnObjectCreate; public event ObjectDeleteDelegate OnObjectRemove; @@ -484,6 +487,14 @@ namespace OpenSim.Region.Framework.Scenes } } + public void FireChangeBackup(SceneObjectGroup obj) + { + if (OnChangeBackup != null) + { + OnChangeBackup(obj); + } + } + /// /// Process all pending updates /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index e18dfd2..7081ced 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -200,6 +200,10 @@ namespace OpenSim.Region.Framework.Scenes { if (value) { + if (m_isBackedUp) + { + m_scene.SceneGraph.FireChangeBackup(this); + } timeLastChanged = DateTime.Now.Ticks; if (!m_hasGroupChanged) timeFirstChanged = DateTime.Now.Ticks; -- cgit v1.1 From 6274317e63e18785a2c3d96514ca371e0a04cf71 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 26 Jun 2010 06:16:24 +0200 Subject: Fix loading of attachments on login --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 654e9ce..4a4cac9 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -4151,7 +4151,14 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); { m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service"); stateData = attServ.Get(ControllingClient.AgentId.ToString()); - doc.LoadXml(stateData); + if (stateData != String.Empty) + { + try + { + doc.LoadXml(stateData); + } + catch { } + } } Dictionary itemData = new Dictionary(); -- cgit v1.1 From d3d63fe553e335adc6d3a0dbd7907ea6733cb428 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 26 Jun 2010 06:21:38 +0200 Subject: remove conflicting pdb debug files --- bin/GitSharp.Core.pdb | Bin 1906176 -> 0 bytes bin/GitSharp.pdb | Bin 347648 -> 0 bytes bin/Winterdom.IO.FileMap.pdb | Bin 24064 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 bin/GitSharp.Core.pdb delete mode 100644 bin/GitSharp.pdb delete mode 100644 bin/Winterdom.IO.FileMap.pdb diff --git a/bin/GitSharp.Core.pdb b/bin/GitSharp.Core.pdb deleted file mode 100644 index 32ad5bb..0000000 Binary files a/bin/GitSharp.Core.pdb and /dev/null differ diff --git a/bin/GitSharp.pdb b/bin/GitSharp.pdb deleted file mode 100644 index 4c65b1f..0000000 Binary files a/bin/GitSharp.pdb and /dev/null differ diff --git a/bin/Winterdom.IO.FileMap.pdb b/bin/Winterdom.IO.FileMap.pdb deleted file mode 100644 index 8368cfc..0000000 Binary files a/bin/Winterdom.IO.FileMap.pdb and /dev/null differ -- cgit v1.1 From 6c6c7b09273a465993b7893b235f8ebfd5b0dcf5 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 26 Jun 2010 06:25:03 +0200 Subject: Remove libs from main tree --- bin/DiffieHellman.dll | Bin 53248 -> 0 bytes bin/GitSharp.Core.dll | Bin 558080 -> 0 bytes bin/GitSharp.dll | Bin 219648 -> 0 bytes bin/ICSharpCode.SharpZipLib.dll | Bin 188416 -> 0 bytes bin/ICSharpCode.SharpZipLib.xml | 9055 --------------------------------------- bin/Org.Mentalis.Security.dll | Bin 184320 -> 0 bytes bin/Tamir.SharpSSH.dll | Bin 212992 -> 0 bytes bin/Winterdom.IO.FileMap.dll | Bin 9728 -> 0 bytes 8 files changed, 9055 deletions(-) delete mode 100644 bin/DiffieHellman.dll delete mode 100644 bin/GitSharp.Core.dll delete mode 100644 bin/GitSharp.dll delete mode 100644 bin/ICSharpCode.SharpZipLib.dll delete mode 100644 bin/ICSharpCode.SharpZipLib.xml delete mode 100644 bin/Org.Mentalis.Security.dll delete mode 100644 bin/Tamir.SharpSSH.dll delete mode 100644 bin/Winterdom.IO.FileMap.dll diff --git a/bin/DiffieHellman.dll b/bin/DiffieHellman.dll deleted file mode 100644 index aa31051..0000000 Binary files a/bin/DiffieHellman.dll and /dev/null differ diff --git a/bin/GitSharp.Core.dll b/bin/GitSharp.Core.dll deleted file mode 100644 index 5aad773..0000000 Binary files a/bin/GitSharp.Core.dll and /dev/null differ diff --git a/bin/GitSharp.dll b/bin/GitSharp.dll deleted file mode 100644 index 99a91a7..0000000 Binary files a/bin/GitSharp.dll and /dev/null differ diff --git a/bin/ICSharpCode.SharpZipLib.dll b/bin/ICSharpCode.SharpZipLib.dll deleted file mode 100644 index e565e3a..0000000 Binary files a/bin/ICSharpCode.SharpZipLib.dll and /dev/null differ diff --git a/bin/ICSharpCode.SharpZipLib.xml b/bin/ICSharpCode.SharpZipLib.xml deleted file mode 100644 index 98cb51e..0000000 --- a/bin/ICSharpCode.SharpZipLib.xml +++ /dev/null @@ -1,9055 +0,0 @@ - - - - ICSharpCode.SharpZipLib - - - - - FastZipEvents supports all events applicable to FastZip operations. - - - - - Delegate to invoke when processing directories. - - - - - Delegate to invoke when processing files. - - - - - Delegate to invoke during processing of files. - - - - - Delegate to invoke when processing for a file has been completed. - - - - - Delegate to invoke when processing directory failures. - - - - - Delegate to invoke when processing file failures. - - - - - Raise the directory failure event. - - The directory causing the failure. - The exception for this event. - A boolean indicating if execution should continue or not. - - - - Raises the file failure delegate. - - The file causing the failure. - The exception for this failure. - A boolean indicating if execution should continue or not. - - - - Fires the Process File delegate. - - The file being processed. - A boolean indicating if execution should continue or not. - - - - Fires the CompletedFile delegate - - The file whose processing has been completed. - A boolean indicating if execution should continue or not. - - - - Fires the process directory delegate. - - The directory being processed. - Flag indicating if the directory has matching files as determined by the current filter. - A of true if the operation should continue; false otherwise. - - - - The minimum timespan between events. - - The minimum period of time between events. - - - - - FastZip provides facilities for creating and extracting zip files. - - - - - Initialise a default instance of . - - - - - Initialise a new instance of - - The events to use during operations. - - - - Create a zip file. - - The name of the zip file to create. - The directory to source files from. - True to recurse directories, false for no recursion. - The file filter to apply. - The directory filter to apply. - - - - Create a zip file/archive. - - The name of the zip file to create. - The directory to obtain files and directories from. - True to recurse directories, false for no recursion. - The file filter to apply. - - - - Create a zip archive sending output to the passed. - - The stream to write archive data to. - The directory to source files from. - True to recurse directories, false for no recursion. - The file filter to apply. - The directory filter to apply. - - - - Extract the contents of a zip file. - - The zip file to extract from. - The directory to save extracted information in. - A filter to apply to files. - - - - Extract the contents of a zip file. - - The zip file to extract from. - The directory to save extracted information in. - The style of overwriting to apply. - A delegate to invoke when confirming overwriting. - A filter to apply to files. - A filter to apply to directories. - Flag indicating wether to restore the date and time for extracted files. - - - - Get/set a value indicating wether empty directories should be created. - - - - - Get / set the password value. - - - - - Get or set the active when creating Zip files. - - - - - - Get or set the active when creating Zip files. - - - - - Get/set a value indicating wether file dates and times should - be restored when extracting files from an archive. - - The default value is false. - - - - Get/set a value indicating wether file attributes should - be restored during extract operations - - - - - Defines the desired handling when overwriting files during extraction. - - - - - Prompt the user to confirm overwriting - - - - - Never overwrite files. - - - - - Always overwrite files. - - - - - Delegate called when confirming overwriting of files. - - - - - NameFilter is a string matching class which allows for both positive and negative - matching. - A filter is a sequence of independant regular expressions separated by semi-colons ';' - Each expression can be prefixed by a plus '+' sign or a minus '-' sign to denote the expression - is intended to include or exclude names. If neither a plus or minus sign is found include is the default - A given name is tested for inclusion before checking exclusions. Only names matching an include spec - and not matching an exclude spec are deemed to match the filter. - An empty filter matches any name. - - The following expression includes all name ending in '.dat' with the exception of 'dummy.dat' - "+\.dat$;-^dummy\.dat$" - - - - - Scanning filters support filtering of names. - - - - - Test a name to see if it 'matches' the filter. - - The name to test. - Returns true if the name matches the filter, false if it does not match. - - - - Construct an instance based on the filter expression passed - - The filter expression. - - - - Test a string to see if it is a valid regular expression. - - The expression to test. - True if expression is a valid false otherwise. - - - - Test an expression to see if it is valid as a filter. - - The filter expression to test. - True if the expression is valid, false otherwise. - - - - Convert this filter to its string equivalent. - - The string equivalent for this filter. - - - - Test a value to see if it is included by the filter. - - The value to test. - True if the value is included, false otherwise. - - - - Test a value to see if it is excluded by the filter. - - The value to test. - True if the value is excluded, false otherwise. - - - - Test a value to see if it matches the filter. - - The value to test. - True if the value matches, false otherwise. - - - - Compile this filter. - - - - - Huffman tree used for inflation - - - - - Literal length tree - - - - - Distance tree - - - - - Constructs a Huffman tree from the array of code lengths. - - - the array of code lengths - - - - - Reads the next symbol from input. The symbol is encoded using the - huffman tree. - - - input the input source. - - - the next symbol, or -1 if not enough input is available. - - - - - This class is general purpose class for writing data to a buffer. - - It allows you to write bits as well as bytes - Based on DeflaterPending.java - - author of the original java version : Jochen Hoenicke - - - - - Internal work buffer - - - - - construct instance using default buffer size of 4096 - - - - - construct instance using specified buffer size - - - size to use for internal buffer - - - - - Clear internal state/buffers - - - - - Write a byte to buffer - - - The value to write - - - - - Write a short value to buffer LSB first - - - The value to write. - - - - - write an integer LSB first - - The value to write. - - - - Write a block of data to buffer - - data to write - offset of first byte to write - number of bytes to write - - - - Align internal buffer on a byte boundary - - - - - Write bits to internal buffer - - source of bits - number of bits to write - - - - Write a short value to internal buffer most significant byte first - - value to write - - - - Flushes the pending buffer into the given output array. If the - output array is to small, only a partial flush is done. - - The output array. - The offset into output array. - The maximum number of bytes to store. - The number of bytes flushed. - - - - Convert internal buffer to byte array. - Buffer is empty on completion - - - The internal buffer contents converted to a byte array. - - - - - The number of bits written to the buffer - - - - - Indicates if buffer has been flushed - - - - - Used to advise clients of 'events' while processing archives - - - - - The TarArchive class implements the concept of a - 'Tape Archive'. A tar archive is a series of entries, each of - which represents a file system object. Each entry in - the archive consists of a header block followed by 0 or more data blocks. - Directory entries consist only of the header block, and are followed by entries - for the directory's contents. File entries consist of a - header followed by the number of blocks needed to - contain the file's contents. All entries are written on - block boundaries. Blocks are 512 bytes long. - - TarArchives are instantiated in either read or write mode, - based upon whether they are instantiated with an InputStream - or an OutputStream. Once instantiated TarArchives read/write - mode can not be changed. - - There is currently no support for random access to tar archives. - However, it seems that subclassing TarArchive, and using the - TarBuffer.CurrentRecord and TarBuffer.CurrentBlock - properties, this would be rather trivial. - - - - - Raises the ProgressMessage event - - The TarEntry for this event - message for this event. Null is no message - - - - Constructor for a default . - - - - - Initalise a TarArchive for input. - - The to use for input. - - - - Initialise a TarArchive for output. - - The to use for output. - - - - The InputStream based constructors create a TarArchive for the - purposes of extracting or listing a tar archive. Thus, use - these constructors when you wish to extract files from or list - the contents of an existing tar archive. - - The stream to retrieve archive data from. - Returns a new suitable for reading from. - - - - Create TarArchive for reading setting block factor - - Stream for tar archive contents - The blocking factor to apply - Returns a suitable for reading. - - - - Create a TarArchive for writing to, using the default blocking factor - - The to write to - Returns a suitable for writing. - - - - Create a TarArchive for writing to - - The stream to write to - The blocking factor to use for buffering. - Returns a suitable for writing. - - - - Set the flag that determines whether existing files are - kept, or overwritten during extraction. - - - If true, do not overwrite existing files. - - - - - Set the ascii file translation flag. - - - If true, translate ascii text files. - - - - - Set user and group information that will be used to fill in the - tar archive's entry headers. This information based on that available - for the linux operating system, which is not always available on other - operating systems. TarArchive allows the programmer to specify values - to be used in their place. - is set to true by this call. - - - The user id to use in the headers. - - - The user name to use in the headers. - - - The group id to use in the headers. - - - The group name to use in the headers. - - - - - Close the archive. - - - - - Perform the "list" command for the archive contents. - - NOTE That this method uses the progress event to actually list - the contents. If the progress display event is not set, nothing will be listed! - - - - - Perform the "extract" command and extract the contents of the archive. - - - The destination directory into which to extract. - - - - - Extract an entry from the archive. This method assumes that the - tarIn stream has been properly set with a call to GetNextEntry(). - - - The destination directory into which to extract. - - - The TarEntry returned by tarIn.GetNextEntry(). - - - - - Write an entry to the archive. This method will call the putNextEntry - and then write the contents of the entry, and finally call closeEntry() - for entries that are files. For directories, it will call putNextEntry(), - and then, if the recurse flag is true, process each entry that is a - child of the directory. - - - The TarEntry representing the entry to write to the archive. - - - If true, process the children of directory entries. - - - - - Write an entry to the archive. This method will call the putNextEntry - and then write the contents of the entry, and finally call closeEntry() - for entries that are files. For directories, it will call putNextEntry(), - and then, if the recurse flag is true, process each entry that is a - child of the directory. - - - The TarEntry representing the entry to write to the archive. - - - If true, process the children of directory entries. - - - - - Releases the unmanaged resources used by the FileStream and optionally releases the managed resources. - - true to release both managed and unmanaged resources; - false to release only unmanaged resources. - - - - Closes the archive and releases any associated resources. - - - - - Ensures that resources are freed and other cleanup operations are performed - when the garbage collector reclaims the . - - - - - Client hook allowing detailed information to be reported during processing - - - - - Get/set the ascii file translation flag. If ascii file translation - is true, then the file is checked to see if it a binary file or not. - If the flag is true and the test indicates it is ascii text - file, it will be translated. The translation converts the local - operating system's concept of line ends into the UNIX line end, - '\n', which is the defacto standard for a TAR archive. This makes - text files compatible with UNIX. - - - - - PathPrefix is added to entry names as they are written if the value is not null. - A slash character is appended after PathPrefix - - - - - RootPath is removed from entry names if it is found at the - beginning of the name. - - - - - Get or set a value indicating if overrides defined by SetUserInfo should be applied. - - If overrides are not applied then the values as set in each header will be used. - - - - Get the archive user id. - See ApplyUserInfoOverrides for detail - on how to allow setting values on a per entry basis. - - - The current user id. - - - - - Get the archive user name. - See ApplyUserInfoOverrides for detail - on how to allow setting values on a per entry basis. - - - The current user name. - - - - - Get the archive group id. - See ApplyUserInfoOverrides for detail - on how to allow setting values on a per entry basis. - - - The current group id. - - - - - Get the archive group name. - See ApplyUserInfoOverrides for detail - on how to allow setting values on a per entry basis. - - - The current group name. - - - - - Get the archive's record size. Tar archives are composed of - a series of RECORDS each containing a number of BLOCKS. - This allowed tar archives to match the IO characteristics of - the physical device being used. Archives are expected - to be properly "blocked". - - - The record size this archive is using. - - - - - An output stream that compresses into the BZip2 format - including file header chars into another stream. - - - - - Construct a default output stream with maximum block size - - The stream to write BZip data onto. - - - - Initialise a new instance of the - for the specified stream, using the given blocksize. - - The stream to write compressed data to. - The block size to use. - - Valid block sizes are in the range 1..9, with 1 giving - the lowest compression and 9 the highest. - - - - - Ensures that resources are freed and other cleanup operations - are performed when the garbage collector reclaims the BZip2OutputStream. - - - - - Sets the current position of this stream to the given value. - - The point relative to the offset from which to being seeking. - The reference point from which to begin seeking. - The new position in the stream. - - - - Sets the length of this stream to the given value. - - The new stream length. - - - - Read a byte from the stream advancing the position. - - The byte read cast to an int; -1 if end of stream. - - - - Read a block of bytes - - The buffer to read into. - The offset in the buffer to start storing data at. - The maximum number of bytes to read. - The total number of bytes read. This might be less than the number of bytes - requested if that number of bytes are not currently available, or zero - if the end of the stream is reached. - - - - Write a block of bytes to the stream - - The buffer containing data to write. - The offset of the first byte to write. - The number of bytes to write. - - - - Write a byte to the stream. - - The byte to write to the stream. - - - - End the current block and end compression. - Close the stream and free any resources - - - - - Get the number of bytes written to output. - - - - - Releases the unmanaged resources used by the and optionally releases the managed resources. - - true to release both managed and unmanaged resources; false to release only unmanaged resources. - - - - Flush output buffers - - - - - Get/set flag indicating ownership of underlying stream. - When the flag is true will close the underlying stream also. - - - - - Gets a value indicating whether the current stream supports reading - - - - - Gets a value indicating whether the current stream supports seeking - - - - - Gets a value indicating whether the current stream supports writing - - - - - Gets the length in bytes of the stream - - - - - Gets or sets the current position of this stream. - - - - - Get the number of bytes written to the output. - - - - - Represents exception conditions specific to Zip archive handling - - - - - SharpZipBaseException is the base exception class for the SharpZipLibrary. - All library exceptions are derived from this. - - NOTE: Not all exceptions thrown will be derived from this class. - A variety of other exceptions are possible for example - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initializes a new instance of the SharpZipBaseException class. - - - - - Initializes a new instance of the SharpZipBaseException class with a specified error message. - - A message describing the exception. - - - - Initializes a new instance of the SharpZipBaseException class with a specified - error message and a reference to the inner exception that is the cause of this exception. - - A message describing the exception. - The inner exception - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initializes a new instance of the ZipException class. - - - - - Initializes a new instance of the ZipException class with a specified error message. - - The error message that explains the reason for the exception. - - - - Initialise a new instance of ZipException. - - A message describing the error. - The exception that is the cause of the current exception. - - - - A helper class to simplify compressing and decompressing streams. - - - - - Decompress input writing - decompressed data to the output stream - - The stream containing data to decompress. - The stream to write decompressed data to. - Both streams are closed on completion - - - - Compress input stream sending - result to output stream - - The stream to compress. - The stream to write compressed data to. - The block size to use. - Both streams are closed on completion - - - - Initialise a default instance of this class. - - - - - Determines how entries are tested to see if they should use Zip64 extensions or not. - - - - - Zip64 will not be forced on entries during processing. - - An entry can have this overridden if required - - - - Zip64 should always be used. - - - - - #ZipLib will determine use based on entry values when added to archive. - - - - - The kind of compression used for an entry in an archive - - - - - A direct copy of the file contents is held in the archive - - - - - Common Zip compression method using a sliding dictionary - of up to 32KB and secondary compression from Huffman/Shannon-Fano trees - - - - - An extension to deflate with a 64KB window. Not supported by #Zip currently - - - - - Not supported by #Zip currently - - - - - WinZip special for AES encryption, Not supported by #Zip - - - - - Identifies the encryption algorithm used for an entry - - - - - No encryption has been used. - - - - - Encrypted using PKZIP 2.0 or 'classic' encryption. - - - - - DES encryption has been used. - - - - - RCS encryption has been used for encryption. - - - - - Triple DES encryption with 168 bit keys has been used for this entry. - - - - - Triple DES with 112 bit keys has been used for this entry. - - - - - AES 128 has been used for encryption. - - - - - AES 192 has been used for encryption. - - - - - AES 256 has been used for encryption. - - - - - RC2 corrected has been used for encryption. - - - - - Blowfish has been used for encryption. - - - - - Twofish has been used for encryption. - - - - - RCS has been used for encryption. - - - - - An unknown algorithm has been used for encryption. - - - - - Defines the contents of the general bit flags field for an archive entry. - - - - - Bit 0 if set indicates that the file is encrypted - - - - - Bits 1 and 2 - Two bits defining the compression method (only for Method 6 Imploding and 8,9 Deflating) - - - - - Bit 3 if set indicates a trailing data desciptor is appended to the entry data - - - - - Bit 4 is reserved for use with method 8 for enhanced deflation - - - - - Bit 5 if set indicates the file contains Pkzip compressed patched data. - Requires version 2.7 or greater. - - - - - Bit 6 if set strong encryption has been used for this entry. - - - - - Bit 7 is currently unused - - - - - Bit 8 is currently unused - - - - - Bit 9 is currently unused - - - - - Bit 10 is currently unused - - - - - Bit 11 if set indicates the filename and - comment fields for this file must be encoded using UTF-8. - - - - - Bit 12 is documented as being reserved by PKware for enhanced compression. - - - - - Bit 13 if set indicates that values in the local header are masked to hide - their actual values, and the central directory is encrypted. - - - Used when encrypting the central directory contents. - - - - - Bit 14 is documented as being reserved for use by PKware - - - - - Bit 15 is documented as being reserved for use by PKware - - - - - This class contains constants used for Zip format files - - - - - The version made by field for entries in the central header when created by this library - - - This is also the Zip version for the library when comparing against the version required to extract - for an entry. See . - - - - - The version made by field for entries in the central header when created by this library - - - This is also the Zip version for the library when comparing against the version required to extract - for an entry. See ZipInputStream.CanDecompressEntry. - - - - - The minimum version required to support strong encryption - - - - - The minimum version required to support strong encryption - - - - - The version required for Zip64 extensions - - - - - Size of local entry header (excluding variable length fields at end) - - - - - Size of local entry header (excluding variable length fields at end) - - - - - Size of Zip64 data descriptor - - - - - Size of data descriptor - - - - - Size of data descriptor - - - - - Size of central header entry (excluding variable fields) - - - - - Size of central header entry - - - - - Size of end of central record (excluding variable fields) - - - - - Size of end of central record (excluding variable fields) - - - - - Size of 'classic' cryptographic header stored before any entry data - - - - - Size of cryptographic header stored before entry data - - - - - Signature for local entry header - - - - - Signature for local entry header - - - - - Signature for spanning entry - - - - - Signature for spanning entry - - - - - Signature for temporary spanning entry - - - - - Signature for temporary spanning entry - - - - - Signature for data descriptor - - - This is only used where the length, Crc, or compressed size isnt known when the - entry is created and the output stream doesnt support seeking. - The local entry cannot be 'patched' with the correct values in this case - so the values are recorded after the data prefixed by this header, as well as in the central directory. - - - - - Signature for data descriptor - - - This is only used where the length, Crc, or compressed size isnt known when the - entry is created and the output stream doesnt support seeking. - The local entry cannot be 'patched' with the correct values in this case - so the values are recorded after the data prefixed by this header, as well as in the central directory. - - - - - Signature for central header - - - - - Signature for central header - - - - - Signature for Zip64 central file header - - - - - Signature for Zip64 central file header - - - - - Signature for Zip64 central directory locator - - - - - Signature for archive extra data signature (were headers are encrypted). - - - - - Central header digitial signature - - - - - Central header digitial signature - - - - - End of central directory record signature - - - - - End of central directory record signature - - - - - Convert a portion of a byte array to a string. - - - Data to convert to string - - - Number of bytes to convert starting from index 0 - - - data[0]..data[length - 1] converted to a string - - - - - Convert a byte array to string - - - Byte array to convert - - - dataconverted to a string - - - - - Convert a byte array to string - - The applicable general purpose bits flags - - Byte array to convert - - The number of bytes to convert. - - dataconverted to a string - - - - - Convert a byte array to string - - - Byte array to convert - - The applicable general purpose bits flags - - dataconverted to a string - - - - - Convert a string to a byte array - - - String to convert to an array - - Converted array - - - - Convert a string to a byte array - - The applicable general purpose bits flags - - String to convert to an array - - Converted array - - - - Initialise default instance of ZipConstants - - - Private to prevent instances being created. - - - - - Default encoding used for string conversion. 0 gives the default system OEM code page. - Dont use unicode encodings if you want to be Zip compatible! - Using the default code page isnt the full solution neccessarily - there are many variable factors, codepage 850 is often a good choice for - European users, however be careful about compatability. - - - - - This is a DeflaterOutputStream that writes the files into a zip - archive one after another. It has a special method to start a new - zip entry. The zip entries contains information about the file name - size, compressed size, CRC, etc. - - It includes support for Stored and Deflated entries. - This class is not thread safe. -
-
Author of the original java version : Jochen Hoenicke -
- This sample shows how to create a zip file - - using System; - using System.IO; - - using ICSharpCode.SharpZipLib.Core; - using ICSharpCode.SharpZipLib.Zip; - - class MainClass - { - public static void Main(string[] args) - { - string[] filenames = Directory.GetFiles(args[0]); - byte[] buffer = new byte[4096]; - - using ( ZipOutputStream s = new ZipOutputStream(File.Create(args[1])) ) { - - s.SetLevel(9); // 0 - store only to 9 - means best compression - - foreach (string file in filenames) { - ZipEntry entry = new ZipEntry(file); - s.PutNextEntry(entry); - - using (FileStream fs = File.OpenRead(file)) { - StreamUtils.Copy(fs, s, buffer); - } - } - } - } - } - - -
- - - A special stream deflating or compressing the bytes that are - written to it. It uses a Deflater to perform actual deflating.
- Authors of the original java version : Tom Tromey, Jochen Hoenicke -
-
- - - Creates a new DeflaterOutputStream with a default Deflater and default buffer size. - - - the output stream where deflated output should be written. - - - - - Creates a new DeflaterOutputStream with the given Deflater and - default buffer size. - - - the output stream where deflated output should be written. - - - the underlying deflater. - - - - - Creates a new DeflaterOutputStream with the given Deflater and - buffer size. - - - The output stream where deflated output is written. - - - The underlying deflater to use - - - The buffer size to use when deflating - - - bufsize is less than or equal to zero. - - - baseOutputStream does not support writing - - - deflater instance is null - - - - - Finishes the stream by calling finish() on the deflater. - - - Not all input is deflated - - - - - Encrypt a block of data - - - Data to encrypt. NOTE the original contents of the buffer are lost - - - Offset of first byte in buffer to encrypt - - - Number of bytes in buffer to encrypt - - - - - Initializes encryption keys based on given password - - The password. - - - - Deflates everything in the input buffers. This will call - def.deflate() until all bytes from the input buffers - are processed. - - - - - Sets the current position of this stream to the given value. Not supported by this class! - - The offset relative to the to seek. - The to seek from. - The new position in the stream. - Any access - - - - Sets the length of this stream to the given value. Not supported by this class! - - The new stream length. - Any access - - - - Read a byte from stream advancing position by one - - The byte read cast to an int. THe value is -1 if at the end of the stream. - Any access - - - - Read a block of bytes from stream - - The buffer to store read data in. - The offset to start storing at. - The maximum number of bytes to read. - The actual number of bytes read. Zero if end of stream is detected. - Any access - - - - Asynchronous reads are not supported a NotSupportedException is always thrown - - The buffer to read into. - The offset to start storing data at. - The number of bytes to read - The async callback to use. - The state to use. - Returns an - Any access - - - - Asynchronous writes arent supported, a NotSupportedException is always thrown - - The buffer to write. - The offset to begin writing at. - The number of bytes to write. - The to use. - The state object. - Returns an IAsyncResult. - Any access - - - - Flushes the stream by calling Flush on the deflater and then - on the underlying stream. This ensures that all bytes are flushed. - - - - - Calls and closes the underlying - stream when is true. - - - - - Writes a single byte to the compressed output stream. - - - The byte value. - - - - - Writes bytes from an array to the compressed stream. - - - The byte array - - - The offset into the byte array where to start. - - - The number of bytes to write. - - - - - This buffer is used temporarily to retrieve the bytes from the - deflater and write them to the underlying output stream. - - - - - The deflater which is used to deflate the stream. - - - - - Base stream the deflater depends on. - - - - - Get/set flag indicating ownership of the underlying stream. - When the flag is true will close the underlying stream also. - - - - - Allows client to determine if an entry can be patched after its added - - - - - Get/set the password used for encryption. - - When set to null or if the password is empty no encryption is performed - - - - Gets value indicating stream can be read from - - - - - Gets a value indicating if seeking is supported for this stream - This property always returns false - - - - - Get value indicating if this stream supports writing - - - - - Get current length of stream - - - - - Gets the current position within the stream. - - Any attempt to set position - - - - Creates a new Zip output stream, writing a zip archive. - - - The output stream to which the archive contents are written. - - - - - Set the zip file comment. - - - The comment text for the entire archive. - - - The converted comment is longer than 0xffff bytes. - - - - - Sets the compression level. The new level will be activated - immediately. - - The new compression level (1 to 9). - - Level specified is not supported. - - - - - - Get the current deflater compression level - - The current compression level - - - - Write an unsigned short in little endian byte order. - - - - - Write an int in little endian byte order. - - - - - Write an int in little endian byte order. - - - - - Starts a new Zip entry. It automatically closes the previous - entry if present. - All entry elements bar name are optional, but must be correct if present. - If the compression method is stored and the output is not patchable - the compression for that entry is automatically changed to deflate level 0 - - - the entry. - - - if entry passed is null. - - - if an I/O error occured. - - - if stream was finished - - - Too many entries in the Zip file
- Entry name is too long
- Finish has already been called
-
-
- - - Closes the current entry, updating header and footer information as required - - - An I/O error occurs. - - - No entry is active. - - - - - Writes the given buffer to the current entry. - - The buffer containing data to write. - The offset of the first byte to write. - The number of bytes to write. - Archive size is invalid - No entry is active. - - - - Finishes the stream. This will write the central directory at the - end of the zip file and flush the stream. - - - This is automatically called when the stream is closed. - - - An I/O error occurs. - - - Comment exceeds the maximum length
- Entry name exceeds the maximum length -
-
- - - The entries for the archive. - - - - - Used to track the crc of data added to entries. - - - - - The current entry being added. - - - - - Used to track the size of data for an entry during writing. - - - - - Offset to be recorded for each entry in the central header. - - - - - Comment for the entire archive recorded in central header. - - - - - Flag indicating that header patching is required for the current entry. - - - - - Position to patch crc - - - - - Position to patch size. - - - - - Gets a flag value of true if the central header has been added for this archive; false if it has not been added. - - No further entries can be added once this has been done. - - - - Get / set a value indicating how Zip64 Extension usage is determined when adding entries. - - Older archivers may not understand Zip64 extensions. - If backwards compatability is an issue be careful when adding entries to an archive. - Setting this property to off is workable but less desirable as in those circumstances adding a file - larger then 4GB will fail. - - - - INameTransform defines how file system names are transformed for use with archives. - - - - - Given a file name determine the transformed value. - - The name to transform. - The transformed file name. - - - - Given a directory name determine the transformed value. - - The name to transform. - The transformed directory name - - - - This class contains constants used for deflation. - - - - - Set to true to enable debugging - - - - - Written to Zip file to identify a stored block - - - - - Identifies static tree in Zip file - - - - - Identifies dynamic tree in Zip file - - - - - Header flag indicating a preset dictionary for deflation - - - - - Sets internal buffer sizes for Huffman encoding - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - This class stores the pending output of the Deflater. - - author of the original java version : Jochen Hoenicke - - - - - Construct instance with default buffer size - - - - - PathFilter filters directories and files using a form of regular expressions - by full path name. - See NameFilter for more detail on filtering. - - - - - Initialise a new instance of . - - The filter expression to apply. - - - - Test a name to see if it matches the filter. - - The name to test. - True if the name matches, false otherwise. - - - - ExtendedPathFilter filters based on name, file size, and the last write time of the file. - - Provides an example of how to customise filtering. - - - - Initialise a new instance of ExtendedPathFilter. - - The filter to apply. - The minimum file size to include. - The maximum file size to include. - - - - Initialise a new instance of ExtendedPathFilter. - - The filter to apply. - The minimum to include. - The maximum to include. - - - - Initialise a new instance of ExtendedPathFilter. - - The filter to apply. - The minimum file size to include. - The maximum file size to include. - The minimum to include. - The maximum to include. - - - - Test a filename to see if it matches the filter. - - The filename to test. - True if the filter matches, false otherwise. - - - - Get/set the minimum size for a file that will match this filter. - - - - - Get/set the maximum size for a file that will match this filter. - - - - - Get/set the minimum value that will match for this filter. - - Files with a LastWrite time less than this value are excluded by the filter. - - - - Get/set the maximum value that will match for this filter. - - Files with a LastWrite time greater than this value are excluded by the filter. - - - - NameAndSizeFilter filters based on name and file size. - - A sample showing how filters might be extended. - - - - Initialise a new instance of NameAndSizeFilter. - - The filter to apply. - The minimum file size to include. - The maximum file size to include. - - - - Test a filename to see if it matches the filter. - - The filename to test. - True if the filter matches, false otherwise. - - - - Get/set the minimum size for a file that will match this filter. - - - - - Get/set the maximum size for a file that will match this filter. - - - - - BZip2Exception represents exceptions specific to Bzip2 algorithm - - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initialise a new instance of BZip2Exception. - - - - - Initialise a new instance of BZip2Exception with its message set to message. - - The message describing the error. - - - - Initialise an instance of BZip2Exception - - A message describing the error. - The exception that is the cause of the current exception. - - - - GZipException represents a Gzip specific exception - - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initialise a new instance of GZipException - - - - - Initialise a new instance of GZipException with its message string. - - A that describes the error. - - - - Initialise a new instance of . - - A that describes the error. - The that caused this exception. - - - - Contains the output from the Inflation process. - We need to have a window so that we can refer backwards into the output stream - to repeat stuff.
- Author of the original java version : John Leuner -
-
- - - Write a byte to this output window - - value to write - - if window is full - - - - - Append a byte pattern already in the window itself - - length of pattern to copy - distance from end of window pattern occurs - - If the repeated data overflows the window - - - - - Copy from input manipulator to internal window - - source of data - length of data to copy - the number of bytes copied - - - - Copy dictionary to window - - source dictionary - offset of start in source dictionary - length of dictionary - - If window isnt empty - - - - - Get remaining unfilled space in window - - Number of bytes left in window - - - - Get bytes available for output in window - - Number of bytes filled - - - - Copy contents of window to output - - buffer to copy to - offset to start at - number of bytes to count - The number of bytes copied - - If a window underflow occurs - - - - - Reset by clearing window so GetAvailable returns 0 - - - - - Defines internal values for both compression and decompression - - - - - When multiplied by compression parameter (1-9) gives the block size for compression - 9 gives the best compresssion but uses the most memory. - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Random numbers used to randomise repetitive blocks - - - - - This filter stream is used to compress a stream into a "GZIP" stream. - The "GZIP" format is described in RFC 1952. - - author of the original java version : John Leuner - - This sample shows how to gzip a file - - using System; - using System.IO; - - using ICSharpCode.SharpZipLib.GZip; - using ICSharpCode.SharpZipLib.Core; - - class MainClass - { - public static void Main(string[] args) - { - using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz"))) - using (FileStream fs = File.OpenRead(args[0])) { - byte[] writeData = new byte[4096]; - Streamutils.Copy(s, fs, writeData); - } - } - } - } - - - - - - CRC-32 value for uncompressed data - - - - - Creates a GzipOutputStream with the default buffer size - - - The stream to read data (to be compressed) from - - - - - Creates a GZipOutputStream with the specified buffer size - - - The stream to read data (to be compressed) from - - - Size of the buffer to use - - - - - Sets the active compression level (1-9). The new level will be activated - immediately. - - The compression level to set. - - Level specified is not supported. - - - - - - Get the current compression level. - - The current compression level. - - - - Write given buffer to output updating crc - - Buffer to write - Offset of first byte in buf to write - Number of bytes to write - - - - Writes remaining compressed output data to the output stream - and closes it. - - - - - Finish compression and write any footer information required to stream - - - - - Arguments used with KeysRequiredEvent - - - - - Initialise a new instance of - - The name of the file for which keys are required. - - - - Initialise a new instance of - - The name of the file for which keys are required. - The current key value. - - - - Get the name of the file for which keys are required. - - - - - Get/set the key value - - - - - The strategy to apply to testing. - - - - - Find the first error only. - - - - - Find all possible errors. - - - - - The operation in progress reported by a during testing. - - TestArchive - - - - Setting up testing. - - - - - Testing an individual entries header - - - - - Testing an individual entries data - - - - - Testing an individual entry has completed. - - - - - Running miscellaneous tests - - - - - Testing is complete - - - - - Status returned returned by during testing. - - TestArchive - - - - Initialise a new instance of - - The this status applies to. - - - - Get the current in progress. - - - - - Get the this status is applicable to. - - - - - Get the current/last entry tested. - - - - - Get the number of errors detected so far. - - - - - Get the number of bytes tested so far for the current entry. - - - - - Get a value indicating wether the last entry test was valid. - - - - - Delegate invoked during testing if supplied indicating current progress and status. - - If the message is non-null an error has occured. If the message is null - the operation as found in status has started. - - - - The possible ways of applying updates to an archive. - - - - - Perform all updates on temporary files ensuring that the original file is saved. - - - - - Update the archive directly, which is faster but less safe. - - - - - This class represents a Zip archive. You can ask for the contained - entries, or get an input stream for a file entry. The entry is - automatically decompressed. - - You can also update the archive adding or deleting entries. - - This class is thread safe for input: You can open input streams for arbitrary - entries in different threads. -
-
Author of the original java version : Jochen Hoenicke -
- - - using System; - using System.Text; - using System.Collections; - using System.IO; - - using ICSharpCode.SharpZipLib.Zip; - - class MainClass - { - static public void Main(string[] args) - { - using (ZipFile zFile = new ZipFile(args[0])) { - Console.WriteLine("Listing of : " + zFile.Name); - Console.WriteLine(""); - Console.WriteLine("Raw Size Size Date Time Name"); - Console.WriteLine("-------- -------- -------- ------ ---------"); - foreach (ZipEntry e in zFile) { - if ( e.IsFile ) { - DateTime d = e.DateTime; - Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize, - d.ToString("dd-MM-yy"), d.ToString("HH:mm"), - e.Name); - } - } - } - } - } - - -
- - - Event handler for handling encryption keys. - - - - - Handles getting of encryption keys when required. - - The file for which encryption keys are required. - - - - Opens a Zip file with the given name for reading. - - The name of the file to open. - - An i/o error occurs - - - The file doesn't contain a valid zip archive. - - - - - Opens a Zip file reading the given . - - The to read archive data from. - - An i/o error occurs. - - - The file doesn't contain a valid zip archive. - - - - - Opens a Zip file reading the given . - - The to read archive data from. - - An i/o error occurs - - - The file doesn't contain a valid zip archive.
- The stream provided cannot seek -
-
- - - Initialises a default instance with no entries and no file storage. - - - - - Finalize this instance. - - - - - Closes the ZipFile. If the stream is owned then this also closes the underlying input stream. - Once closed, no further instance methods should be called. - - - An i/o error occurs. - - - - - Create a new whose data will be stored in a file. - - The name of the archive to create. - Returns the newly created - - - - Create a new whose data will be stored on a stream. - - The stream providing data storage. - Returns the newly created - - - - Gets an enumerator for the Zip entries in this Zip file. - - Returns an for this archive. - - The Zip file has been closed. - - - - - Return the index of the entry with a matching name - - Entry name to find - If true the comparison is case insensitive - The index position of the matching entry or -1 if not found - - The Zip file has been closed. - - - - - Searches for a zip entry in this archive with the given name. - String comparisons are case insensitive - - - The name to find. May contain directory components separated by slashes ('/'). - - - A clone of the zip entry, or null if no entry with that name exists. - - - The Zip file has been closed. - - - - - Gets an input stream for reading the given zip entry data in an uncompressed form. - Normally the should be an entry returned by GetEntry(). - - The to obtain a data for - An input containing data for this - - The ZipFile has already been closed - - - The compression method for the entry is unknown - - - The entry is not found in the ZipFile - - - - - Creates an input stream reading a zip entry - - The index of the entry to obtain an input stream for. - - An input containing data for this - - - The ZipFile has already been closed - - - The compression method for the entry is unknown - - - The entry is not found in the ZipFile - - - - - Test an archive for integrity/validity - - Perform low level data Crc check - true if all tests pass, false otherwise - Testing will terminate on the first error found. - - - - Test an archive for integrity/validity - - Perform low level data Crc check - The to apply. - The handler to call during testing. - true if all tests pass, false otherwise - - - - Test a local header against that provided from the central directory - - - The entry to test against - - The type of tests to carry out. - The offset of the entries data in the file - - - - Begin updating this archive. - - The archive storage for use during the update. - The data source to utilise during updating. - - - - Begin updating to this archive. - - The storage to use during the update. - - - - Begin updating this archive. - - - - - - - - Commit current updates, updating this archive. - - - - - - - Abort updating leaving the archive unchanged. - - - - - - - Set the file comment to be recorded when the current update is commited. - - The comment to record. - - - - Add a new entry to the archive. - - The name of the file to add. - The compression method to use. - Ensure Unicode text is used for name and comment for this entry. - - - - Add a new entry to the archive. - - The name of the file to add. - The compression method to use. - - - - Add a file to the archive. - - The name of the file to add. - - - - Add a file entry with data. - - The source of the data for this entry. - The name to give to the entry. - - - - Add a file entry with data. - - The source of the data for this entry. - The name to give to the entry. - The compression method to use. - - - - Add a file entry with data. - - The source of the data for this entry. - The name to give to the entry. - The compression method to use. - Ensure Unicode text is used for name and comments for this entry. - - - - Add a that contains no data. - - The entry to add. - This can be used to add directories, volume labels, or empty file entries. - - - - Add a directory entry to the archive. - - The directory to add. - - - - Delete an entry by name - - The filename to delete - True if the entry was found and deleted; false otherwise. - - - - Delete a from the archive. - - The entry to delete. - - - - Write an unsigned short in little endian byte order. - - - - - Write an int in little endian byte order. - - - - - Write an unsigned int in little endian byte order. - - - - - Write a long in little endian byte order. - - - - - Get a raw memory buffer. - - Returns a raw memory buffer. - - - - Get the size of the source descriptor for a . - - The update to get the size for. - The descriptor size, zero if there isnt one. - - - - Get an output stream for the specified - - The entry to get an output stream for. - The output stream obtained for the entry. - - - - Releases the unmanaged resources used by the this instance and optionally releases the managed resources. - - true to release both managed and unmanaged resources; - false to release only unmanaged resources. - - - - Read an unsigned short in little endian byte order. - - Returns the value read. - - The stream ends prematurely - - - - - Read a uint in little endian byte order. - - Returns the value read. - - An i/o error occurs. - - - The file ends prematurely - - - - - Search for and read the central directory of a zip file filling the entries array. - - - An i/o error occurs. - - - The central directory is malformed or cannot be found - - - - - Locate the data for a given entry. - - - The start offset of the data. - - - The stream ends prematurely - - - The local header signature is invalid, the entry and central header file name lengths are different - or the local and entry compression methods dont match - - - - - Get/set the encryption key value. - - - - - Password to be used for encrypting/decrypting files. - - Set to null if no password is required. - - - - Get a value indicating wether encryption keys are currently available. - - - - - Get/set a flag indicating if the underlying stream is owned by the ZipFile instance. - If the flag is true then the stream will be closed when Close is called. - - - The default value is true in all cases. - - - - - Get a value indicating wether - this archive is embedded in another file or not. - - - - - Get a value indicating that this archive is a new one. - - - - - Gets the comment for the zip file. - - - - - Gets the name of this zip file. - - - - - Gets the number of entries in this zip file. - - - The Zip file has been closed. - - - - - Get the number of entries contained in this . - - - - - Indexer property for ZipEntries - - - - - Get / set the to apply to names when updating. - - - - - Get/set the used to generate values - during updates. - - - - - Get /set the buffer size to be used when updating this zip file. - - - - - Get a value indicating an update has been started. - - - - - Get / set a value indicating how Zip64 Extension usage is determined when adding entries. - - - - - Delegate for handling keys/password setting during compresion/decompression. - - - - - The kind of update to apply. - - - - - Class used to sort updates. - - - - - Compares two objects and returns a value indicating whether one is - less than, equal to or greater than the other. - - First object to compare - Second object to compare. - Compare result. - - - - Represents a pending update to a Zip file. - - - - - Copy an existing entry. - - The existing entry to copy. - - - - Get the for this update. - - This is the source or original entry. - - - - Get the that will be written to the updated/new file. - - - - - Get the command for this update. - - - - - Get the filename if any for this update. Null if none exists. - - - - - Get/set the location of the size patch for this update. - - - - - Get /set the location of the crc patch for this update. - - - - - Represents a string from a which is stored as an array of bytes. - - - - - Initialise a with a string. - - The textual string form. - - - - Initialise a using a string in its binary 'raw' form. - - - - - - Reset the comment to its initial state. - - - - - Implicit conversion of comment to a string. - - The to convert to a string. - The textual equivalent for the input value. - - - - Get a value indicating the original source of data for this instance. - True if the source was a string; false if the source was binary data. - - - - - Get the length of the comment when represented as raw bytes. - - - - - Get the comment in its 'raw' form as plain bytes. - - - - - An enumerator for Zip entries - - - - - An is a stream that you can write uncompressed data - to and flush, but cannot read, seek or do anything else to. - - - - - Close this stream instance. - - - - - Write any buffered data to underlying storage. - - - - - Gets a value indicating whether the current stream supports reading. - - - - - Gets a value indicating whether the current stream supports writing. - - - - - Gets a value indicating whether the current stream supports seeking. - - - - - Get the length in bytes of the stream. - - - - - Gets or sets the position within the current stream. - - - - - A is an - whose data is only a part or subsection of a file. - - - - - This filter stream is used to decompress data compressed using the "deflate" - format. The "deflate" format is described in RFC 1951. - - This stream may form the basis for other decompression filters, such - as the GZipInputStream. - - Author of the original java version : John Leuner. - - - - - Create an InflaterInputStream with the default decompressor - and a default buffer size of 4KB. - - - The InputStream to read bytes from - - - - - Create an InflaterInputStream with the specified decompressor - and a default buffer size of 4KB. - - - The source of input data - - - The decompressor used to decompress data read from baseInputStream - - - - - Create an InflaterInputStream with the specified decompressor - and the specified buffer size. - - - The InputStream to read bytes from - - - The decompressor to use - - - Size of the buffer to use - - - - - Skip specified number of bytes of uncompressed data - - - Number of bytes to skip - - - The number of bytes skipped, zero if the end of - stream has been reached - - - Number of bytes to skip is less than zero - - - - - Clear any cryptographic state. - - - - - Fills the buffer with more data to decompress. - - - Stream ends early - - - - - Flushes the baseInputStream - - - - - Sets the position within the current stream - Always throws a NotSupportedException - - The relative offset to seek to. - The defining where to seek from. - The new position in the stream. - Any access - - - - Set the length of the current stream - Always throws a NotSupportedException - - The new length value for the stream. - Any access - - - - Writes a sequence of bytes to stream and advances the current position - This method always throws a NotSupportedException - - Thew buffer containing data to write. - The offset of the first byte to write. - The number of bytes to write. - Any access - - - - Writes one byte to the current stream and advances the current position - Always throws a NotSupportedException - - The byte to write. - Any access - - - - Entry point to begin an asynchronous write. Always throws a NotSupportedException. - - The buffer to write data from - Offset of first byte to write - The maximum number of bytes to write - The method to be called when the asynchronous write operation is completed - A user-provided object that distinguishes this particular asynchronous write request from other requests - An IAsyncResult that references the asynchronous write - Any access - - - - Closes the input stream. When - is true the underlying stream is also closed. - - - - - Reads decompressed data into the provided buffer byte array - - - The array to read and decompress data into - - - The offset indicating where the data should be placed - - - The number of bytes to decompress - - The number of bytes read. Zero signals the end of stream - - Inflater needs a dictionary - - - - - Decompressor for this stream - - - - - Input buffer for this stream. - - - - - Base stream the inflater reads from. - - - - - The compressed size - - - - - Flag indicating wether this instance has been closed or not. - - - - - Flag indicating wether this instance is designated the stream owner. - When closing if this flag is true the underlying stream is closed. - - - - - Get/set flag indicating ownership of underlying stream. - When the flag is true will close the underlying stream also. - - - The default value is true. - - - - - Returns 0 once the end of the stream (EOF) has been reached. - Otherwise returns 1. - - - - - Gets a value indicating whether the current stream supports reading - - - - - Gets a value of false indicating seeking is not supported for this stream. - - - - - Gets a value of false indicating that this stream is not writeable. - - - - - A value representing the length of the stream in bytes. - - - - - The current position within the stream. - Throws a NotSupportedException when attempting to set the position - - Attempting to set the position - - - - Initialise a new instance of the class. - - The underlying stream to use for IO. - The start of the partial data. - The length of the partial data. - - - - Skip the specified number of input bytes. - - The maximum number of input bytes to skip. - The actuial number of input bytes skipped. - - - - Read a byte from this stream. - - Returns the byte read or -1 on end of stream. - - - - Close this partial input stream. - - - The underlying stream is not closed. Close the parent ZipFile class to do that. - - - - - Provides a static way to obtain a source of data for an entry. - - - - - Get a source of data by creating a new stream. - - Returns a to use for compression input. - Ideally a new stream is created and opened to achieve this, to avoid locking problems. - - - - Represents a source of data that can dynamically provide - multiple data sources based on the parameters passed. - - - - - Get a data source. - - The to get a source for. - The name for data if known. - Returns a to use for compression input. - Ideally a new stream is created and opened to achieve this, to avoid locking problems. - - - - Default implementation of a for use with files stored on disk. - - - - - Initialise a new instnace of - - The name of the file to obtain data from. - - - - Get a providing data. - - Returns a provising data. - - - - Default implementation of for files stored on disk. - - - - - Initialise a default instance of . - - - - - Get a providing data for an entry. - - The entry to provide data for. - The file name for data if known. - Returns a stream providing data; or null if not available - - - - Defines facilities for data storage when updating Zip Archives. - - - - - Get an empty that can be used for temporary output. - - Returns a temporary output - - - - - Convert a temporary output stream to a final stream. - - The resulting final - - - - - Make a temporary copy of the original stream. - - The to copy. - Returns a temporary output that is a copy of the input. - - - - Return a stream suitable for performing direct updates on the original source. - - The current stream. - Returns a stream suitable for direct updating. - This may be the current stream passed. - - - - Dispose of this instance. - - - - - Get the to apply during updates. - - - - - An abstract suitable for extension by inheritance. - - - - - Initializes a new instance of the class. - - The update mode. - - - - Gets a temporary output - - Returns the temporary output stream. - - - - - Converts the temporary to its final form. - - Returns a that can be used to read - the final storage for the archive. - - - - - Make a temporary copy of a . - - The to make a copy of. - Returns a temporary output that is a copy of the input. - - - - Return a stream suitable for performing direct updates on the original source. - - The to open for direct update. - Returns a stream suitable for direct updating. - - - - Disposes this instance. - - - - - Gets the update mode applicable. - - The update mode. - - - - An implementation suitable for hard disks. - - - - - Initializes a new instance of the class. - - The file. - The update mode. - - - - Initializes a new instance of the class. - - The file. - - - - Gets a temporary output for performing updates on. - - Returns the temporary output stream. - - - - Converts a temporary to its final form. - - Returns a that can be used to read - the final storage for the archive. - - - - Make a temporary copy of a stream. - - The to copy. - Returns a temporary output that is a copy of the input. - - - - Return a stream suitable for performing direct updates on the original source. - - The current stream. - Returns a stream suitable for direct updating. - If the stream is not null this is used as is. - - - - Disposes this instance. - - - - - An implementation suitable for in memory streams. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - The to use - This constructor is for testing as memory streams dont really require safe mode. - - - - Gets the temporary output - - Returns the temporary output stream. - - - - Converts the temporary to its final form. - - Returns a that can be used to read - the final storage for the archive. - - - - Make a temporary copy of the original stream. - - The to copy. - Returns a temporary output that is a copy of the input. - - - - Return a stream suitable for performing direct updates on the original source. - - The original source stream - Returns a stream suitable for direct updating. - If the passed is not null this is used; - otherwise a new is returned. - - - - Disposes this instance. - - - - - Get the stream returned by if this was in fact called. - - - - - Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The table is simply the CRC of all possible eight bit values. This is all - the information needed to generate CRC's on data a byte at a time for all - combinations of CRC register values and incoming bytes. - - - - - Interface to compute a data checksum used by checked input/output streams. - A data checksum can be updated by one byte or with a byte array. After each - update the value of the current checksum can be returned by calling - getValue. The complete checksum object can also be reset - so it can be used again with new data. - - - - - Resets the data checksum as if no update was ever called. - - - - - Adds one byte to the data checksum. - - - the data value to add. The high byte of the int is ignored. - - - - - Updates the data checksum with the bytes taken from the array. - - - buffer an array of bytes - - - - - Adds the byte array to the data checksum. - - - The buffer which contains the data - - - The offset in the buffer where the data starts - - - the number of data bytes to add. - - - - - Returns the data checksum computed so far. - - - - - The crc data checksum so far. - - - - - Resets the CRC32 data checksum as if no update was ever called. - - - - - Updates the checksum with the int bval. - - - the byte is taken as the lower 8 bits of value - - - - - Updates the checksum with the bytes taken from the array. - - - buffer an array of bytes - - - - - Adds the byte array to the data checksum. - - - The buffer which contains the data - - - The offset in the buffer where the data starts - - - The number of data bytes to update the CRC with. - - - - - Returns the CRC32 data checksum computed so far. - - - - - Basic implementation of - - - - - Defines factory methods for creating new values. - - - - - Create a for a file given its name - - The name of the file to create an entry for. - Returns a file entry based on the passed. - - - - Create a for a file given its name - - The name of the file to create an entry for. - If true get details from the file system if the file exists. - Returns a file entry based on the passed. - - - - Create a for a directory given its name - - The name of the directory to create an entry for. - Returns a directory entry based on the passed. - - - - Create a for a directory given its name - - The name of the directory to create an entry for. - If true get details from the file system for this directory if it exists. - Returns a directory entry based on the passed. - - - - Get/set the applicable. - - - - - Initialise a new instance of the class. - - A default , and the LastWriteTime for files is used. - - - - Initialise a new instance of using the specified - - The time setting to use when creating Zip entries. - - - - Initialise a new instance of using the specified - - The time to set all values to. - - - - Make a new for a file. - - The name of the file to create a new entry for. - Returns a new based on the . - - - - Make a new from a name. - - The name of the file to create a new entry for. - If true entry detail is retrieved from the file system if the file exists. - Returns a new based on the . - - - - Make a new for a directory. - - The raw untransformed name for the new directory - Returns a new representing a directory. - - - - Make a new for a directory. - - The raw untransformed name for the new directory - If true entry detail is retrieved from the file system if the file exists. - Returns a new representing a directory. - - - - Get / set the to be used when creating new values. - - - Setting this property to null will cause a default name transform to be used. - - - - - Get / set the in use. - - - - - Get / set the value to use when is set to - - - - - A bitmask defining the attributes to be retrieved from the actual file. - - The default is to get all possible attributes from the actual file. - - - - A bitmask defining which attributes are to be set on. - - By default no attributes are set on. - - - - Get set a value indicating wether unidoce text should be set on. - - - - - Defines the possible values to be used for the . - - - - - Use the recorded LastWriteTime value for the file. - - - - - Use the recorded LastWriteTimeUtc value for the file - - - - - Use the recorded CreateTime value for the file. - - - - - Use the recorded CreateTimeUtc value for the file. - - - - - Use the recorded LastAccessTime value for the file. - - - - - Use the recorded LastAccessTimeUtc value for the file. - - - - - Use a fixed value. - - The actual value used can be - specified via the constructor or - using the with the setting set - to which will use the when this class was constructed. - The property can also be used to set this value. - - - - PkzipClassic embodies the classic or original encryption facilities used in Pkzip archives. - While it has been superceded by more recent and more powerful algorithms, its still in use and - is viable for preventing casual snooping - - - - - Generates new encryption keys based on given seed - - The seed value to initialise keys with. - A new key value. - - - - PkzipClassicCryptoBase provides the low level facilities for encryption - and decryption using the PkzipClassic algorithm. - - - - - Transform a single byte - - - The transformed value - - - - - Set the key schedule for encryption/decryption. - - The data use to set the keys from. - - - - Update encryption keys - - - - - Reset the internal state. - - - - - PkzipClassic CryptoTransform for encryption. - - - - - Initialise a new instance of - - The key block to use. - - - - Transforms the specified region of the specified byte array. - - The input for which to compute the transform. - The offset into the byte array from which to begin using data. - The number of bytes in the byte array to use as data. - The computed transform. - - - - Transforms the specified region of the input byte array and copies - the resulting transform to the specified region of the output byte array. - - The input for which to compute the transform. - The offset into the input byte array from which to begin using data. - The number of bytes in the input byte array to use as data. - The output to which to write the transform. - The offset into the output byte array from which to begin writing data. - The number of bytes written. - - - - Cleanup internal state. - - - - - Gets a value indicating whether the current transform can be reused. - - - - - Gets the size of the input data blocks in bytes. - - - - - Gets the size of the output data blocks in bytes. - - - - - Gets a value indicating whether multiple blocks can be transformed. - - - - - PkzipClassic CryptoTransform for decryption. - - - - - Initialise a new instance of . - - The key block to decrypt with. - - - - Transforms the specified region of the specified byte array. - - The input for which to compute the transform. - The offset into the byte array from which to begin using data. - The number of bytes in the byte array to use as data. - The computed transform. - - - - Transforms the specified region of the input byte array and copies - the resulting transform to the specified region of the output byte array. - - The input for which to compute the transform. - The offset into the input byte array from which to begin using data. - The number of bytes in the input byte array to use as data. - The output to which to write the transform. - The offset into the output byte array from which to begin writing data. - The number of bytes written. - - - - Cleanup internal state. - - - - - Gets a value indicating whether the current transform can be reused. - - - - - Gets the size of the input data blocks in bytes. - - - - - Gets the size of the output data blocks in bytes. - - - - - Gets a value indicating whether multiple blocks can be transformed. - - - - - Defines a wrapper object to access the Pkzip algorithm. - This class cannot be inherited. - - - - - Generate an initial vector. - - - - - Generate a new random key. - - - - - Create an encryptor. - - The key to use for this encryptor. - Initialisation vector for the new encryptor. - Returns a new PkzipClassic encryptor - - - - Create a decryptor. - - Keys to use for this new decryptor. - Initialisation vector for the new decryptor. - Returns a new decryptor. - - - - Get / set the applicable block size in bits. - - The only valid block size is 8. - - - - Get an array of legal key sizes. - - - - - Get an array of legal block sizes. - - - - - Get / set the key value applicable. - - - - - This class represents an entry in a Tar archive. It consists - of the entry's header, as well as the entry's File. Entries - can be instantiated in one of three ways, depending on how - they are to be used. -

- TarEntries that are created from the header bytes read from - an archive are instantiated with the TarEntry( byte[] ) - constructor. These entries will be used when extracting from - or listing the contents of an archive. These entries have their - header filled in using the header bytes. They also set the File - to null, since they reference an archive entry not a file.

-

- TarEntries that are created from files that are to be written - into an archive are instantiated with the CreateEntryFromFile(string) - pseudo constructor. These entries have their header filled in using - the File's information. They also keep a reference to the File - for convenience when writing entries.

-

- Finally, TarEntries can be constructed from nothing but a name. - This allows the programmer to construct the entry by hand, for - instance when only an InputStream is available for writing to - the archive, and the header information is constructed from - other information. In this case the header fields are set to - defaults and the File is set to null.

- -
-
- - - Initialise a default instance of . - - - - - Construct an entry from an archive's header bytes. File is set - to null. - - - The header bytes from a tar archive entry. - - - - - Construct a TarEntry using the header provided - - Header details for entry - - - - Clone this tar entry. - - Returns a clone of this entry. - - - - Construct an entry with only a name. - This allows the programmer to construct the entry's header "by hand". - - The name to use for the entry - Returns the newly created - - - - Construct an entry for a file. File is set to file, and the - header is constructed from information from the file. - - The file name that the entry represents. - Returns the newly created - - - - Determine if the two entries are equal. Equality is determined - by the header names being equal. - - The to compare with the current Object. - - True if the entries are equal; false if not. - - - - - Derive a Hash value for the current - - A Hash code for the current - - - - Determine if the given entry is a descendant of this entry. - Descendancy is determined by the name of the descendant - starting with this entry's name. - - - Entry to be checked as a descendent of this. - - - True if entry is a descendant of this. - - - - - Convenience method to set this entry's group and user ids. - - - This entry's new user id. - - - This entry's new group id. - - - - - Convenience method to set this entry's group and user names. - - - This entry's new user name. - - - This entry's new group name. - - - - - Fill in a TarHeader with information from a File. - - - The TarHeader to fill in. - - - The file from which to get the header information. - - - - - Get entries for all files present in this entries directory. - If this entry doesnt represent a directory zero entries are returned. - - - An array of TarEntry's for this entry's children. - - - - - Write an entry's header information to a header buffer. - - - The tar entry header buffer to fill in. - - - - - Convenience method that will modify an entry's name directly - in place in an entry header buffer byte array. - - - The buffer containing the entry header to modify. - - - The new name to place into the header buffer. - - - - - Fill in a TarHeader given only the entry's name. - - - The TarHeader to fill in. - - - The tar entry name. - - - - - The name of the file this entry represents or null if the entry is not based on a file. - - - - - The entry's header information. - - - - - Get this entry's header. - - - This entry's TarHeader. - - - - - Get/Set this entry's name. - - - - - Get/set this entry's user id. - - - - - Get/set this entry's group id. - - - - - Get/set this entry's user name. - - - - - Get/set this entry's group name. - - - - - Get/Set the modification time for this entry - - - - - Get this entry's file. - - - This entry's file. - - - - - Get/set this entry's recorded file size. - - - - - Return true if this entry represents a directory, false otherwise - - - True if this entry is a directory. - - - - - This filter stream is used to decompress a "GZIP" format stream. - The "GZIP" format is described baseInputStream RFC 1952. - - author of the original java version : John Leuner - - This sample shows how to unzip a gzipped file - - using System; - using System.IO; - - using ICSharpCode.SharpZipLib.Core; - using ICSharpCode.SharpZipLib.GZip; - - class MainClass - { - public static void Main(string[] args) - { - using (Stream inStream = new GZipInputStream(File.OpenRead(args[0]))) - using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { - byte[] buffer = new byte[4096]; - StreamUtils.Copy(inStream, outStream, buffer); - } - } - } - - - - - - CRC-32 value for uncompressed data - - - - - Indicates end of stream - - - - - Creates a GZipInputStream with the default buffer size - - - The stream to read compressed data from (baseInputStream GZIP format) - - - - - Creates a GZIPInputStream with the specified buffer size - - - The stream to read compressed data from (baseInputStream GZIP format) - - - Size of the buffer to use - - - - - Reads uncompressed data into an array of bytes - - - The buffer to read uncompressed data into - - - The offset indicating where the data should be placed - - - The number of uncompressed bytes to be read - - Returns the number of bytes actually read. - - - - Provides simple " utilities. - - - - - Read from a ensuring all the required data is read. - - The stream to read. - The buffer to fill. - - - - Read from a " ensuring all the required data is read. - - The stream to read data from. - The buffer to store data in. - The offset at which to begin storing data. - The number of bytes of data to store. - - - - Copy the contents of one to another. - - The stream to source data from. - The stream to write data to. - The buffer to use during copying. - The progress handler delegate to use. - The minimum between progress updates. - The source for this event. - The name to use with the event. - - - - Copy the contents of one to another. - - The stream to source data from. - The stream to write data to. - The buffer to use during copying. - - - - Initialise an instance of - - - - - This is the DeflaterHuffman class. - - This class is not thread safe. This is inherent in the API, due - to the split of Deflate and SetInput. - - author of the original java version : Jochen Hoenicke - - - - - Pending buffer to use - - - - - Construct instance with pending buffer - - Pending buffer to use - - - - Reset internal state - - - - - Write all trees to pending buffer - - The number/rank of treecodes to send. - - - - Compress current buffer writing data to pending buffer - - - - - Flush block to output with no compression - - Data to write - Index of first byte to write - Count of bytes to write - True if this is the last block - - - - Flush block to output with compression - - Data to flush - Index of first byte to flush - Count of bytes to flush - True if this is the last block - - - - Get value indicating if internal buffer is full - - true if buffer is full - - - - Add literal to buffer - - Literal value to add to buffer. - Value indicating internal buffer is full - - - - Add distance code and length to literal and distance trees - - Distance code - Length - Value indicating if internal buffer is full - - - - Reverse the bits of a 16 bit value. - - Value to reverse bits - Value with bits reversed - - - - Resets the internal state of the tree - - - - - Check that all frequencies are zero - - - At least one frequency is non-zero - - - - - Set static codes and length - - new codes - length for new codes - - - - Build dynamic codes and lengths - - - - - Get encoded length - - Encoded length, the sum of frequencies * lengths - - - - Scan a literal or distance tree to determine the frequencies of the codes - in the bit length tree. - - - - - Write tree values - - Tree to write - - - - This class contains constants used for gzip. - - - - - Magic number found at start of GZIP header - - - - - Flag bit mask for text - - - - - Flag bitmask for Crc - - - - - Flag bit mask for extra - - - - - flag bitmask for name - - - - - flag bit mask indicating comment is present - - - - - Initialise default instance. - - Constructor is private to prevent instances being created. - - - - TarExceptions are used for exceptions specific to tar classes and code. - - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initialises a new instance of the TarException class. - - - - - Initialises a new instance of the TarException class with a specified message. - - The message that describes the error. - - - - - - A message describing the error. - The exception that is the cause of the current exception. - - - - Bzip2 checksum algorithm - - - - - Initialise a default instance of - - - - - Reset the state of Crc. - - - - - Update the Crc value. - - data update is based on - - - - Update Crc based on a block of data - - The buffer containing data to update the crc with. - - - - Update Crc based on a portion of a block of data - - block of data - index of first byte to use - number of bytes to use - - - - Get the current Crc value. - - - - - This is an InflaterInputStream that reads the files baseInputStream an zip archive - one after another. It has a special method to get the zip entry of - the next file. The zip entry contains information about the file name - size, compressed size, Crc, etc. - It includes support for Stored and Deflated entries. -
-
Author of the original java version : Jochen Hoenicke -
- - This sample shows how to read a zip file - - using System; - using System.Text; - using System.IO; - - using ICSharpCode.SharpZipLib.Zip; - - class MainClass - { - public static void Main(string[] args) - { - using ( ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]))) { - - ZipEntry theEntry; - while ((theEntry = s.GetNextEntry()) != null) { - int size = 2048; - byte[] data = new byte[2048]; - - Console.Write("Show contents (y/n) ?"); - if (Console.ReadLine() == "y") { - while (true) { - size = s.Read(data, 0, data.Length); - if (size > 0) { - Console.Write(new ASCIIEncoding().GetString(data, 0, size)); - } else { - break; - } - } - } - } - } - } - } - - -
- - - The current reader this instance. - - - - - Creates a new Zip input stream, for reading a zip archive. - - The underlying providing data. - - - - Advances to the next entry in the archive - - - The next entry in the archive or null if there are no more entries. - - - If the previous entry is still open CloseEntry is called. - - - Input stream is closed - - - Password is not set, password is invalid, compression method is invalid, - version required to extract is not supported - - - - - Read data descriptor at the end of compressed data. - - - - - Complete cleanup as the final part of closing. - - True if the crc value should be tested - - - - Closes the current zip entry and moves to the next one. - - - The stream is closed - - - The Zip stream ends early - - - - - Reads a byte from the current zip entry. - - - The byte or -1 if end of stream is reached. - - - - - Handle attempts to read by throwing an . - - The destination array to store data in. - The offset at which data read should be stored. - The maximum number of bytes to read. - Returns the number of bytes actually read. - - - - Handle attempts to read from this entry by throwing an exception - - - - - Perform the initial read on an entry which may include - reading encryption headers and setting up inflation. - - The destination to fill with data read. - The offset to start reading at. - The maximum number of bytes to read. - The actual number of bytes read. - - - - Read a block of bytes from the stream. - - The destination for the bytes. - The index to start storing data. - The number of bytes to attempt to read. - Returns the number of bytes read. - Zero bytes read means end of stream. - - - - Reads a block of bytes from the current zip entry. - - - The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream. - - - An i/o error occured. - - - The deflated stream is corrupted. - - - The stream is not open. - - - - - Closes the zip input stream - - - - - Optional password used for encryption when non-null - - A password for all encrypted entries in this - - - - Gets a value indicating if there is a current entry and it can be decompressed - - - The entry can only be decompressed if the library supports the zip features required to extract it. - See the ZipEntry Version property for more details. - - - - - Returns 1 if there is an entry available - Otherwise returns 0. - - - - - Returns the current size that can be read from the current entry if available - - Thrown if the entry size is not known. - Thrown if no entry is currently available. - - - - ZipNameTransform transforms names as per the Zip file naming convention. - - The use of absolute names is supported although its use is not valid - according to Zip naming conventions, and should not be used if maximum compatability is desired. - - - - Initialize a new instance of - - - - - Initialize a new instance of - - The string to trim from front of paths if found. - - - - Static constructor. - - - - - Transform a directory name according to the Zip file naming conventions. - - The directory name to transform. - The transformed name. - - - - Transform a windows file name according to the Zip file naming conventions. - - The file name to transform. - The transformed name. - - - - Force a name to be valid by replacing invalid characters with a fixed value - - The name to force valid - The replacement character to use. - Returns a valid name - - - - Test a name to see if it is a valid name for a zip entry. - - The name to test. - If true checking is relaxed about windows file names and absolute paths. - Returns true if the name is a valid zip name; false otherwise. - Zip path names are actually in Unix format, and should only contain relative paths. - This means that any path stored should not contain a drive or - device letter, or a leading slash. All slashes should forward slashes '/'. - An empty name is valid for a file where the input comes from standard input. - A null name is not considered valid. - - - - - Test a name to see if it is a valid name for a zip entry. - - The name to test. - Returns true if the name is a valid zip name; false otherwise. - Zip path names are actually in unix format, - and should only contain relative paths if a path is present. - This means that the path stored should not contain a drive or - device letter, or a leading slash. All slashes should forward slashes '/'. - An empty name is valid where the input comes from standard input. - A null name is not considered valid. - - - - - Get/set the path prefix to be trimmed from paths if present. - - The prefix is trimmed before any conversion from - a windows path is done. - - - - This exception is used to indicate that there is a problem - with a TAR archive header. - - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initialise a new instance of the InvalidHeaderException class. - - - - - Initialises a new instance of the InvalidHeaderException class with a specified message. - - Message describing the exception cause. - - - - Initialise a new instance of InvalidHeaderException - - Message describing the problem. - The exception that is the cause of the current exception. - - - - This class allows us to retrieve a specified number of bits from - the input buffer, as well as copy big byte blocks. - - It uses an int buffer to store up to 31 bits for direct - manipulation. This guarantees that we can get at least 16 bits, - but we only need at most 15, so this is all safe. - - There are some optimizations in this class, for example, you must - never peek more than 8 bits more than needed, and you must first - peek bits before you may drop them. This is not a general purpose - class but optimized for the behaviour of the Inflater. - - authors of the original java version : John Leuner, Jochen Hoenicke - - - - - Constructs a default StreamManipulator with all buffers empty - - - - - Get the next sequence of bits but don't increase input pointer. bitCount must be - less or equal 16 and if this call succeeds, you must drop - at least n - 8 bits in the next call. - - The number of bits to peek. - - the value of the bits, or -1 if not enough bits available. */ - - - - - Drops the next n bits from the input. You should have called PeekBits - with a bigger or equal n before, to make sure that enough bits are in - the bit buffer. - - The number of bits to drop. - - - - Gets the next n bits and increases input pointer. This is equivalent - to followed by , except for correct error handling. - - The number of bits to retrieve. - - the value of the bits, or -1 if not enough bits available. - - - - - Skips to the next byte boundary. - - - - - Copies bytes from input buffer to output buffer starting - at output[offset]. You have to make sure, that the buffer is - byte aligned. If not enough bytes are available, copies fewer - bytes. - - - The buffer to copy bytes to. - - - The offset in the buffer at which copying starts - - - The length to copy, 0 is allowed. - - - The number of bytes copied, 0 if no bytes were available. - - - Length is less than zero - - - Bit buffer isnt byte aligned - - - - - Resets state and empties internal buffers - - - - - Add more input for consumption. - Only call when IsNeedingInput returns true - - data to be input - offset of first byte of input - number of bytes of input to add. - - - - Gets the number of bits available in the bit buffer. This must be - only called when a previous PeekBits() returned -1. - - - the number of bits available. - - - - - Gets the number of bytes available. - - - The number of bytes available. - - - - - Returns true when SetInput can be called - - - - - Strategies for deflater - - - - - The default strategy - - - - - This strategy will only allow longer string repetitions. It is - useful for random data with a small character set. - - - - - This strategy will not look for string repetitions at all. It - only encodes with Huffman trees (which means, that more common - characters get a smaller encoding. - - - - - Low level compression engine for deflate algorithm which uses a 32K sliding window - with secondary compression from Huffman/Shannon-Fano codes. - - - - - Construct instance with pending buffer - - - Pending buffer to use - > - - - - Deflate drives actual compression of data - - True to flush input buffers - Finish deflation with the current input. - Returns true if progress has been made. - - - - Sets input data to be deflated. Should only be called when NeedsInput() - returns true - - The buffer containing input data. - The offset of the first byte of data. - The number of bytes of data to use as input. - - - - Determines if more input is needed. - - Return true if input is needed via SetInput - - - - Set compression dictionary - - The buffer containing the dictionary data - The offset in the buffer for the first byte of data - The length of the dictionary data. - - - - Reset internal state - - - - - Reset Adler checksum - - - - - Set the deflate level (0-9) - - The value to set the level to. - - - - Fill the window - - - - - Inserts the current string in the head hash and returns the previous - value for this hash. - - The previous hash value - - - - Find the best (longest) string in the window matching the - string starting at strstart. - - Preconditions: - - strstart + MAX_MATCH <= window.length. - - - True if a match greater than the minimum length is found - - - - Hashtable, hashing three characters to an index for window, so - that window[index]..window[index+2] have this hash code. - Note that the array should really be unsigned short, so you need - to and the values with 0xffff. - - - - - prev[index & WMASK] points to the previous index that has the - same hash code as the string starting at index. This way - entries with the same hash code are in a linked list. - Note that the array should really be unsigned short, so you need - to and the values with 0xffff. - - - - - Points to the current character in the window. - - - - - lookahead is the number of characters starting at strstart in - window that are valid. - So window[strstart] until window[strstart+lookahead-1] are valid - characters. - - - - - This array contains the part of the uncompressed stream that - is of relevance. The current character is indexed by strstart. - - - - - The current compression function. - - - - - The input data for compression. - - - - - The total bytes of input read. - - - - - The offset into inputBuf, where input data starts. - - - - - The end offset of the input data. - - - - - The adler checksum - - - - - Get current value of Adler checksum - - - - - Total data processed - - - - - Get/set the deflate strategy - - - - - The TarBuffer class implements the tar archive concept - of a buffered input stream. This concept goes back to the - days of blocked tape drives and special io devices. In the - C# universe, the only real function that this class - performs is to ensure that files have the correct "record" - size, or other tars will complain. -

- You should never have a need to access this class directly. - TarBuffers are created by Tar IO Streams. -

-
-
- - - The size of a block in a tar archive in bytes. - - This is 512 bytes. - - - - The number of blocks in a default record. - - - The default value is 20 blocks per record. - - - - - The size in bytes of a default record. - - - The default size is 10KB. - - - - - Get the TAR Buffer's record size. - - The record size in bytes. - This is equal to the multiplied by the - - - - Get the TAR Buffer's block factor - - The block factor; the number of blocks per record. - - - - Construct a default TarBuffer - - - - - Create TarBuffer for reading with default BlockFactor - - Stream to buffer - A new suitable for input. - - - - Construct TarBuffer for reading inputStream setting BlockFactor - - Stream to buffer - Blocking factor to apply - A new suitable for input. - - - - Construct TarBuffer for writing with default BlockFactor - - output stream for buffer - A new suitable for output. - - - - Construct TarBuffer for writing Tar output to streams. - - Output stream to write to. - Blocking factor to apply - A new suitable for output. - - - - Initialization common to all constructors. - - - - - Determine if an archive block indicates End of Archive. End of - archive is indicated by a block that consists entirely of null bytes. - All remaining blocks for the record should also be null's - However some older tars only do a couple of null blocks (Old GNU tar for one) - and also partial records - - The data block to check. - Returns true if the block is an EOF block; false otherwise. - - - - Skip over a block on the input stream. - - - - - Read a block from the input stream. - - - The block of data read. - - - - - Read a record from data stream. - - - false if End-Of-File, else true. - - - - - Get the current block number, within the current record, zero based. - - - The current zero based block number. - - - The absolute block number = (record number * block factor) + block number. - - - - - Get the current record number. - - - The current zero based record number. - - - - - Write a block of data to the archive. - - - The data to write to the archive. - - - - - Write an archive record to the archive, where the record may be - inside of a larger array buffer. The buffer must be "offset plus - record size" long. - - - The buffer containing the record data to write. - - - The offset of the record data within buffer. - - - - - Write a TarBuffer record to the archive. - - - - - Flush the current record if it has any data in it. - - - - - Close the TarBuffer. If this is an output buffer, also flush the - current block before closing. - - - - - Get the record size for this buffer - - The record size in bytes. - This is equal to the multiplied by the - - - - Get the Blocking factor for the buffer - - This is the number of block in each record. - - - - Get the current block number, within the current record, zero based. - - - - - Get the current record number. - - - The current zero based record number. - - - - - This class encapsulates the Tar Entry Header used in Tar Archives. - The class also holds a number of tar constants, used mostly in headers. - - - - - The length of the name field in a header buffer. - - - - - The length of the mode field in a header buffer. - - - - - The length of the user id field in a header buffer. - - - - - The length of the group id field in a header buffer. - - - - - The length of the checksum field in a header buffer. - - - - - Offset of checksum in a header buffer. - - - - - The length of the size field in a header buffer. - - - - - The length of the magic field in a header buffer. - - - - - The length of the version field in a header buffer. - - - - - The length of the modification time field in a header buffer. - - - - - The length of the user name field in a header buffer. - - - - - The length of the group name field in a header buffer. - - - - - The length of the devices field in a header buffer. - - - - - The "old way" of indicating a normal file. - - - - - Normal file type. - - - - - Link file type. - - - - - Symbolic link file type. - - - - - Character device file type. - - - - - Block device file type. - - - - - Directory file type. - - - - - FIFO (pipe) file type. - - - - - Contiguous file type. - - - - - Posix.1 2001 global extended header - - - - - Posix.1 2001 extended header - - - - - Solaris access control list file type - - - - - GNU dir dump file type - This is a dir entry that contains the names of files that were in the - dir at the time the dump was made - - - - - Solaris Extended Attribute File - - - - - Inode (metadata only) no file content - - - - - Identifies the next file on the tape as having a long link name - - - - - Identifies the next file on the tape as having a long name - - - - - Continuation of a file that began on another volume - - - - - For storing filenames that dont fit in the main header (old GNU) - - - - - GNU Sparse file - - - - - GNU Tape/volume header ignore on extraction - - - - - The magic tag representing a POSIX tar archive. (includes trailing NULL) - - - - - The magic tag representing an old GNU tar archive where version is included in magic and overwrites it - - - - - Initialise a default TarHeader instance - - - - - Get the name of this entry. - - The entry's name. - - - - Create a new that is a copy of the current instance. - - A new that is a copy of the current instance. - - - - Parse TarHeader information from a header buffer. - - - The tar entry header buffer to get information from. - - - - - 'Write' header information to buffer provided, updating the check sum. - - output buffer for header information - - - - Get a hash code for the current object. - - A hash code for the current object. - - - - Determines if this instance is equal to the specified object. - - The object to compare with. - true if the objects are equal, false otherwise. - - - - Set defaults for values used when constructing a TarHeader instance. - - Value to apply as a default for userId. - Value to apply as a default for userName. - Value to apply as a default for groupId. - Value to apply as a default for groupName. - - - - Parse an octal string from a header buffer. - - The header buffer from which to parse. - The offset into the buffer from which to parse. - The number of header bytes to parse. - The long equivalent of the octal string. - - - - Parse a name from a header buffer. - - - The header buffer from which to parse. - - - The offset into the buffer from which to parse. - - - The number of header bytes to parse. - - - The name parsed. - - - - - Add name to the buffer as a collection of bytes - - The name to add - The offset of the first character - The buffer to add to - The index of the first byte to add - The number of characters/bytes to add - The next free index in the buffer - - - - Add name to the buffer as a collection of bytes - - The name to add - The offset of the first character - The buffer to add to - The index of the first byte to add - The number of characters/bytes to add - The next free index in the buffer - - - - Add an entry name to the buffer - - - The name to add - - - The buffer to add to - - - The offset into the buffer from which to start adding - - - The number of header bytes to add - - - The index of the next free byte in the buffer - - - - - Add an entry name to the buffer - - The name to add - The buffer to add to - The offset into the buffer from which to start adding - The number of header bytes to add - The index of the next free byte in the buffer - - - - Add a string to a buffer as a collection of ascii bytes. - - The string to add - The offset of the first character to add. - The buffer to add to. - The offset to start adding at. - The number of ascii characters to add. - The next free index in the buffer. - - - - Put an octal representation of a value into a buffer - - - the value to be converted to octal - - - buffer to store the octal string - - - The offset into the buffer where the value starts - - - The length of the octal string to create - - - The offset of the character next byte after the octal string - - - - - Put an octal representation of a value into a buffer - - Value to be convert to octal - The buffer to update - The offset into the buffer to store the value - The length of the octal string - Index of next byte - - - - Add the checksum integer to header buffer. - - - The header buffer to set the checksum for - The offset into the buffer for the checksum - The number of header bytes to update. - It's formatted differently from the other fields: it has 6 digits, a - null, then a space -- rather than digits, a space, then a null. - The final space is already there, from checksumming - - The modified buffer offset - - - - Compute the checksum for a tar entry header. - The checksum field must be all spaces prior to this happening - - The tar entry's header buffer. - The computed checksum. - - - - Make a checksum for a tar entry ignoring the checksum contents. - - The tar entry's header buffer. - The checksum for the buffer - - - - Get/set the name for this tar entry. - - Thrown when attempting to set the property to null. - - - - Get/set the entry's Unix style permission mode. - - - - - The entry's user id. - - - This is only directly relevant to unix systems. - The default is zero. - - - - - Get/set the entry's group id. - - - This is only directly relevant to linux/unix systems. - The default value is zero. - - - - - Get/set the entry's size. - - Thrown when setting the size to less than zero. - - - - Get/set the entry's modification time. - - - The modification time is only accurate to within a second. - - Thrown when setting the date time to less than 1/1/1970. - - - - Get the entry's checksum. This is only valid/updated after writing or reading an entry. - - - - - Get value of true if the header checksum is valid, false otherwise. - - - - - Get/set the entry's type flag. - - - - - The entry's link name. - - Thrown when attempting to set LinkName to null. - - - - Get/set the entry's magic tag. - - Thrown when attempting to set Magic to null. - - - - The entry's version. - - Thrown when attempting to set Version to null. - - - - The entry's user name. - - - - - Get/set the entry's group name. - - - This is only directly relevant to unix systems. - - - - - Get/set the entry's major device number. - - - - - Get/set the entry's minor device number. - - - - - Event arguments for scanning. - - - - - Initialise a new instance of - - The file or directory name. - - - - The fie or directory name for this event. - - - - - Get set a value indicating if scanning should continue or not. - - - - - Event arguments during processing of a single file or directory. - - - - - Initialise a new instance of - - The file or directory name if known. - The number of bytes processed so far - The total number of bytes to process, 0 if not known - - - - The name for this event if known. - - - - - Get set a value indicating wether scanning should continue or not. - - - - - Get a percentage representing how much of the has been processed - - 0.0 to 100.0 percent; 0 if target is not known. - - - - The number of bytes processed so far - - - - - The number of bytes to process. - - Target may be 0 or negative if the value isnt known. - - - - Event arguments for directories. - - - - - Initialize an instance of . - - The name for this directory. - Flag value indicating if any matching files are contained in this directory. - - - - Get a value indicating if the directory contains any matching files or not. - - - - - Arguments passed when scan failures are detected. - - - - - Initialise a new instance of - - The name to apply. - The exception to use. - - - - The applicable name. - - - - - The applicable exception. - - - - - Get / set a value indicating wether scanning should continue. - - - - - Delegate invoked before starting to process a directory. - - - - - Delegate invoked before starting to process a file. - - The source of the event - The event arguments. - - - - Delegate invoked during processing of a file or directory - - The source of the event - The event arguments. - - - - Delegate invoked when a file has been completely processed. - - The source of the event - The event arguments. - - - - Delegate invoked when a directory failure is detected. - - The source of the event - The event arguments. - - - - Delegate invoked when a file failure is detected. - - The source of the event - The event arguments. - - - - FileSystemScanner provides facilities scanning of files and directories. - - - - - Initialise a new instance of - - The file filter to apply when scanning. - - - - Initialise a new instance of - - The file filter to apply. - The directory filter to apply. - - - - Initialise a new instance of - - The file filter to apply. - - - - Initialise a new instance of - - The file filter to apply. - The directory filter to apply. - - - - Delegate to invoke when a directory is processed. - - - - - Delegate to invoke when a file is processed. - - - - - Delegate to invoke when processing for a file has finished. - - - - - Delegate to invoke when a directory failure is detected. - - - - - Delegate to invoke when a file failure is detected. - - - - - Raise the DirectoryFailure event. - - The directory name. - The exception detected. - - - - Raise the FileFailure event. - - The file name. - The exception detected. - - - - Raise the ProcessFile event. - - The file name. - - - - Raise the complete file event - - The file name - - - - Raise the ProcessDirectory event. - - The directory name. - Flag indicating if the directory has matching files. - - - - Scan a directory. - - The base directory to scan. - True to recurse subdirectories, false to scan a single directory. - - - - The file filter currently in use. - - - - - The directory filter currently in use. - - - - - Flag indicating if scanning should continue running. - - - - - An input buffer customised for use by - - - The buffer supports decryption of incoming data. - - - - - Initialise a new instance of with a default buffer size - - The stream to buffer. - - - - Initialise a new instance of - - The stream to buffer. - The size to use for the buffer - A minimum buffer size of 1KB is permitted. Lower sizes are treated as 1KB. - - - - Call passing the current clear text buffer contents. - - The inflater to set input for. - - - - Fill the buffer from the underlying input stream. - - - - - Read a buffer directly from the input stream - - The buffer to fill - Returns the number of bytes read. - - - - Read a buffer directly from the input stream - - The buffer to read into - The offset to start reading data into. - The number of bytes to read. - Returns the number of bytes read. - - - - Read clear text data from the input stream. - - The buffer to add data to. - The offset to start adding data at. - The number of bytes to read. - Returns the number of bytes actually read. - - - - Read a from the input stream. - - Returns the byte read. - - - - Read an in little endian byte order. - - The short value read case to an int. - - - - Read an in little endian byte order. - - The int value read. - - - - Read a in little endian byte order. - - The long value read. - - - - Get the length of bytes bytes in the - - - - - Get the contents of the raw data buffer. - - This may contain encrypted data. - - - - Get the number of useable bytes in - - - - - Get the contents of the clear text buffer. - - - - - Get/set the number of bytes available - - - - - Get/set the to apply to any data. - - Set this value to null to have no transform applied. - - - - The TarOutputStream writes a UNIX tar archive as an OutputStream. - Methods are provided to put entries, and then write their contents - by writing to this stream using write(). - - public - - - - Construct TarOutputStream using default block factor - - stream to write to - - - - Construct TarOutputStream with user specified block factor - - stream to write to - blocking factor - - - - set the position within the current stream - - The offset relative to the to seek to - The to seek from. - The new position in the stream. - - - - Set the length of the current stream - - The new stream length. - - - - Read a byte from the stream and advance the position within the stream - by one byte or returns -1 if at the end of the stream. - - The byte value or -1 if at end of stream - - - - read bytes from the current stream and advance the position within the - stream by the number of bytes read. - - The buffer to store read bytes in. - The index into the buffer to being storing bytes at. - The desired number of bytes to read. - The total number of bytes read, or zero if at the end of the stream. - The number of bytes may be less than the count - requested if data is not avialable. - - - - All buffered data is written to destination - - - - - Ends the TAR archive without closing the underlying OutputStream. - The result is that the EOF block of nulls is written. - - - - - Ends the TAR archive and closes the underlying OutputStream. - - This means that Finish() is called followed by calling the - TarBuffer's Close(). - - - - Get the record size being used by this stream's TarBuffer. - - - The TarBuffer record size. - - - - - Put an entry on the output stream. This writes the entry's - header and positions the output stream for writing - the contents of the entry. Once this method is called, the - stream is ready for calls to write() to write the entry's - contents. Once the contents are written, closeEntry() - MUST be called to ensure that all buffered data - is completely written to the output stream. - - - The TarEntry to be written to the archive. - - - - - Close an entry. This method MUST be called for all file - entries that contain data. The reason is that we must - buffer data written to the stream in order to satisfy - the buffer's block based writes. Thus, there may be - data fragments still being assembled that must be written - to the output stream before this entry is closed and the - next entry written. - - - - - Writes a byte to the current tar archive entry. - This method simply calls Write(byte[], int, int). - - - The byte to be written. - - - - - Writes bytes to the current tar archive entry. This method - is aware of the current entry and will throw an exception if - you attempt to write bytes past the length specified for the - current entry. The method is also (painfully) aware of the - record buffering required by TarBuffer, and manages buffers - that are not a multiple of recordsize in length, including - assembling records from small buffers. - - - The buffer to write to the archive. - - - The offset in the buffer from which to get bytes. - - - The number of bytes to write. - - - - - Write an EOF (end of archive) block to the tar archive. - An EOF block consists of all zeros. - - - - - bytes written for this entry so far - - - - - current 'Assembly' buffer length - - - - - Flag indicating wether this instance has been closed or not. - - - - - Size for the current entry - - - - - single block working buffer - - - - - 'Assembly' buffer used to assemble data before writing - - - - - TarBuffer used to provide correct blocking factor - - - - - the destination stream for the archive contents - - - - - true if the stream supports reading; otherwise, false. - - - - - true if the stream supports seeking; otherwise, false. - - - - - true if stream supports writing; otherwise, false. - - - - - length of stream in bytes - - - - - gets or sets the position within the current stream. - - - - - Get the record size being used by this stream's TarBuffer. - - - - - Get a value indicating wether an entry is open, requiring more data to be written. - - - - - This is the Deflater class. The deflater class compresses input - with the deflate algorithm described in RFC 1951. It has several - compression levels and three different strategies described below. - - This class is not thread safe. This is inherent in the API, due - to the split of deflate and setInput. - - author of the original java version : Jochen Hoenicke - - - - - The best and slowest compression level. This tries to find very - long and distant string repetitions. - - - - - The worst but fastest compression level. - - - - - The default compression level. - - - - - This level won't compress at all but output uncompressed blocks. - - - - - The compression method. This is the only method supported so far. - There is no need to use this constant at all. - - - - - Creates a new deflater with default compression level. - - - - - Creates a new deflater with given compression level. - - - the compression level, a value between NO_COMPRESSION - and BEST_COMPRESSION, or DEFAULT_COMPRESSION. - - if lvl is out of range. - - - - Creates a new deflater with given compression level. - - - the compression level, a value between NO_COMPRESSION - and BEST_COMPRESSION. - - - true, if we should suppress the Zlib/RFC1950 header at the - beginning and the adler checksum at the end of the output. This is - useful for the GZIP/PKZIP formats. - - if lvl is out of range. - - - - Resets the deflater. The deflater acts afterwards as if it was - just created with the same compression level and strategy as it - had before. - - - - - Flushes the current input block. Further calls to deflate() will - produce enough output to inflate everything in the current input - block. This is not part of Sun's JDK so I have made it package - private. It is used by DeflaterOutputStream to implement - flush(). - - - - - Finishes the deflater with the current input block. It is an error - to give more input after this method was called. This method must - be called to force all bytes to be flushed. - - - - - Sets the data which should be compressed next. This should be only - called when needsInput indicates that more input is needed. - If you call setInput when needsInput() returns false, the - previous input that is still pending will be thrown away. - The given byte array should not be changed, before needsInput() returns - true again. - This call is equivalent to setInput(input, 0, input.length). - - - the buffer containing the input data. - - - if the buffer was finished() or ended(). - - - - - Sets the data which should be compressed next. This should be - only called when needsInput indicates that more input is needed. - The given byte array should not be changed, before needsInput() returns - true again. - - - the buffer containing the input data. - - - the start of the data. - - - the number of data bytes of input. - - - if the buffer was Finish()ed or if previous input is still pending. - - - - - Sets the compression level. There is no guarantee of the exact - position of the change, but if you call this when needsInput is - true the change of compression level will occur somewhere near - before the end of the so far given input. - - - the new compression level. - - - - - Get current compression level - - Returns the current compression level - - - - Sets the compression strategy. Strategy is one of - DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact - position where the strategy is changed, the same as for - SetLevel() applies. - - - The new compression strategy. - - - - - Deflates the current input block with to the given array. - - - The buffer where compressed data is stored - - - The number of compressed bytes added to the output, or 0 if either - IsNeedingInput() or IsFinished returns true or length is zero. - - - - - Deflates the current input block to the given array. - - - Buffer to store the compressed data. - - - Offset into the output array. - - - The maximum number of bytes that may be stored. - - - The number of compressed bytes added to the output, or 0 if either - needsInput() or finished() returns true or length is zero. - - - If Finish() was previously called. - - - If offset or length don't match the array length. - - - - - Sets the dictionary which should be used in the deflate process. - This call is equivalent to setDictionary(dict, 0, dict.Length). - - - the dictionary. - - - if SetInput () or Deflate () were already called or another dictionary was already set. - - - - - Sets the dictionary which should be used in the deflate process. - The dictionary is a byte array containing strings that are - likely to occur in the data which should be compressed. The - dictionary is not stored in the compressed output, only a - checksum. To decompress the output you need to supply the same - dictionary again. - - - The dictionary data - - - The index where dictionary information commences. - - - The number of bytes in the dictionary. - - - If SetInput () or Deflate() were already called or another dictionary was already set. - - - - - Compression level. - - - - - If true no Zlib/RFC1950 headers or footers are generated - - - - - The current state. - - - - - The total bytes of output written. - - - - - The pending output. - - - - - The deflater engine. - - - - - Gets the current adler checksum of the data that was processed so far. - - - - - Gets the number of input bytes processed so far. - - - - - Gets the number of output bytes so far. - - - - - Returns true if the stream was finished and no more output bytes - are available. - - - - - Returns true, if the input buffer is empty. - You should then call setInput(). - NOTE: This method can also return true when the stream - was finished. - - - - - The TarInputStream reads a UNIX tar archive as an InputStream. - methods are provided to position at each successive entry in - the archive, and the read each entry as a normal input stream - using read(). - - - - - Construct a TarInputStream with default block factor - - stream to source data from - - - - Construct a TarInputStream with user specified block factor - - stream to source data from - block factor to apply to archive - - - - Flushes the baseInputStream - - - - - Set the streams position. This operation is not supported and will throw a NotSupportedException - - The offset relative to the origin to seek to. - The to start seeking from. - The new position in the stream. - Any access - - - - Sets the length of the stream - This operation is not supported and will throw a NotSupportedException - - The new stream length. - Any access - - - - Writes a block of bytes to this stream using data from a buffer. - This operation is not supported and will throw a NotSupportedException - - The buffer containing bytes to write. - The offset in the buffer of the frist byte to write. - The number of bytes to write. - Any access - - - - Writes a byte to the current position in the file stream. - This operation is not supported and will throw a NotSupportedException - - The byte value to write. - Any access - - - - Reads a byte from the current tar archive entry. - - A byte cast to an int; -1 if the at the end of the stream. - - - - Reads bytes from the current tar archive entry. - - This method is aware of the boundaries of the current - entry in the archive and will deal with them appropriately - - - The buffer into which to place bytes read. - - - The offset at which to place bytes read. - - - The number of bytes to read. - - - The number of bytes read, or 0 at end of stream/EOF. - - - - - Closes this stream. Calls the TarBuffer's close() method. - The underlying stream is closed by the TarBuffer. - - - - - Set the entry factory for this instance. - - The factory for creating new entries - - - - Get the record size being used by this stream's TarBuffer. - - - TarBuffer record size. - - - - - Skip bytes in the input buffer. This skips bytes in the - current entry's data, not the entire archive, and will - stop at the end of the current entry's data if the number - to skip extends beyond that point. - - - The number of bytes to skip. - - - - - Since we do not support marking just yet, we do nothing. - - - The limit to mark. - - - - - Since we do not support marking just yet, we do nothing. - - - - - Get the next entry in this tar archive. This will skip - over any remaining data in the current entry, if there - is one, and place the input stream at the header of the - next entry, and read the header and instantiate a new - TarEntry from the header bytes and return that entry. - If there are no more entries in the archive, null will - be returned to indicate that the end of the archive has - been reached. - - - The next TarEntry in the archive, or null. - - - - - Copies the contents of the current tar archive entry directly into - an output stream. - - - The OutputStream into which to write the entry's data. - - - - - Flag set when last block has been read - - - - - Size of this entry as recorded in header - - - - - Number of bytes read for this entry so far - - - - - Buffer used with calls to Read() - - - - - Working buffer - - - - - Current entry being read - - - - - Factory used to create TarEntry or descendant class instance - - - - - Stream used as the source of input data. - - - - - Gets a value indicating whether the current stream supports reading - - - - - Gets a value indicating whether the current stream supports seeking - This property always returns false. - - - - - Gets a value indicating if the stream supports writing. - This property always returns false. - - - - - The length in bytes of the stream - - - - - Gets or sets the position within the stream. - Setting the Position is not supported and throws a NotSupportedExceptionNotSupportedException - - Any attempt to set position - - - - Get the record size being used by this stream's TarBuffer. - - - - - Get the available data that can be read from the current - entry in the archive. This does not indicate how much data - is left in the entire archive, only in the current entry. - This value is determined from the entry's size header field - and the amount of data already read from the current entry. - - - The number of available bytes for the current entry. - - - - - Return a value of true if marking is supported; false otherwise. - - Currently marking is not supported, the return value is always false. - - - - This interface is provided, along with the method , to allow - the programmer to have their own subclass instantiated for the - entries return from . - - - - - Create an entry based on name alone - - - Name of the new EntryPointNotFoundException to create - - created TarEntry or descendant class - - - - Create an instance based on an actual file - - - Name of file to represent in the entry - - - Created TarEntry or descendant class - - - - - Create a tar entry based on the header information passed - - - Buffer containing header information to base entry on - - - Created TarEntry or descendant class - - - - - Standard entry factory class creating instances of the class TarEntry - - - - - Create a based on named - - The name to use for the entry - A new - - - - Create a tar entry with details obtained from file - - The name of the file to retrieve details from. - A new - - - - Create an entry based on details in header - - The buffer containing entry details. - A new - - - - Defines known values for the property. - - - - - Host system = MSDOS - - - - - Host system = Amiga - - - - - Host system = Open VMS - - - - - Host system = Unix - - - - - Host system = VMCms - - - - - Host system = Atari ST - - - - - Host system = OS2 - - - - - Host system = Macintosh - - - - - Host system = ZSystem - - - - - Host system = Cpm - - - - - Host system = Windows NT - - - - - Host system = MVS - - - - - Host system = VSE - - - - - Host system = Acorn RISC - - - - - Host system = VFAT - - - - - Host system = Alternate MVS - - - - - Host system = BEOS - - - - - Host system = Tandem - - - - - Host system = OS400 - - - - - Host system = OSX - - - - - Host system = WinZIP AES - - - - - This class represents an entry in a zip archive. This can be a file - or a directory - ZipFile and ZipInputStream will give you instances of this class as - information about the members in an archive. ZipOutputStream - uses an instance of this class when creating an entry in a Zip file. -
-
Author of the original java version : Jochen Hoenicke -
-
- - - Creates a zip entry with the given name. - - - The name for this entry. Can include directory components. - The convention for names is 'unix' style paths with relative names only. - There are with no device names and path elements are separated by '/' characters. - - - The name passed is null - - - - - Creates a zip entry with the given name and version required to extract - - - The name for this entry. Can include directory components. - The convention for names is 'unix' style paths with no device names and - path elements separated by '/' characters. This is not enforced see CleanName - on how to ensure names are valid if this is desired. - - - The minimum 'feature version' required this entry - - - The name passed is null - - - - - Initializes an entry with the given name and made by information - - Name for this entry - Version and HostSystem Information - Minimum required zip feature version required to extract this entry - Compression method for this entry. - - The name passed is null - - - versionRequiredToExtract should be 0 (auto-calculate) or > 10 - - - This constructor is used by the ZipFile class when reading from the central header - It is not generally useful, use the constructor specifying the name only. - - - - - Creates a deep copy of the given zip entry. - - - The entry to copy. - - - - - Test the external attributes for this to - see if the external attributes are Dos based (including WINNT and variants) - and match the values - - The attributes to test. - Returns true if the external attributes are known to be DOS/Windows - based and have the same attributes set as the value passed. - - - - Force this entry to be recorded using Zip64 extensions. - - - - - Get a value indicating wether Zip64 extensions were forced. - - A value of true if Zip64 extensions have been forced on; false if not. - - - - Process extra data fields updating the entry based on the contents. - - True if the extra data fields should be handled - for a local header, rather than for a central header. - - - - - Test entry to see if data can be extracted. - - Returns true if data can be extracted for this entry; false otherwise. - - - - Creates a copy of this zip entry. - - An that is a copy of the current instance. - - - - Gets a string representation of this ZipEntry. - - A readable textual representation of this - - - - Test a compression method to see if this library - supports extracting data compressed with that method - - The compression method to test. - Returns true if the compression method is supported; false otherwise - - - - Cleans a name making it conform to Zip file conventions. - Devices names ('c:\') and UNC share names ('\\server\share') are removed - and forward slashes ('\') are converted to back slashes ('/'). - Names are made relative by trimming leading slashes which is compatible - with the ZIP naming convention. - - The name to clean - The 'cleaned' name. - - The Zip name transform class is more flexible. - - - - - Get a value indicating wether the entry has a CRC value available. - - - - - Get/Set flag indicating if entry is encrypted. - A simple helper routine to aid interpretation of flags - - This is an assistant that interprets the flags property. - - - - Get / set a flag indicating wether entry name and comment text are - encoded in unicode UTF8. - - This is an assistant that interprets the flags property. - - - - Value used during password checking for PKZIP 2.0 / 'classic' encryption. - - - - - Get/Set general purpose bit flag for entry - - - General purpose bit flag
-
- Bit 0: If set, indicates the file is encrypted
- Bit 1-2 Only used for compression type 6 Imploding, and 8, 9 deflating
- Imploding:
- Bit 1 if set indicates an 8K sliding dictionary was used. If clear a 4k dictionary was used
- Bit 2 if set indicates 3 Shannon-Fanno trees were used to encode the sliding dictionary, 2 otherwise
-
- Deflating:
- Bit 2 Bit 1
- 0 0 Normal compression was used
- 0 1 Maximum compression was used
- 1 0 Fast compression was used
- 1 1 Super fast compression was used
-
- Bit 3: If set, the fields crc-32, compressed size - and uncompressed size are were not able to be written during zip file creation - The correct values are held in a data descriptor immediately following the compressed data.
- Bit 4: Reserved for use by PKZIP for enhanced deflating
- Bit 5: If set indicates the file contains compressed patch data
- Bit 6: If set indicates strong encryption was used.
- Bit 7-10: Unused or reserved
- Bit 11: If set the name and comments for this entry are in unicode.
- Bit 12-15: Unused or reserved
-
- - -
- - - Get/Set index of this entry in Zip file - - This is only valid when the entry is part of a - - - - Get/set offset for use in central header - - - - - Get/Set external file attributes as an integer. - The values of this are operating system dependant see - HostSystem for details - - - - - Get the version made by for this entry or zero if unknown. - The value / 10 indicates the major version number, and - the value mod 10 is the minor version number - - - - - Get a value indicating this entry is for a DOS/Windows system. - - - - - Gets the compatability information for the external file attribute - If the external file attributes are compatible with MS-DOS and can be read - by PKZIP for DOS version 2.04g then this value will be zero. Otherwise the value - will be non-zero and identify the host system on which the attributes are compatible. - - - - The values for this as defined in the Zip File format and by others are shown below. The values are somewhat - misleading in some cases as they are not all used as shown. You should consult the relevant documentation - to obtain up to date and correct information. The modified appnote by the infozip group is - particularly helpful as it documents a lot of peculiarities. The document is however a little dated. - - 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) - 1 - Amiga - 2 - OpenVMS - 3 - Unix - 4 - VM/CMS - 5 - Atari ST - 6 - OS/2 HPFS - 7 - Macintosh - 8 - Z-System - 9 - CP/M - 10 - Windows NTFS - 11 - MVS (OS/390 - Z/OS) - 12 - VSE - 13 - Acorn Risc - 14 - VFAT - 15 - Alternate MVS - 16 - BeOS - 17 - Tandem - 18 - OS/400 - 19 - OS/X (Darwin) - 99 - WinZip AES - remainder - unused - - - - - - Get minimum Zip feature version required to extract this entry - - - Minimum features are defined as:
- 1.0 - Default value
- 1.1 - File is a volume label
- 2.0 - File is a folder/directory
- 2.0 - File is compressed using Deflate compression
- 2.0 - File is encrypted using traditional encryption
- 2.1 - File is compressed using Deflate64
- 2.5 - File is compressed using PKWARE DCL Implode
- 2.7 - File is a patch data set
- 4.5 - File uses Zip64 format extensions
- 4.6 - File is compressed using BZIP2 compression
- 5.0 - File is encrypted using DES
- 5.0 - File is encrypted using 3DES
- 5.0 - File is encrypted using original RC2 encryption
- 5.0 - File is encrypted using RC4 encryption
- 5.1 - File is encrypted using AES encryption
- 5.1 - File is encrypted using corrected RC2 encryption
- 5.1 - File is encrypted using corrected RC2-64 encryption
- 6.1 - File is encrypted using non-OAEP key wrapping
- 6.2 - Central directory encryption (not confirmed yet)
- 6.3 - File is compressed using LZMA
- 6.3 - File is compressed using PPMD+
- 6.3 - File is encrypted using Blowfish
- 6.3 - File is encrypted using Twofish
-
- -
- - - Get a value indicating wether this entry can be decompressed by the library. - - This is based on the and - wether the compression method is supported. - - - - Gets a value indicating if the entry requires Zip64 extensions - to store the full entry values. - - A value of true if a local header requires Zip64 extensions; false if not. - - - - Get a value indicating wether the central directory entry requires Zip64 extensions to be stored. - - - - - Get/Set DosTime value. - - - The MS-DOS date format can only represent dates between 1/1/1980 and 12/31/2107. - - - - - Gets/Sets the time of last modification of the entry. - - - The property is updated to match this as far as possible. - - - - - Returns the entry name. - - - The unix naming convention is followed. - Path components in the entry should always separated by forward slashes ('/'). - Dos device names like C: should also be removed. - See the class, or - - - - - Gets/Sets the size of the uncompressed data. - - - The size or -1 if unknown. - - Setting the size before adding an entry to an archive can help - avoid compatability problems with some archivers which dont understand Zip64 extensions. - - - - Gets/Sets the size of the compressed data. - - - The compressed entry size or -1 if unknown. - - - - - Gets/Sets the crc of the uncompressed data. - - - Crc is not in the range 0..0xffffffffL - - - The crc value or -1 if unknown. - - - - - Gets/Sets the compression method. Only Deflated and Stored are supported. - - - The compression method for this entry - - - - - - - Gets/Sets the extra data. - - - Extra data is longer than 64KB (0xffff) bytes. - - - Extra data or null if not set. - - - - - Gets/Sets the entry comment. - - - If comment is longer than 0xffff. - - - The comment or null if not set. - - - A comment is only available for entries when read via the class. - The class doesnt have the comment data available. - - - - - Gets a value indicating if the entry is a directory. - however. - - - A directory is determined by an entry name with a trailing slash '/'. - The external file attributes can also indicate an entry is for a directory. - Currently only dos/windows attributes are tested in this manner. - The trailing slash convention should always be followed. - - - - - Get a value of true if the entry appears to be a file; false otherwise - - - This only takes account of DOS/Windows attributes. Other operating systems are ignored. - For linux and others the result may be incorrect. - - - - - ExtraData tagged value interface. - - - - - Set the contents of this instance from the data passed. - - The data to extract contents from. - The offset to begin extracting data from. - The number of bytes to extract. - - - - Get the data representing this instance. - - Returns the data for this instance. - - - - Get the ID for this tagged data value. - - - - - A raw binary tagged value - - - - - Initialise a new instance. - - The tag ID. - - - - Set the data from the raw values provided. - - The raw data to extract values from. - The index to start extracting values from. - The number of bytes available. - - - - Get the binary data representing this instance. - - The raw binary data representing this instance. - - - - The tag ID for this instance. - - - - - Get the ID for this tagged data value. - - - - - Get /set the binary data representing this instance. - - The raw binary data representing this instance. - - - - Class representing extended unix date time values. - - - - - Set the data from the raw values provided. - - The raw data to extract values from. - The index to start extracting values from. - The number of bytes available. - - - - Get the binary data representing this instance. - - The raw binary data representing this instance. - - - - Test a value to see if is valid and can be represented here. - - The value to test. - Returns true if the value is valid and can be represented; false if not. - The standard Unix time is a signed integer data type, directly encoding the Unix time number, - which is the number of seconds since 1970-01-01. - Being 32 bits means the values here cover a range of about 136 years. - The minimum representable time is 1901-12-13 20:45:52, - and the maximum representable time is 2038-01-19 03:14:07. - - - - - Get the ID - - - - - Get /set the Modification Time - - - - - - - Get / set the Access Time - - - - - - - Get / Set the Create Time - - - - - - - Get/set the values to include. - - - - - Flags indicate which values are included in this instance. - - - - - The modification time is included - - - - - The access time is included - - - - - The create time is included. - - - - - Class handling NT date time values. - - - - - Set the data from the raw values provided. - - The raw data to extract values from. - The index to start extracting values from. - The number of bytes available. - - - - Get the binary data representing this instance. - - The raw binary data representing this instance. - - - - Test a valuie to see if is valid and can be represented here. - - The value to test. - Returns true if the value is valid and can be represented; false if not. - - NTFS filetimes are 64-bit unsigned integers, stored in Intel - (least significant byte first) byte order. They determine the - number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", - which is "01-Jan-1601 00:00:00 UTC". 28 May 60056 is the upper limit - - - - - Get the ID for this tagged data value. - - - - - Get/set the last modification time. - - - - - Get /set the create time - - - - - Get /set the last access time. - - - - - A factory that creates tagged data instances. - - - - - Get data for a specific tag value. - - The tag ID to find. - The data to search. - The offset to begin extracting data from. - The number of bytes to extract. - The located value found, or null if not found. - - - - - A class to handle the extra data field for Zip entries - - - Extra data contains 0 or more values each prefixed by a header tag and length. - They contain zero or more bytes of actual data. - The data is held internally using a copy on write strategy. This is more efficient but - means that for extra data created by passing in data can have the values modified by the caller - in some circumstances. - - - - - Initialise a default instance. - - - - - Initialise with known extra data. - - The extra data. - - - - Get the raw extra data value - - Returns the raw byte[] extra data this instance represents. - - - - Clear the stored data. - - - - - Get a read-only for the associated tag. - - The tag to locate data for. - Returns a containing tag data or null if no tag was found. - - - - Get the tagged data for a tag. - - The tag to search for. - Returns a tagged value or null if none found. - - - - Find an extra data value - - The identifier for the value to find. - Returns true if the value was found; false otherwise. - - - - Add a new entry to extra data. - - The value to add. - - - - Add a new entry to extra data - - The ID for this entry. - The data to add. - If the ID already exists its contents are replaced. - - - - Start adding a new entry. - - Add data using , , , or . - The new entry is completed and actually added by calling - - - - - Add entry data added since using the ID passed. - - The identifier to use for this entry. - - - - Add a byte of data to the pending new entry. - - The byte to add. - - - - - Add data to a pending new entry. - - The data to add. - - - - - Add a short value in little endian order to the pending new entry. - - The data to add. - - - - - Add an integer value in little endian order to the pending new entry. - - The data to add. - - - - - Add a long value in little endian order to the pending new entry. - - The data to add. - - - - - Delete an extra data field. - - The identifier of the field to delete. - Returns true if the field was found and deleted. - - - - Read a long in little endian form from the last found data value - - Returns the long value read. - - - - Read an integer in little endian form from the last found data value. - - Returns the integer read. - - - - Read a short value in little endian form from the last found data value. - - Returns the short value read. - - - - Read a byte from an extra data - - The byte value read or -1 if the end of data has been reached. - - - - Skip data during reading. - - The number of bytes to skip. - - - - Internal form of that reads data at any location. - - Returns the short value read. - - - - Dispose of this instance. - - - - - Gets the current extra data length. - - - - - Get the length of the last value found by - - This is only value if has previsouly returned true. - - - - Get the index for the current read value. - - This is only valid if has previously returned true. - Initially it will be the index of the first byte of actual data. The value is updated after calls to - , and . - - - - Get the number of bytes remaining to be read for the current value; - - - - - Holds data pertinent to a data descriptor. - - - - - Get /set the compressed size of data. - - - - - Get / set the uncompressed size of data - - - - - Get /set the crc value. - - - - - This class assists with writing/reading from Zip files. - - - - - Initialise an instance of this class. - - The name of the file to open. - - - - Initialise a new instance of . - - The stream to use. - - - - Close the stream. - - - The underlying stream is closed only if is true. - - - - - Locates a block with the desired . - - The signature to find. - Location, marking the end of block. - Minimum size of the block. - The maximum variable data. - Eeturns the offset of the first byte after the signature; -1 if not found - - - - Write Zip64 end of central directory records (File header and locator). - - The number of entries in the central directory. - The size of entries in the central directory. - The offset of the dentral directory. - - - - Write the required records to end the central directory. - - The number of entries in the directory. - The size of the entries in the directory. - The start of the central directory. - The archive comment. (This can be null). - - - - Read an unsigned short in little endian byte order. - - Returns the value read. - - An i/o error occurs. - - - The file ends prematurely - - - - - Read an int in little endian byte order. - - Returns the value read. - - An i/o error occurs. - - - The file ends prematurely - - - - - Read a long in little endian byte order. - - The value read. - - - - Write an unsigned short in little endian byte order. - - The value to write. - - - - Write a ushort in little endian byte order. - - The value to write. - - - - Write an int in little endian byte order. - - The value to write. - - - - Write a uint in little endian byte order. - - The value to write. - - - - Write a long in little endian byte order. - - The value to write. - - - - Write a ulong in little endian byte order. - - The value to write. - - - - Write a data descriptor. - - The entry to write a descriptor for. - Returns the number of descriptor bytes written. - - - - Read data descriptor at the end of compressed data. - - if set to true [zip64]. - The data to fill in. - Returns the number of bytes read in the descriptor. - - - - Get / set a value indicating wether the the underlying stream is owned or not. - - If the stream is owned it is closed when this instance is closed. - - - - Inflater is used to decompress data that has been compressed according - to the "deflate" standard described in rfc1951. - - By default Zlib (rfc1950) headers and footers are expected in the input. - You can use constructor public Inflater(bool noHeader) passing true - if there is no Zlib header information - - The usage is as following. First you have to set some input with - SetInput(), then Inflate() it. If inflate doesn't - inflate any bytes there may be three reasons: -
    -
  • IsNeedingInput() returns true because the input buffer is empty. - You have to provide more input with SetInput(). - NOTE: IsNeedingInput() also returns true when, the stream is finished. -
  • -
  • IsNeedingDictionary() returns true, you have to provide a preset - dictionary with SetDictionary().
  • -
  • IsFinished returns true, the inflater has finished.
  • -
- Once the first output byte is produced, a dictionary will not be - needed at a later stage. - - author of the original java version : John Leuner, Jochen Hoenicke -
-
- - - These are the possible states for an inflater - - - - - Copy lengths for literal codes 257..285 - - - - - Extra bits for literal codes 257..285 - - - - - Copy offsets for distance codes 0..29 - - - - - Extra bits for distance codes - - - - - This variable contains the current state. - - - - - The adler checksum of the dictionary or of the decompressed - stream, as it is written in the header resp. footer of the - compressed stream. - Only valid if mode is DECODE_DICT or DECODE_CHKSUM. - - - - - The number of bits needed to complete the current state. This - is valid, if mode is DECODE_DICT, DECODE_CHKSUM, - DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. - - - - - True, if the last block flag was set in the last block of the - inflated stream. This means that the stream ends after the - current block. - - - - - The total number of inflated bytes. - - - - - The total number of bytes set with setInput(). This is not the - value returned by the TotalIn property, since this also includes the - unprocessed input. - - - - - This variable stores the noHeader flag that was given to the constructor. - True means, that the inflated stream doesn't contain a Zlib header or - footer. - - - - - Creates a new inflater or RFC1951 decompressor - RFC1950/Zlib headers and footers will be expected in the input data - - - - - Creates a new inflater. - - - True if no RFC1950/Zlib header and footer fields are expected in the input data - - This is used for GZIPed/Zipped input. - - For compatibility with - Sun JDK you should provide one byte of input more than needed in - this case. - - - - - Resets the inflater so that a new stream can be decompressed. All - pending input and output will be discarded. - - - - - Decodes a zlib/RFC1950 header. - - - False if more input is needed. - - - The header is invalid. - - - - - Decodes the dictionary checksum after the deflate header. - - - False if more input is needed. - - - - - Decodes the huffman encoded symbols in the input stream. - - - false if more input is needed, true if output window is - full or the current block ends. - - - if deflated stream is invalid. - - - - - Decodes the adler checksum after the deflate stream. - - - false if more input is needed. - - - If checksum doesn't match. - - - - - Decodes the deflated stream. - - - false if more input is needed, or if finished. - - - if deflated stream is invalid. - - - - - Sets the preset dictionary. This should only be called, if - needsDictionary() returns true and it should set the same - dictionary, that was used for deflating. The getAdler() - function returns the checksum of the dictionary needed. - - - The dictionary. - - - - - Sets the preset dictionary. This should only be called, if - needsDictionary() returns true and it should set the same - dictionary, that was used for deflating. The getAdler() - function returns the checksum of the dictionary needed. - - - The dictionary. - - - The index into buffer where the dictionary starts. - - - The number of bytes in the dictionary. - - - No dictionary is needed. - - - The adler checksum for the buffer is invalid - - - - - Sets the input. This should only be called, if needsInput() - returns true. - - - the input. - - - - - Sets the input. This should only be called, if needsInput() - returns true. - - - The source of input data - - - The index into buffer where the input starts. - - - The number of bytes of input to use. - - - No input is needed. - - - The index and/or count are wrong. - - - - - Inflates the compressed stream to the output buffer. If this - returns 0, you should check, whether IsNeedingDictionary(), - IsNeedingInput() or IsFinished() returns true, to determine why no - further output is produced. - - - the output buffer. - - - The number of bytes written to the buffer, 0 if no further - output can be produced. - - - if buffer has length 0. - - - if deflated stream is invalid. - - - - - Inflates the compressed stream to the output buffer. If this - returns 0, you should check, whether needsDictionary(), - needsInput() or finished() returns true, to determine why no - further output is produced. - - - the output buffer. - - - the offset in buffer where storing starts. - - - the maximum number of bytes to output. - - - the number of bytes written to the buffer, 0 if no further output can be produced. - - - if count is less than 0. - - - if the index and / or count are wrong. - - - if deflated stream is invalid. - - - - - Returns true, if the input buffer is empty. - You should then call setInput(). - NOTE: This method also returns true when the stream is finished. - - - - - Returns true, if a preset dictionary is needed to inflate the input. - - - - - Returns true, if the inflater has finished. This means, that no - input is needed and no output can be produced. - - - - - Gets the adler checksum. This is either the checksum of all - uncompressed bytes returned by inflate(), or if needsDictionary() - returns true (and thus no output was yet produced) this is the - adler checksum of the expected dictionary. - - - the adler checksum. - - - - - Gets the total number of output bytes returned by Inflate(). - - - the total number of output bytes. - - - - - Gets the total number of processed compressed input bytes. - - - The total number of bytes of processed input bytes. - - - - - Gets the number of unprocessed input bytes. Useful, if the end of the - stream is reached and you want to further process the bytes after - the deflate stream. - - - The number of bytes of the input which have not been processed. - - - - - An input stream that decompresses files in the BZip2 format - - - - - Construct instance for reading from stream - - Data source - - - - Flushes the stream. - - - - - Set the streams position. This operation is not supported and will throw a NotSupportedException - - A byte offset relative to the parameter. - A value of type indicating the reference point used to obtain the new position. - The new position of the stream. - Any access - - - - Sets the length of this stream to the given value. - This operation is not supported and will throw a NotSupportedExceptionortedException - - The new length for the stream. - Any access - - - - Writes a block of bytes to this stream using data from a buffer. - This operation is not supported and will throw a NotSupportedException - - The buffer to source data from. - The offset to start obtaining data from. - The number of bytes of data to write. - Any access - - - - Writes a byte to the current position in the file stream. - This operation is not supported and will throw a NotSupportedException - - The value to write. - Any access - - - - Read a sequence of bytes and advances the read position by one byte. - - Array of bytes to store values in - Offset in array to begin storing data - The maximum number of bytes to read - The total number of bytes read into the buffer. This might be less - than the number of bytes requested if that number of bytes are not - currently available or zero if the end of the stream is reached. - - - - - Closes the stream, releasing any associated resources. - - - - - Read a byte from stream advancing position - - byte read or -1 on end of stream - - - - Get/set flag indicating ownership of underlying stream. - When the flag is true will close the underlying stream also. - - - - - Gets a value indicating if the stream supports reading - - - - - Gets a value indicating whether the current stream supports seeking. - - - - - Gets a value indicating whether the current stream supports writing. - This property always returns false - - - - - Gets the length in bytes of the stream. - - - - - Gets or sets the streams position. - Setting the position is not supported and will throw a NotSupportException - - Any attempt to set the position - - - - Computes Adler32 checksum for a stream of data. An Adler32 - checksum is not as reliable as a CRC32 checksum, but a lot faster to - compute. - - The specification for Adler32 may be found in RFC 1950. - ZLIB Compressed Data Format Specification version 3.3) - - - From that document: - - "ADLER32 (Adler-32 checksum) - This contains a checksum value of the uncompressed data - (excluding any dictionary data) computed according to Adler-32 - algorithm. This algorithm is a 32-bit extension and improvement - of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 - standard. - - Adler-32 is composed of two sums accumulated per byte: s1 is - the sum of all bytes, s2 is the sum of all s1 values. Both sums - are done modulo 65521. s1 is initialized to 1, s2 to zero. The - Adler-32 checksum is stored as s2*65536 + s1 in most- - significant-byte first (network) order." - - "8.2. The Adler-32 algorithm - - The Adler-32 algorithm is much faster than the CRC32 algorithm yet - still provides an extremely low probability of undetected errors. - - The modulo on unsigned long accumulators can be delayed for 5552 - bytes, so the modulo operation time is negligible. If the bytes - are a, b, c, the second sum is 3a + 2b + c + 3, and so is position - and order sensitive, unlike the first sum, which is just a - checksum. That 65521 is prime is important to avoid a possible - large class of two-byte errors that leave the check unchanged. - (The Fletcher checksum uses 255, which is not prime and which also - makes the Fletcher check insensitive to single byte changes 0 - - 255.) - - The sum s1 is initialized to 1 instead of zero to make the length - of the sequence part of s2, so that the length does not have to be - checked separately. (Any sequence of zeroes has a Fletcher - checksum of zero.)" - - - - - - - largest prime smaller than 65536 - - - - - Creates a new instance of the Adler32 class. - The checksum starts off with a value of 1. - - - - - Resets the Adler32 checksum to the initial value. - - - - - Updates the checksum with a byte value. - - - The data value to add. The high byte of the int is ignored. - - - - - Updates the checksum with an array of bytes. - - - The source of the data to update with. - - - - - Updates the checksum with the bytes taken from the array. - - - an array of bytes - - - the start of the data used for this update - - - the number of bytes to use for this update - - - - - Returns the Adler32 data checksum computed so far. - - -
-
diff --git a/bin/Org.Mentalis.Security.dll b/bin/Org.Mentalis.Security.dll deleted file mode 100644 index bac39dd..0000000 Binary files a/bin/Org.Mentalis.Security.dll and /dev/null differ diff --git a/bin/Tamir.SharpSSH.dll b/bin/Tamir.SharpSSH.dll deleted file mode 100644 index c2f67a8..0000000 Binary files a/bin/Tamir.SharpSSH.dll and /dev/null differ diff --git a/bin/Winterdom.IO.FileMap.dll b/bin/Winterdom.IO.FileMap.dll deleted file mode 100644 index f3965d6..0000000 Binary files a/bin/Winterdom.IO.FileMap.dll and /dev/null differ -- cgit v1.1 From 5b6485481bbabc2cbe37af00fe55656c12db4b9e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 11:02:09 -0700 Subject: Add extra Gitminster config options to ini.example --- bin/OpenSim.ini.example | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 6fdfcf2..a71fe72 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -887,6 +887,13 @@ Enabled = true RepoPath = "git" +;How many frames between the scheduled commits? +CommitFrameInterval = 360000 + +;Should we automatically commit when necessary to avoid objects never making it into the repo? +UseSafetyCommit = true + + [SVN] Enabled = false Directory = SVNmodule\repo -- cgit v1.1 From 70d3b9aecaf5bf2447b43a1359c631eb60ca66aa Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 11:14:58 -0700 Subject: Add a DeleteAllSceneObjects(bool exceptNoCopy) method to allow NoCopy objects to be retained when the scene is cleared. --- OpenSim/Region/Framework/Scenes/Scene.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index dc58d84..c596baa 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2183,6 +2183,14 @@ namespace OpenSim.Region.Framework.Scenes ///
public void DeleteAllSceneObjects() { + DeleteAllSceneObjects(false); + } + + /// + /// Delete every object from the scene. This does not include attachments worn by avatars. + /// + public void DeleteAllSceneObjects(bool exceptNoCopy) + { lock (Entities) { ICollection entities = new List(Entities); @@ -2192,8 +2200,13 @@ namespace OpenSim.Region.Framework.Scenes if (e is SceneObjectGroup) { SceneObjectGroup sog = (SceneObjectGroup)e; - if (!sog.IsAttachment) - DeleteSceneObject((SceneObjectGroup)e, false); + if (sog != null && !sog.IsAttachment) + { + if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0)) + { + DeleteSceneObject((SceneObjectGroup)e, false); + } + } } } } -- cgit v1.1 From acab2a159d150072aa9952100aa6722cbd51c1ea Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 11:24:36 -0700 Subject: Return objects which are NoCopy instead of just leaving them when cleaning the scene, if exceptNoCopy = true. --- OpenSim/Region/Framework/Scenes/Scene.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c596baa..abc7377 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2206,6 +2206,10 @@ namespace OpenSim.Region.Framework.Scenes { DeleteSceneObject((SceneObjectGroup)e, false); } + else + { + DeRezObject(null, sog.RootPart.LocalId, sog.RootPart.GroupID, DeRezAction.Return, UUID.Zero); + } } } } -- cgit v1.1 From bd19cf739a03e255b0bf46021d3fab6ea0148afb Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 12:38:08 -0700 Subject: Fix a bug with DeRezObjects (check for a null remoteClient) --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 5e1798b..83fd349 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1591,15 +1591,17 @@ namespace OpenSim.Region.Framework.Scenes // So that we know the database is upto date, // for when deleting the object from it ForceSceneObjectBackup(grp); + if (remoteClient != null) + { + if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) + permissionToTakeCopy = false; + if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) + permissionToTake = false; - if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) - permissionToTakeCopy = false; - if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) - permissionToTake = false; - - if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) - permissionToDelete = false; + if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) + permissionToDelete = false; + } } // Handle god perms -- cgit v1.1 From ed5dac7e82adfe639a2057ed5d531418277869d7 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 13:06:47 -0700 Subject: Fix another nullref issue in DeRezSceneObject --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 83fd349..0380199 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1605,7 +1605,7 @@ namespace OpenSim.Region.Framework.Scenes } // Handle god perms - if (Permissions.IsGod(remoteClient.AgentId)) + if (remoteClient != null && Permissions.IsGod(remoteClient.AgentId)) { permissionToTake = true; permissionToTakeCopy = true; -- cgit v1.1 From d188ed8ed86661a79b68f5c43ce0a94dc51308f0 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 13:07:17 -0700 Subject: Return everything at once, it's more efficient that way --- OpenSim/Region/Framework/Scenes/Scene.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index abc7377..bbac919 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2191,6 +2191,7 @@ namespace OpenSim.Region.Framework.Scenes ///
public void DeleteAllSceneObjects(bool exceptNoCopy) { + List toReturn = new List(); lock (Entities) { ICollection entities = new List(Entities); @@ -2208,12 +2209,16 @@ namespace OpenSim.Region.Framework.Scenes } else { - DeRezObject(null, sog.RootPart.LocalId, sog.RootPart.GroupID, DeRezAction.Return, UUID.Zero); + toReturn.Add((SceneObjectGroup)e); } } } } } + if (toReturn.Count > 0) + { + returnObjects(toReturn.ToArray(), UUID.Zero); + } } /// -- cgit v1.1 From 8f0adfbfb264532d55c0f0bab5bc508d36ad365e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 15:15:19 -0700 Subject: Trigger the RegionLightShareData OnSave event properly when the profile is saved --- OpenSim/Region/Framework/Scenes/Scene.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index bbac919..c5fb198 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1770,6 +1770,7 @@ namespace OpenSim.Region.Framework.Scenes public void StoreWindlightProfile(RegionLightShareData wl) { m_regInfo.WindlightSettings = wl; + wl.Save(); m_storageManager.DataStore.StoreRegionWindlightSettings(wl); m_eventManager.TriggerOnSaveNewWindlightProfile(); } -- cgit v1.1 From 49272657d7085471b85a4735968495bda31f599f Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 15:30:47 -0700 Subject: Make RegionLightShareData serializable --- OpenSim/Framework/RegionInfo.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index afc4060..2a74e79 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -40,6 +40,7 @@ using OpenSim.Framework.Console; namespace OpenSim.Framework { + [Serializable] public class RegionLightShareData : ICloneable { public UUID regionID = UUID.Zero; -- cgit v1.1 From c3e806a2eac31c4dde67586f0404c796628ba9ce Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 17:25:45 -0700 Subject: Add a new accessor for the TerainModule : "HasChanged" --- OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 1e7ea7b..5bf1f9c 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -93,6 +93,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain get { return m_commander; } } + public bool HasChanged + { + get + { + return m_tainted; + } + } + #endregion #region INonSharedRegionModule Members -- cgit v1.1 From 3bcee57e3efbd63f392067bff1a01ae51be98d13 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 17:34:19 -0700 Subject: add HasChanged to ITerrainModule --- OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | 7 ++----- OpenSim/Region/Framework/Interfaces/ITerrainModule.cs | 3 ++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 5bf1f9c..ffd86a4 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -93,12 +93,9 @@ namespace OpenSim.Region.CoreModules.World.Terrain get { return m_commander; } } - public bool HasChanged + public bool HasChanged() { - get - { - return m_tainted; - } + return m_tainted; } #endregion diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs index 5947afb..98996e2 100644 --- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs @@ -42,7 +42,8 @@ namespace OpenSim.Region.Framework.Interfaces /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight) /// void TaintTerrain(); - + + bool HasChanged(); /// /// Load a terrain from a stream. /// -- cgit v1.1 From c97e9f86219cd79e6fee7266174e78825c405476 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 18:43:01 -0700 Subject: Reverting the ITerrainModule changes. Turns out this was useless. --- OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs | 5 ----- OpenSim/Region/Framework/Interfaces/ITerrainModule.cs | 3 +-- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index ffd86a4..1e7ea7b 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -93,11 +93,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain get { return m_commander; } } - public bool HasChanged() - { - return m_tainted; - } - #endregion #region INonSharedRegionModule Members diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs index 98996e2..5947afb 100644 --- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs @@ -42,8 +42,7 @@ namespace OpenSim.Region.Framework.Interfaces /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight) ///
void TaintTerrain(); - - bool HasChanged(); + /// /// Load a terrain from a stream. /// -- cgit v1.1 From 592ff1288dd1fccc1d2efde90e94ca0ab4a57652 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 18:51:19 -0700 Subject: Add a new global event : OnTerrainUpdate --- .../CoreModules/World/Terrain/TerrainModule.cs | 2 ++ OpenSim/Region/Framework/Scenes/EventManager.cs | 24 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index 1e7ea7b..0c20393 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -544,6 +544,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain m_scene.PhysicsScene.SetTerrain(m_channel.GetFloatsSerialised()); m_scene.SaveTerrain(); + m_scene.EventManager.TriggerTerrainUpdate(); + // Clients who look at the map will never see changes after they looked at the map, so i've commented this out. //m_scene.CreateTerrainTexture(true); } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index ef125cd..0c9759d 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -55,8 +55,12 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnTerrainTickDelegate(); + public delegate void OnTerrainUpdateDelegate(); + public event OnTerrainTickDelegate OnTerrainTick; + public event OnTerrainUpdateDelegate OnTerrainUpdate; + public delegate void OnBackupDelegate(IRegionDataStore datastore, bool forceBackup); public event OnBackupDelegate OnBackup; @@ -716,6 +720,26 @@ namespace OpenSim.Region.Framework.Scenes } } } + public void TriggerTerrainUpdate() + { + OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate; + if (handlerTerrainUpdate != null) + { + foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList()) + { + try + { + d(); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}", + e.Message, e.StackTrace); + } + } + } + } public void TriggerTerrainTick() { -- cgit v1.1 From 9f00f141fe679b13e93240589f7d8b7f519e012b Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 18:54:55 -0700 Subject: Restore "AllowCareminsterFunctions" as an alias to the new "AllowLightshareFunctions". --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index fe71ed5..1fa8c30 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -73,6 +73,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) m_LSFunctionsEnabled = true; + if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false)) + m_LSFunctionsEnabled = true; + m_comms = m_ScriptEngine.World.RequestModuleInterface(); if (m_comms == null) m_LSFunctionsEnabled = false; -- cgit v1.1 From ef0ac7c4032ebb369479c18a4f2cc432b613234f Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 26 Jun 2010 23:20:28 -0700 Subject: Deal with incoming land objects properly so they don't just stack up --- .../CoreModules/World/Land/LandManagementModule.cs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 91c8130..cfee1b0 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -1303,18 +1303,31 @@ namespace OpenSim.Region.CoreModules.World.Land public void EventManagerOnIncomingLandDataFromStorage(List data) { - for (int i = 0; i < data.Count; i++) + lock (m_landList) { - IncomingLandObjectFromStorage(data[i]); + //Remove all the land objects in the sim and then process our new data + foreach (int n in m_landList.Keys) + { + m_scene.EventManager.TriggerLandObjectRemoved(m_landList[n].LandData.GlobalID); + } + m_landIDList.Initialize(); + m_landList.Clear(); + + for (int i = 0; i < data.Count; i++) + { + IncomingLandObjectFromStorage(data[i]); + } } } public void IncomingLandObjectFromStorage(LandData data) { + ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); new_land.LandData = data.Copy(); new_land.SetLandBitmapFromByteArray(); AddLandObject(new_land); + new_land.SendLandUpdateToAvatarsOverMe(); } public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) -- cgit v1.1 From 19f18c8a1b6377fec44ebd358bb4d810d36bd586 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 27 Jun 2010 21:04:30 +0200 Subject: Make drag copy and copy-on-ray handle friends list perms properly --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 81ef54f..dfcbc4c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1851,6 +1851,28 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup copy = original.Copy(AgentID, GroupID, true); copy.AbsolutePosition = copy.AbsolutePosition + offset; + if (copy.OwnerID != AgentID) + { + copy.SetOwnerId(AgentID); + copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); + + List partList = + new List(copy.Children.Values); + + if (m_parentScene.Permissions.PropagatePermissions()) + { + foreach (SceneObjectPart child in partList) + { + child.Inventory.ChangeInventoryOwner(AgentID); + child.TriggerScriptChangedEvent(Changed.OWNER); + child.ApplyNextOwnerPermissions(); + } + } + + copy.RootPart.ObjectSaleType = 0; + copy.RootPart.SalePrice = 10; + } + Entities.Add(copy); // Since we copy from a source group that is in selected -- cgit v1.1 From 9c553cd254b5b27f3ddcffddee9684aeb4a6298b Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 27 Jun 2010 20:20:08 +0100 Subject: Fix more perms weirdness. Preserve "Locked" status across gives and rez/take. Preserve "Anyone can move" flag in most cases. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 55c1575..6532537 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -402,7 +402,7 @@ namespace OpenSim.Region.Framework.Scenes // First, make sore base is limited to the next perms itemCopy.BasePermissions = item.BasePermissions & (item.NextPermissions | (uint)PermissionMask.Move); // By default, current equals base - itemCopy.CurrentPermissions = itemCopy.BasePermissions; + itemCopy.CurrentPermissions = itemCopy.BasePermissions & item.CurrentPermissions; // If this is an object, replace current perms // with folded perms @@ -413,7 +413,7 @@ namespace OpenSim.Region.Framework.Scenes } // Ensure there is no escalation - itemCopy.CurrentPermissions &= item.NextPermissions; + itemCopy.CurrentPermissions &= (item.NextPermissions | (uint)PermissionMask.Move); // Need slam bit on xfer itemCopy.CurrentPermissions |= 8; @@ -918,12 +918,13 @@ namespace OpenSim.Region.Framework.Scenes { agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); if (taskItem.InvType == (int)InventoryType.Object) - agentItem.CurrentPermissions = agentItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13); - agentItem.CurrentPermissions = agentItem.BasePermissions ; + agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); + else + agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; agentItem.CurrentPermissions |= 8; agentItem.NextPermissions = taskItem.NextPermissions; - agentItem.EveryOnePermissions = taskItem.EveryonePermissions & taskItem.NextPermissions; + agentItem.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; } else @@ -1105,11 +1106,11 @@ namespace OpenSim.Region.Framework.Scenes if (Permissions.PropagatePermissions()) { destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions & - srcTaskItem.NextPermissions; + (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions & - srcTaskItem.NextPermissions; + (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions & - srcTaskItem.NextPermissions; + (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); destTaskItem.BasePermissions = srcTaskItem.BasePermissions & (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); destTaskItem.CurrentPermissions |= 8; // Slam! -- cgit v1.1 From d570cffa39e9ca6417ebd1c05cbdfea1d3beabd2 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 28 Jun 2010 01:29:30 +0200 Subject: Fix Copy on Ray, Drag Copy and other little things. Removed the wrong and nonworking ownership assignment in SOG, which messed things up before. No longer trust the client to send the ID of the person something is copied as, since it allows to run a script with someone else's permissions. Properly adjust inventory ownership and perms. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 6 +++--- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 18 ++---------------- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index f071841..cf1dda9 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -6307,8 +6307,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerObjectDuplicate != null) { handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, - dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, - AgentandGroupData.GroupID); + dupe.SharedData.DuplicateFlags, AgentId, + m_activeGroupID); } } @@ -6898,7 +6898,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerObjectDuplicateOnRay != null) { handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, - dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, + AgentId, m_activeGroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index dfcbc4c..69a909b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1851,7 +1851,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup copy = original.Copy(AgentID, GroupID, true); copy.AbsolutePosition = copy.AbsolutePosition + offset; - if (copy.OwnerID != AgentID) + if (original.OwnerID != AgentID) { copy.SetOwnerId(AgentID); copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 7081ced..241295f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1781,7 +1781,9 @@ namespace OpenSim.Region.Framework.Scenes dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); if (!userExposed) + { dupe.RootPart.IsAttachment = previousAttachmentStatus; + } dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; @@ -1806,16 +1808,6 @@ namespace OpenSim.Region.Framework.Scenes dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); } - // Now we've made a copy that replaces this one, we need to - // switch the owner to the person who did the copying - // Second Life copies an object and duplicates the first one in it's place - // So, we have to make a copy of this one, set it in it's place then set the owner on this one - if (userExposed) - { - SetRootPartOwner(m_rootPart, cAgentID, cGroupID); - m_rootPart.ScheduleFullUpdate(); - } - List partList; lockPartsForRead(true); @@ -1837,12 +1829,6 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); newPart.LinkNum = part.LinkNum; - - if (userExposed) - { - SetPartOwner(newPart, cAgentID, cGroupID); - newPart.ScheduleFullUpdate(); - } } } -- cgit v1.1 From a817f6b48c27fe5e950846d687edcd4d375a3c6c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 28 Jun 2010 01:48:24 +0200 Subject: Remove AgentID and GroupOD from the signature of SOG.Copy(). They were never used, but made for a very mispleading read of the code in the callers. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 6 +++--- .../ContentManagementSystem/ContentManagementEntity.cs | 2 +- .../Region/OptionalModules/ContentManagementSystem/MetaEntity.cs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 69a909b..a36800b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1848,7 +1848,7 @@ namespace OpenSim.Region.Framework.Scenes { if (m_parentScene.Permissions.CanDuplicateObject(original.Children.Count, original.UUID, AgentID, original.AbsolutePosition)) { - SceneObjectGroup copy = original.Copy(AgentID, GroupID, true); + SceneObjectGroup copy = original.Copy(true); copy.AbsolutePosition = copy.AbsolutePosition + offset; if (original.OwnerID != AgentID) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 241295f..c48ce3b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1700,7 +1700,7 @@ namespace OpenSim.Region.Framework.Scenes "[SCENE]: Storing {0}, {1} in {2}", Name, UUID, m_scene.RegionInfo.RegionName); - SceneObjectGroup backup_group = Copy(OwnerID, GroupID, false); + SceneObjectGroup backup_group = Copy(false); backup_group.RootPart.Velocity = RootPart.Velocity; backup_group.RootPart.Acceleration = RootPart.Acceleration; backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity; @@ -1758,7 +1758,7 @@ namespace OpenSim.Region.Framework.Scenes /// Duplicates this object, including operations such as physics set up and attaching to the backup event. ///
/// - public SceneObjectGroup Copy(UUID cAgentID, UUID cGroupID, bool userExposed) + public SceneObjectGroup Copy(bool userExposed) { SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); dupe.m_isBackedUp = false; @@ -3897,7 +3897,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual ISceneObject CloneForNewScene() { - SceneObjectGroup sog = Copy(this.OwnerID, this.GroupID, false); + SceneObjectGroup sog = Copy(false); sog.m_isDeleted = false; return sog; } diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs index c277034..ada6701 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) : base(Unchanged, false) { - m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false); + m_UnchangedEntity = Unchanged.Copy(false); } public ContentManagementEntity(string objectXML, Scene scene, bool physics) diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs index 1a72971..841ee00 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs @@ -80,7 +80,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement ///
public MetaEntity(SceneObjectGroup orig, bool physics) { - m_Entity = orig.Copy(orig.RootPart.OwnerID, orig.RootPart.GroupID, false); + m_Entity = orig.Copy(false); Initialize(physics); } -- cgit v1.1 From 4fa1d4896c89d9907fe49f3ad718444b63c03ec9 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 28 Jun 2010 02:30:36 +0200 Subject: Change the way IRegionModule us referenced by IEmailModule to allow later conversion to new style --- OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs | 2 +- OpenSim/Region/Framework/Interfaces/IEmailModule.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs index 83f004d..c0975ea 100644 --- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs @@ -40,7 +40,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Scripting.EmailModules { - public class EmailModule : IEmailModule + public class EmailModule : IRegionModule, IEmailModule { // // Log diff --git a/OpenSim/Region/Framework/Interfaces/IEmailModule.cs b/OpenSim/Region/Framework/Interfaces/IEmailModule.cs index 3a2c423..4f1b91a 100644 --- a/OpenSim/Region/Framework/Interfaces/IEmailModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEmailModule.cs @@ -38,7 +38,7 @@ namespace OpenSim.Region.Framework.Interfaces public int numLeft; } - public interface IEmailModule : IRegionModule + public interface IEmailModule { void SendEmail(UUID objectID, string address, string subject, string body); Email GetNextEmail(UUID objectID, string sender, string subject); -- cgit v1.1 From 827d9be48f8177b5975df68208a8cf7c730b58f0 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 27 Jun 2010 22:23:01 -0700 Subject: Fix the sound issue. It was caused by missing assets; once the client has made one request, it continued to wait for asset before requesting any new ones, until the TransferRequest timed out. Fixed by adding a TransferAbortPacket if the asset cannot be retrieved. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index f071841..5b5dc1e 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -2208,6 +2208,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(sound, ThrottleOutPacketType.Task); } + public void SendTransferAbort(TransferRequestPacket transferRequest) + { + TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort); + abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID; + abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType; + m_log.Debug("[Assets] Aborting transfer; asset request failed"); + OutPacket(abort, ThrottleOutPacketType.Task); + } + public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) { SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); @@ -11502,7 +11511,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP // m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); - m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); + if (!m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived)) + { + //We need to send a TransferAbort here, so the client doesn't wait forever for the asset, + //which causes it to not request any more for a while. Which is bad. + SendTransferAbort(transferRequest); + } } /// -- cgit v1.1 From 3e908023b2f7e9edb77687089f2363a77b13d1fc Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 28 Jun 2010 08:58:51 +0200 Subject: Force IM timestamps to current server time to prevent "Saved on" headers while the sender is online --- .../Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs index 2dc7384..a7aa4ea 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs @@ -156,6 +156,10 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage return; } + // Force timestamp to server time to avoid "Saved on" headers + // being generated for online users + im.timestamp = (uint)Util.UnixTimeSinceEpoch(); + if (dialog == (byte)InstantMessageDialog.MessageFromAgent || dialog == (byte)InstantMessageDialog.MessageFromObject) { -- cgit v1.1 From a5a1df68c29b2d78279bcff60ce66fe97772d0c6 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 28 Jun 2010 04:02:33 -0700 Subject: Provide the interface for StoreAsset to report success or failure --- OpenSim/Data/AssetDataBase.cs | 2 +- OpenSim/Data/IAssetData.cs | 2 +- OpenSim/Data/MSSQL/MSSQLAssetData.cs | 4 +++- OpenSim/Data/MySQL/MySQLAssetData.cs | 4 +++- OpenSim/Data/SQLite/SQLiteAssetData.cs | 4 +++- OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs | 4 +++- OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs | 3 ++- 7 files changed, 16 insertions(+), 7 deletions(-) diff --git a/OpenSim/Data/AssetDataBase.cs b/OpenSim/Data/AssetDataBase.cs index e1a810c..b4ae913 100644 --- a/OpenSim/Data/AssetDataBase.cs +++ b/OpenSim/Data/AssetDataBase.cs @@ -38,7 +38,7 @@ namespace OpenSim.Data { public abstract AssetBase GetAsset(UUID uuid); - public abstract void StoreAsset(AssetBase asset); + public abstract bool StoreAsset(AssetBase asset); public abstract bool ExistsAsset(UUID uuid); public abstract List FetchAssetMetadataSet(int start, int count); diff --git a/OpenSim/Data/IAssetData.cs b/OpenSim/Data/IAssetData.cs index 90d5eeb..065d3a5 100644 --- a/OpenSim/Data/IAssetData.cs +++ b/OpenSim/Data/IAssetData.cs @@ -34,7 +34,7 @@ namespace OpenSim.Data public interface IAssetDataPlugin : IPlugin { AssetBase GetAsset(UUID uuid); - void StoreAsset(AssetBase asset); + bool StoreAsset(AssetBase asset); bool ExistsAsset(UUID uuid); List FetchAssetMetadataSet(int start, int count); void Initialise(string connect); diff --git a/OpenSim/Data/MSSQL/MSSQLAssetData.cs b/OpenSim/Data/MSSQL/MSSQLAssetData.cs index c7488d8..c882555 100644 --- a/OpenSim/Data/MSSQL/MSSQLAssetData.cs +++ b/OpenSim/Data/MSSQL/MSSQLAssetData.cs @@ -143,7 +143,7 @@ namespace OpenSim.Data.MSSQL /// Create asset in m_database /// /// the asset - override public void StoreAsset(AssetBase asset) + override public bool StoreAsset(AssetBase asset) { string sql = @@ -192,10 +192,12 @@ namespace OpenSim.Data.MSSQL try { command.ExecuteNonQuery(); + return true; } catch(Exception e) { m_log.Error("[ASSET DB]: Error storing item :" + e.Message); + return false; } } } diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs index fe5152a..f9ce3d9 100644 --- a/OpenSim/Data/MySQL/MySQLAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLAssetData.cs @@ -153,7 +153,7 @@ namespace OpenSim.Data.MySQL ///
/// Asset UUID to create /// On failure : Throw an exception and attempt to reconnect to database - override public void StoreAsset(AssetBase asset) + override public bool StoreAsset(AssetBase asset) { lock (m_dbLock) { @@ -201,12 +201,14 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?data", asset.Data); cmd.ExecuteNonQuery(); cmd.Dispose(); + return true; } } catch (Exception e) { m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}", asset.FullID, asset.Name, e.Message); + return false; } } } diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs index 16e560c..75e51a3 100644 --- a/OpenSim/Data/SQLite/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs @@ -119,7 +119,7 @@ namespace OpenSim.Data.SQLite /// Create an asset ///
/// Asset Base - override public void StoreAsset(AssetBase asset) + override public bool StoreAsset(AssetBase asset) { //m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString()); if (ExistsAsset(asset.FullID)) @@ -141,6 +141,7 @@ namespace OpenSim.Data.SQLite cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); cmd.ExecuteNonQuery(); + return true; } } } @@ -161,6 +162,7 @@ namespace OpenSim.Data.SQLite cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); cmd.ExecuteNonQuery(); + return true; } } } diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs index df50902..3da298b 100644 --- a/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLiteLegacy/SQLiteAssetData.cs @@ -119,7 +119,7 @@ namespace OpenSim.Data.SQLiteLegacy /// Create an asset ///
/// Asset Base - override public void StoreAsset(AssetBase asset) + override public bool StoreAsset(AssetBase asset) { //m_log.Info("[ASSET DB]: Creating Asset " + asset.FullID.ToString()); if (ExistsAsset(asset.FullID)) @@ -139,6 +139,7 @@ namespace OpenSim.Data.SQLiteLegacy cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); cmd.ExecuteNonQuery(); + return true; } } } @@ -157,6 +158,7 @@ namespace OpenSim.Data.SQLiteLegacy cmd.Parameters.Add(new SqliteParameter(":Data", asset.Data)); cmd.ExecuteNonQuery(); + return true; } } } diff --git a/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs index 4a15cf2..5bab62c 100644 --- a/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/MockAssetDataPlugin.cs @@ -54,9 +54,10 @@ namespace OpenSim.Tests.Common.Mock return assets.Find(x=>x.FullID == uuid); } - public void StoreAsset(AssetBase asset) + public bool StoreAsset(AssetBase asset) { assets.Add(asset); + return true; } public List FetchAssetMetadataSet(int start, int count) { return new List(count); } -- cgit v1.1 From 06fa0388750b939ede9e3d7783e41a574e101397 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 28 Jun 2010 07:09:05 -0700 Subject: Return a UUID.Zero if the asset fails to upload --- OpenSim/Services/AssetService/AssetService.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index 470a4dd..3122382 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -144,7 +144,10 @@ namespace OpenSim.Services.AssetService public string Store(AssetBase asset) { //m_log.DebugFormat("[ASSET SERVICE]: Store asset {0} {1}", asset.Name, asset.ID); - m_Database.StoreAsset(asset); + if (!m_Database.StoreAsset(asset)) + { + return UUID.Zero.ToString(); + } return asset.ID; } -- cgit v1.1 From 6f4d4543b94f28160d697489e591da6614f0c8fc Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 29 Jun 2010 03:51:16 +0200 Subject: Make newly created prims be named "Object" and make newly created scripts have a default touch handler. Compatibility patch --- OpenSim/Framework/PrimitiveBaseShape.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs index 4d1de22..990c859 100644 --- a/OpenSim/Framework/PrimitiveBaseShape.cs +++ b/OpenSim/Framework/PrimitiveBaseShape.cs @@ -1196,7 +1196,7 @@ namespace OpenSim.Framework prim.Textures = this.Textures; prim.Properties = new Primitive.ObjectProperties(); - prim.Properties.Name = "Primitive"; + prim.Properties.Name = "Object"; prim.Properties.Description = ""; prim.Properties.CreatorID = UUID.Zero; prim.Properties.GroupID = UUID.Zero; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6532537..a2a8882 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1378,7 +1378,7 @@ namespace OpenSim.Region.Framework.Scenes return; AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, - Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), + Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"), remoteClient.AgentId); AssetService.Store(asset); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 09c945b..5b007e6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -358,7 +358,7 @@ namespace OpenSim.Region.Framework.Scenes UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, Quaternion rotationOffset, Vector3 offsetPosition) { - m_name = "Primitive"; + m_name = "Object"; Rezzed = DateTime.UtcNow; _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed); @@ -1625,7 +1625,7 @@ namespace OpenSim.Region.Framework.Scenes PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); part.Shape = shape; - part.Name = "Primitive"; + part.Name = "Object"; part._ownerID = UUID.Random(); return part; -- cgit v1.1 From 3cd717d929d641b8e34d2212165af8d32fc8978e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 29 Jun 2010 04:09:14 +0200 Subject: Comment the "Notecard saved" notification that pops up when a notecard is saved into a prim. Sl doesn't have it, and for good reason: It also happens on scripts in our version. Which is wrong. Better no message than a wrong one. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index a2a8882..e61132e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1285,7 +1285,7 @@ namespace OpenSim.Region.Framework.Scenes } if (part.Inventory.UpdateInventoryItem(itemInfo)) { - remoteClient.SendAgentAlertMessage("Notecard saved", false); + // remoteClient.SendAgentAlertMessage("Notecard saved", false); part.GetProperties(remoteClient); } } -- cgit v1.1 From ae2454821628d847b0add20a4c593162baafde5b Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 29 Jun 2010 18:54:31 +0100 Subject: stop exceptions in setting and getting state from propogating since they aren't fatal to operations this will hopefully stop "save oar" from failing if a script asset is corrupt --- .../Framework/Scenes/SceneObjectPartInventory.cs | 39 +++++++++++++++++----- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index d175695..5ab7d20 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -217,7 +217,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (IScriptModule e in engines) { if (e != null) - { + { ArrayList errors = e.GetScriptErrors(itemID); foreach (Object line in errors) ret.Add(line); @@ -359,14 +359,26 @@ namespace OpenSim.Region.Framework.Scenes m_part.ParentGroup.m_savedScriptState[oldID] = newDoc.OuterXml; } + foreach (IScriptModule e in engines) { if (e != null) { - if (e.SetXMLState(newID, m_part.ParentGroup.m_savedScriptState[oldID])) - break; + // Stop an exception in setting saved state from propogating since this is not fatal. + try + { + if (e.SetXMLState(newID, m_part.ParentGroup.m_savedScriptState[oldID])) + break; + } + catch (Exception ex) + { + m_log.WarnFormat( + "[PRIM INVENTORY]: Could not set script state for old key {0}, new key {1} in prim {2} {3}. Exception {4}{5}", + oldID, newID, m_part.Name, m_part.UUID, ex.Message, ex.StackTrace); + } } } + m_part.ParentGroup.m_savedScriptState.Remove(oldID); } } @@ -1028,12 +1040,23 @@ namespace OpenSim.Region.Framework.Scenes { if (e != null) { - string n = e.GetXMLState(item.ItemID); - if (n != String.Empty) + // Stop any exception from the script engine from propogating since setting state + // isn't essential. + try + { + string n = e.GetXMLState(item.ItemID); + if (n != String.Empty) + { + if (!ret.ContainsKey(item.ItemID)) + ret[item.ItemID] = n; + break; + } + } + catch (Exception ex) { - if (!ret.ContainsKey(item.ItemID)) - ret[item.ItemID] = n; - break; + m_log.WarnFormat( + "[PRIM INVENTORY]: Could not retrieve script state for item {0} {1} in prim {2} {3}. Exception {4}{5}", + item.Name, item.ItemID, m_part.Name, m_part.UUID, ex.Message, ex.StackTrace); } } } -- cgit v1.1 From cabb70d90af48d6efd490c019fa7a899537c4187 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 29 Jun 2010 22:50:04 +0100 Subject: Revert "stop exceptions in setting and getting state from propogating since they aren't fatal to operations" This reverts commit ae2454821628d847b0add20a4c593162baafde5b. Reverted for now pending a fix to the underlying xengine problem instead. --- .../Framework/Scenes/SceneObjectPartInventory.cs | 39 +++++----------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 5ab7d20..d175695 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -217,7 +217,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (IScriptModule e in engines) { if (e != null) - { + { ArrayList errors = e.GetScriptErrors(itemID); foreach (Object line in errors) ret.Add(line); @@ -359,26 +359,14 @@ namespace OpenSim.Region.Framework.Scenes m_part.ParentGroup.m_savedScriptState[oldID] = newDoc.OuterXml; } - foreach (IScriptModule e in engines) { if (e != null) { - // Stop an exception in setting saved state from propogating since this is not fatal. - try - { - if (e.SetXMLState(newID, m_part.ParentGroup.m_savedScriptState[oldID])) - break; - } - catch (Exception ex) - { - m_log.WarnFormat( - "[PRIM INVENTORY]: Could not set script state for old key {0}, new key {1} in prim {2} {3}. Exception {4}{5}", - oldID, newID, m_part.Name, m_part.UUID, ex.Message, ex.StackTrace); - } + if (e.SetXMLState(newID, m_part.ParentGroup.m_savedScriptState[oldID])) + break; } } - m_part.ParentGroup.m_savedScriptState.Remove(oldID); } } @@ -1040,23 +1028,12 @@ namespace OpenSim.Region.Framework.Scenes { if (e != null) { - // Stop any exception from the script engine from propogating since setting state - // isn't essential. - try - { - string n = e.GetXMLState(item.ItemID); - if (n != String.Empty) - { - if (!ret.ContainsKey(item.ItemID)) - ret[item.ItemID] = n; - break; - } - } - catch (Exception ex) + string n = e.GetXMLState(item.ItemID); + if (n != String.Empty) { - m_log.WarnFormat( - "[PRIM INVENTORY]: Could not retrieve script state for item {0} {1} in prim {2} {3}. Exception {4}{5}", - item.Name, item.ItemID, m_part.Name, m_part.UUID, ex.Message, ex.StackTrace); + if (!ret.ContainsKey(item.ItemID)) + ret[item.ItemID] = n; + break; } } } -- cgit v1.1 From 8dc7c0849eecaea09ce3571bab28b44c17bb3743 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 29 Jun 2010 23:18:48 -0700 Subject: The other half of the asset fix. Implement an exponentially incrementing retry timer for asset upload failures. Total queue time in the ballpark of 24 hours, which should be a reasonable time for any grid admin to get their asset service back online. This should stop lost assets. --- OpenSim/Framework/AssetBase.cs | 8 ++ .../Connectors/Asset/AssetServiceConnector.cs | 99 +++++++++++++++++++--- 2 files changed, 96 insertions(+), 11 deletions(-) diff --git a/OpenSim/Framework/AssetBase.cs b/OpenSim/Framework/AssetBase.cs index 53d28be..98fa846 100644 --- a/OpenSim/Framework/AssetBase.cs +++ b/OpenSim/Framework/AssetBase.cs @@ -60,6 +60,8 @@ namespace OpenSim.Framework ///
private AssetMetadata m_metadata; + private int m_uploadAttempts; + // This is needed for .NET serialization!!! // Do NOT "Optimize" away! public AssetBase() @@ -197,6 +199,12 @@ namespace OpenSim.Framework set { m_metadata.Type = value; } } + public int UploadAttempts + { + get { return m_uploadAttempts; } + set { m_uploadAttempts = value; } + } + /// /// Is this a region only asset, or does this exist on the asset server also /// diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index 65b3537..ae600bb 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -30,6 +30,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Reflection; +using System.Timers; using Nini.Config; using OpenSim.Framework; using OpenSim.Framework.Console; @@ -48,7 +49,9 @@ namespace OpenSim.Services.Connectors private string m_ServerURI = String.Empty; private IImprovedAssetCache m_Cache = null; - + private int m_retryCounter; + private Dictionary> m_retryQueue = new Dictionary>(); + private Timer m_retryTimer; public AssetServicesConnector() { } @@ -85,6 +88,55 @@ namespace OpenSim.Services.Connectors MainConsole.Instance.Commands.AddCommand("asset", false, "dump asset", "dump asset ", "dump one cached asset", HandleDumpAsset); + + m_retryTimer = new Timer(); + m_retryTimer.Elapsed += new ElapsedEventHandler(retryCheck); + m_retryTimer.Interval = 60000; + } + + protected void retryCheck(object source, ElapsedEventArgs e) + { + m_retryCounter++; + if (m_retryCounter > 60) m_retryCounter -= 60; + List keys = new List(); + foreach (int a in m_retryQueue.Keys) + { + keys.Add(a); + } + foreach (int a in keys) + { + //We exponentially fall back on frequency until we reach one attempt per hour + //The net result is that we end up in the queue for roughly 24 hours.. + //24 hours worth of assets could be a lot, so the hope is that the region admin + //will have gotten the asset connector back online quickly! + + int timefactor = a ^ 2; + if (timefactor > 60) + { + timefactor = 60; + } + + //First, find out if we care about this timefactor + if (timefactor % a == 0) + { + //Yes, we do! + List retrylist = m_retryQueue[a]; + m_retryQueue.Remove(a); + + foreach(AssetBase ass in retrylist) + { + Store(ass); //Store my ass. This function will put it back in the dictionary if it fails + } + } + } + + if (m_retryQueue.Count == 0) + { + //It might only be one tick per minute, but I have + //repented and abandoned my wasteful ways + m_retryCounter = 0; + m_retryTimer.Stop(); + } } protected void SetCache(IImprovedAssetCache cache) @@ -222,20 +274,45 @@ namespace OpenSim.Services.Connectors } catch (Exception e) { - m_log.WarnFormat("[ASSET CONNECTOR]: Unable to send asset {0} to asset server. Reason: {1}", asset.ID, e.Message); + newID = UUID.Zero.ToString(); } - if (newID != String.Empty) + if (newID == UUID.Zero.ToString()) { - // Placing this here, so that this work with old asset servers that don't send any reply back - // SynchronousRestObjectRequester returns somethins that is not an empty string - if (newID != null) - asset.ID = newID; - - if (m_Cache != null) - m_Cache.Cache(asset); + //The asset upload failed, put it in a queue for later + asset.UploadAttempts++; + if (asset.UploadAttempts > 30) + { + //By this stage we've been in the queue for a good few hours; + //We're going to drop the asset. + m_log.ErrorFormat("[Assets] Dropping asset {0} - Upload has been in the queue for too long.", asset.ID.ToString()); + } + else + { + if (!m_retryQueue.ContainsKey(asset.UploadAttempts)) + { + m_retryQueue.Add(asset.UploadAttempts, new List()); + } + List m_queue = m_retryQueue[asset.UploadAttempts]; + m_queue.Add(asset); + m_log.WarnFormat("[Assets] Upload failed: {0} - Requeuing asset for another run.", asset.ID.ToString()); + m_retryTimer.Start(); + } + } + else + { + if (newID != String.Empty) + { + // Placing this here, so that this work with old asset servers that don't send any reply back + // SynchronousRestObjectRequester returns somethins that is not an empty string + if (newID != null) + asset.ID = newID; + + if (m_Cache != null) + m_Cache.Cache(asset); + } } - return newID; + return asset.ID; } public bool UpdateContent(string id, byte[] data) -- cgit v1.1 From 92edbd3e4745ea9007cf6ae42a38fbcd653cc848 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 30 Jun 2010 21:23:57 +0100 Subject: If an emergency pos is required for a new root agent, correctly preserve the z co-ord instead of accidentally resetting the incorrect x co-ord This is a one-liner. It has already been addressed in master and 0.7-post-fixes in a more extensive way --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 51cdf1b..8a633b5 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -839,7 +839,7 @@ namespace OpenSim.Region.Framework.Scenes if (!(pos.Y < 0)) emergencyPos.Y = pos.Y; if (!(pos.Z < 0)) - emergencyPos.X = pos.X; + emergencyPos.Z = pos.Z; } if (pos.Y < 0) { @@ -857,7 +857,7 @@ namespace OpenSim.Region.Framework.Scenes emergencyPos.Y = pos.Y; //Leave as 128 } - + m_log.WarnFormat( "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Substituting {3}", pos, Name, UUID, emergencyPos); -- cgit v1.1 From d743a221e88626bf8b7de8427c98e54df0f523d0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 30 Jun 2010 21:25:39 +0100 Subject: Fix scripts in rezzed objects not starting (Mantis #4775) --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index f702e65..73ef570 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -488,6 +488,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (stateSource == (int)StateSource.ScriptedRez) { + lock (m_CompileDict) + { + m_CompileDict[itemID] = 0; + } + DoOnRezScript(parms); } else -- cgit v1.1 From 3940a4dbc7ffb4eab319ea9c2f1f787ddeee65e8 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 1 Jul 2010 16:11:10 +0200 Subject: Avoid a spurious error message when taking a friend's no copy item --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 9 ++++- .../Shared/Api/Implementation/LSL_Api.cs | 40 ++++++++++++++++------ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 0ac427f..167e166 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1604,8 +1604,15 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) + if (action == DeRezAction.TakeCopy) + { + if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) + permissionToTakeCopy = false; + } + else + { permissionToTakeCopy = false; + } if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) permissionToTake = false; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index fb191e6..d49bbb2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9829,19 +9829,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llXorBase64StringsCorrect(string str1, string str2) { m_host.AddScriptLPS(1); - string ret = String.Empty; - string src1 = llBase64ToString(str1); - string src2 = llBase64ToString(str2); - int c = 0; - for (int i = 0; i < src1.Length; i++) + + if (str1 == String.Empty) + return String.Empty; + if (str2 == String.Empty) + return str1; + + byte[] data1 = Convert.FromBase64String(str1); + byte[] data2 = Convert.FromBase64String(str2); + + byte[] d2 = new Byte[data1.Length]; + int pos = 0; + + if (data1.Length <= data2.Length) { - ret += (char) (src1[i] ^ src2[c]); + Array.Copy(data2, 0, d2, 0, data1.Length); + } + else + { + while (pos < data1.Length) + { + int len = data1.Length - pos; + if (len > data2.Length) + len = data2.Length; - c++; - if (c >= src2.Length) - c = 0; + Array.Copy(data2, 0, d2, pos, len); + pos += len; + } } - return llStringToBase64(ret); + + for (pos = 0 ; pos < data1.Length ; pos++ ) + data1[pos] ^= d2[pos]; + + return Convert.ToBase64String(data1); } public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) -- cgit v1.1 From d5cbe4cb75a40a5b98d92d7fac504943edf428a1 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 1 Jul 2010 16:40:26 +0200 Subject: Remove trailing slash from HTTP URLs to be compatible with SL --- OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 9b565ed..ab27da9 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -155,7 +155,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp m_UrlMap[url] = urlData; - string uri = "/lslhttp/" + urlcode.ToString() + "/"; + string uri = "/lslhttp/" + urlcode.ToString(); m_HttpServer.AddPollServiceHTTPHandler(uri,HandleHttpPoll, new PollServiceEventArgs(HttpRequestHandler,HasEvents, GetEvents, NoEvents, -- cgit v1.1 From 3d5d44279b99e58cb4f2db3532df522ad3b5cccf Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 1 Jul 2010 17:06:29 +0200 Subject: ANother stab at LSL compatibility --- OpenSim/Framework/ParcelMediaCommandEnum.cs | 2 +- OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | 2 +- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Framework/ParcelMediaCommandEnum.cs b/OpenSim/Framework/ParcelMediaCommandEnum.cs index 93c41ec..e714382 100644 --- a/OpenSim/Framework/ParcelMediaCommandEnum.cs +++ b/OpenSim/Framework/ParcelMediaCommandEnum.cs @@ -27,7 +27,7 @@ namespace OpenSim.Framework { - public enum ParcelMediaCommandEnum + public enum ParcelMediaCommandEnum : int { Stop = 0, Pause = 1, diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index ab27da9..f8cb414 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); return urlcode; } - string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; + string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString(); UrlData urlData = new UrlData(); urlData.hostID = host.UUID; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d49bbb2..e226682 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9394,7 +9394,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (aList.Data[i] != null) { - switch ((ParcelMediaCommandEnum) aList.Data[i]) + switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString())) { case ParcelMediaCommandEnum.Url: list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); -- cgit v1.1 From 1cb7695fb0bcdcbdbb6f2a410fd9f337438afef7 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 1 Jul 2010 08:48:02 -0700 Subject: Catch newid == null which is what happens if the asset service is offline (seems a connection failure does not throw an exception) --- OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index ae600bb..bc56963 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -271,6 +271,10 @@ namespace OpenSim.Services.Connectors { newID = SynchronousRestObjectRequester. MakeRequest("POST", uri, asset); + if (newID == null) + { + newID = UUID.Zero.ToString(); + } } catch (Exception e) { -- cgit v1.1 From 38384cc79c04fe9b97070104283be02511c4e12c Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 1 Jul 2010 08:52:30 -0700 Subject: Report asset upload success if it has previously failed --- OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index bc56963..bbccef9 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -305,6 +305,10 @@ namespace OpenSim.Services.Connectors } else { + if (asset.UploadAttempts > 0) + { + m_log.InfoFormat("[Assets] Upload of {0} succeeded after {1} failed attempts", asset.ID.ToString(), asset.UploadAttempts.ToString())); + } if (newID != String.Empty) { // Placing this here, so that this work with old asset servers that don't send any reply back -- cgit v1.1 From b38a22506b31041e29a1271db32046efcb14af4e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 1 Jul 2010 08:55:52 -0700 Subject: Fix build break --- OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index bbccef9..94acd6c 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -307,7 +307,7 @@ namespace OpenSim.Services.Connectors { if (asset.UploadAttempts > 0) { - m_log.InfoFormat("[Assets] Upload of {0} succeeded after {1} failed attempts", asset.ID.ToString(), asset.UploadAttempts.ToString())); + m_log.InfoFormat("[Assets] Upload of {0} succeeded after {1} failed attempts", asset.ID.ToString(), asset.UploadAttempts.ToString()); } if (newID != String.Empty) { -- cgit v1.1 From 071d601dcbd812bf2e3b163a53323ab5e00a315e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 1 Jul 2010 09:46:57 -0700 Subject: Cache all assets on upload so that the client can still retrieve the asset if it enters a retry queue --- OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index 94acd6c..e63dd50 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -256,11 +256,10 @@ namespace OpenSim.Services.Connectors public string Store(AssetBase asset) { + if (m_Cache != null) + m_Cache.Cache(asset); if (asset.Temporary || asset.Local) { - if (m_Cache != null) - m_Cache.Cache(asset); - return asset.ID; } -- cgit v1.1 From 60c15d7c283a7ded6d7e7b6c40b77b2a6b7218f2 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 2 Jul 2010 03:05:40 +0200 Subject: Fix a dumb little sign error that makes a LSL wiki example fail --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 212dbe3..5927973 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -663,13 +663,13 @@ namespace OpenSim.Region.ScriptEngine.Shared Object[] ret; if (start < 0) - start=m_data.Length-start; + start=m_data.Length+start; if (start < 0) start=0; if (end < 0) - end=m_data.Length-end; + end=m_data.Length+end; if (end < 0) end=0; -- cgit v1.1 From a7c4cb95aade11c302c9d1113f720467233b8600 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 2 Jul 2010 04:26:55 +0200 Subject: Fox another scripting nasty. Stuff no system.string objects into lists --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e226682..11d7c2b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5247,7 +5247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ',': if (parens == 0) { - result.Add(src.Substring(start,length).Trim()); + result.Add(new LSL_String(src.Substring(start,length).Trim())); start += length+1; length = 0; } -- cgit v1.1 From beb5259cd1ae11464e2affaa19788361979fbd0e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 2 Jul 2010 04:51:31 +0200 Subject: Remove GetEconomyData and the economy data structure (unused) --- OpenSim/Framework/IMoneyModule.cs | 21 --------------------- .../World/MoneyModule/SampleMoneyModule.cs | 21 --------------------- 2 files changed, 42 deletions(-) diff --git a/OpenSim/Framework/IMoneyModule.cs b/OpenSim/Framework/IMoneyModule.cs index 3480960..17e74a0 100644 --- a/OpenSim/Framework/IMoneyModule.cs +++ b/OpenSim/Framework/IMoneyModule.cs @@ -43,27 +43,6 @@ namespace OpenSim.Framework bool AmountCovered(IClientAPI client, int amount); void ApplyCharge(UUID agentID, int amount, string text); - EconomyData GetEconomyData(); - event ObjectPaid OnObjectPaid; } - - public struct EconomyData - { - public int ObjectCapacity; - public int ObjectCount; - public int PriceEnergyUnit; - public int PriceGroupCreate; - public int PriceObjectClaim; - public float PriceObjectRent; - public float PriceObjectScaleFactor; - public int PriceParcelClaim; - public float PriceParcelClaimFactor; - public int PriceParcelRent; - public int PricePublicObjectDecay; - public int PricePublicObjectDelete; - public int PriceRentLight; - public int PriceUpload; - public int TeleportMinPrice; - } } diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index b9a75cc..e070077 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -268,27 +268,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule } - public EconomyData GetEconomyData() - { - EconomyData edata = new EconomyData(); - edata.ObjectCapacity = ObjectCapacity; - edata.ObjectCount = ObjectCount; - edata.PriceEnergyUnit = PriceEnergyUnit; - edata.PriceGroupCreate = PriceGroupCreate; - edata.PriceObjectClaim = PriceObjectClaim; - edata.PriceObjectRent = PriceObjectRent; - edata.PriceObjectScaleFactor = PriceObjectScaleFactor; - edata.PriceParcelClaim = PriceParcelClaim; - edata.PriceParcelClaimFactor = PriceParcelClaimFactor; - edata.PriceParcelRent = PriceParcelRent; - edata.PricePublicObjectDecay = PricePublicObjectDecay; - edata.PricePublicObjectDelete = PricePublicObjectDelete; - edata.PriceRentLight = PriceRentLight; - edata.PriceUpload = PriceUpload; - edata.TeleportMinPrice = TeleportMinPrice; - return edata; - } - private void GetClientFunds(IClientAPI client) { CheckExistAndRefreshFunds(client.AgentId); -- cgit v1.1 From c87e6a289c5ab93025bf03f486629fd5aa00aaaa Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 2 Jul 2010 06:20:36 +0200 Subject: Clean up IMoneyModule and adjust the other modules to the changes --- OpenSim/Framework/Capabilities/Caps.cs | 2 +- OpenSim/Framework/IMoneyModule.cs | 11 ++++---- .../AssetTransaction/AssetTransactionModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- .../Avatar/XmlRpcGroups/GroupsModule.cs | 4 +-- .../World/MoneyModule/SampleMoneyModule.cs | 31 +++++++++++----------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs index 62a1e17..da953bb 100644 --- a/OpenSim/Framework/Capabilities/Caps.cs +++ b/OpenSim/Framework/Capabilities/Caps.cs @@ -814,7 +814,7 @@ namespace OpenSim.Framework.Capabilities if (mm != null) { - if (!mm.UploadCovered(client)) + if (!mm.UploadCovered(client, mm.UploadCharge)) { if (client != null) client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); diff --git a/OpenSim/Framework/IMoneyModule.cs b/OpenSim/Framework/IMoneyModule.cs index 17e74a0..3d4873d 100644 --- a/OpenSim/Framework/IMoneyModule.cs +++ b/OpenSim/Framework/IMoneyModule.cs @@ -35,13 +35,14 @@ namespace OpenSim.Framework bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount); - int GetBalance(IClientAPI client); - void ApplyUploadCharge(UUID agentID); - bool UploadCovered(IClientAPI client); - void ApplyGroupCreationCharge(UUID agentID); - bool GroupCreationCovered(IClientAPI client); + int GetBalance(UUID agentID); + bool UploadCovered(IClientAPI client, int amount); bool AmountCovered(IClientAPI client, int amount); void ApplyCharge(UUID agentID, int amount, string text); + void ApplyUploadCharge(UUID agentID, int amount, string text); + + int UploadCharge { get; } + int GroupCreationCharge { get; } event ObjectPaid OnObjectPaid; } diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 7e08ecf..ae31050 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -243,7 +243,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (mm != null) { - if (!mm.UploadCovered(remoteClient)) + if (!mm.UploadCovered(remoteClient, mm.UploadCharge)) { remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); return; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 167e166..489b8ca 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes IMoneyModule money=RequestModuleInterface(); if (money != null) { - money.ApplyUploadCharge(agentID); + money.ApplyUploadCharge(agentID, money.UploadCharge, "Asset upload"); } AddInventoryItem(agentID, item); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 56c0d98..3f15b69 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -722,11 +722,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (money != null) { // do the transaction, that is if the agent has got sufficient funds - if (!money.GroupCreationCovered(remoteClient)) { + if (!money.AmountCovered(remoteClient, money.GroupCreationCharge)) { remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got issuficient funds to create a group."); return UUID.Zero; } - money.ApplyGroupCreationCharge(GetRequestingAgentID(remoteClient)); + money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, "Group Creation"); } UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index e070077..6f5ef9e 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -108,6 +108,16 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule public event ObjectPaid OnObjectPaid; + public int UploadCharge + { + get { return 0; } + } + + public int GroupCreationCharge + { + get { return 0; } + } + /// /// Startup /// @@ -188,15 +198,10 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule // Please do not refactor these to be just one method // Existing implementations need the distinction // - public void ApplyUploadCharge(UUID agentID) - { - } - - public void ApplyGroupCreationCharge(UUID agentID) + public void ApplyCharge(UUID agentID, int amount, string text) { } - - public void ApplyCharge(UUID agentID, int amount, string text) + public void ApplyUploadCharge(UUID agentID, int amount, string text) { } @@ -769,7 +774,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); } - public int GetBalance(IClientAPI client) + public int GetBalance(UUID agentID) { return 0; } @@ -777,16 +782,10 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule // Please do not refactor these to be just one method // Existing implementations need the distinction // - public bool UploadCovered(IClientAPI client) - { - return AmountCovered(client, PriceUpload); - } - - public bool GroupCreationCovered(IClientAPI client) + public bool UploadCovered(IClientAPI client, int amount) { - return AmountCovered(client, PriceGroupCreate); + return true; } - public bool AmountCovered(IClientAPI client, int amount) { return true; -- cgit v1.1 From 233c872d24c8cc9d0b883ff8f816f67e57638042 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 2 Jul 2010 09:40:58 +0200 Subject: Call client.Start() sunchronously. Calling thos async avoids some stuttering when people log in, but fatally screws up money. --- OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index cda461c..f2bcc0b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -900,7 +900,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Start the IClientAPI // Spin it off so that it doesn't clog up the LLUDPServer - Util.FireAndForget(delegate(object o) { client.Start(); }); + //Util.FireAndForget(delegate(object o) { client.Start(); }); + + // NOTE: DO NOT CALL THIS ASYNCHRONOUSLY!!!!! + // This method will ultimately cause the modules to hook + // client events in OnNewClient. If they can't do this + // before further packets are processed, packets WILL BE LOST. + // This includes the all-important EconomyDataRequest! + // So using FireAndForget here WILL screw up money. Badly. + // You have been warned! + client.Start(); } else { -- cgit v1.1 From 721d8a72987cea267ce9d32dfb91a288019107b2 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 3 Jul 2010 07:09:27 +0200 Subject: Re-add the slashes at the end of the URL. Too much depends on them --- OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index f8cb414..9b565ed 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); return urlcode; } - string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString(); + string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; UrlData urlData = new UrlData(); urlData.hostID = host.UUID; @@ -155,7 +155,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp m_UrlMap[url] = urlData; - string uri = "/lslhttp/" + urlcode.ToString(); + string uri = "/lslhttp/" + urlcode.ToString() + "/"; m_HttpServer.AddPollServiceHTTPHandler(uri,HandleHttpPoll, new PollServiceEventArgs(HttpRequestHandler,HasEvents, GetEvents, NoEvents, -- cgit v1.1 From 86a82e6ecb564c4b3126d3472482d713213aaf31 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 3 Jul 2010 08:33:08 +0200 Subject: Now, fix the slash issue the right way. Our URLs now work like SL's --- OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 9b565ed..1fd1f47 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); return urlcode; } - string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; + string url = "http://" + m_ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString(); UrlData urlData = new UrlData(); urlData.hostID = host.UUID; @@ -152,10 +152,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp urlData.urlcode = urlcode; urlData.requests = new Dictionary(); - m_UrlMap[url] = urlData; - string uri = "/lslhttp/" + urlcode.ToString() + "/"; + string uri = "/lslhttp/" + urlcode.ToString(); m_HttpServer.AddPollServiceHTTPHandler(uri,HandleHttpPoll, new PollServiceEventArgs(HttpRequestHandler,HasEvents, GetEvents, NoEvents, @@ -386,6 +385,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp return response; } + public void HttpRequestHandler(UUID requestID, Hashtable request) { lock (request) @@ -400,8 +400,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp int pos1 = uri.IndexOf("/");// /lslhttp int pos2 = uri.IndexOf("/", pos1 + 1);// /lslhttp/ - int pos3 = uri.IndexOf("/", pos2 + 1);// /lslhttp// - string uri_tmp = uri.Substring(0, pos3 + 1); + int pos3 = pos2 + 37; // /lslhttp/urlcode + string uri_tmp = uri.Substring(0, pos3); //HTTP server code doesn't provide us with QueryStrings string pathInfo; string queryString; -- cgit v1.1 From 3d495b709ec897970b24ce48d6a8495d520864d4 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 3 Jul 2010 06:08:18 -0700 Subject: Implement a timeout value in the SynchronousRestObjectRequester. Default is 100 seconds. --- .../HttpServer/SynchronousRestObjectRequester.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs index eab463c..bb3b8b1 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs @@ -57,6 +57,21 @@ namespace OpenSim.Framework.Servers.HttpServer /// the request. You'll want to make sure you deal with this as they're not uncommon public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj) { + return MakeRequest(verb, requestUrl, obj, 100); + } + /// + /// Perform a synchronous REST request. + /// + /// + /// + /// + /// + /// + /// + /// Thrown if we encounter a network issue while posting + /// the request. You'll want to make sure you deal with this as they're not uncommon + public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj, int pTimeout) + { Type type = typeof (TRequest); TResponse deserial = default(TResponse); @@ -81,7 +96,7 @@ namespace OpenSim.Framework.Servers.HttpServer int length = (int) buffer.Length; request.ContentLength = length; - + request.Timeout = pTimeout * 1000; Stream requestStream = null; try { -- cgit v1.1 From 2b49cb922799aadcdb93225d74735fcf7da94bbd Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 3 Jul 2010 06:09:20 -0700 Subject: Make sure the AssetServiceConnector times out within 30 seconds. If it doesn't, the client will get bored and give an upload error, instead of granting success and entering the asset into our retry queue. --- OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index e63dd50..1f40312 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -269,8 +269,8 @@ namespace OpenSim.Services.Connectors try { newID = SynchronousRestObjectRequester. - MakeRequest("POST", uri, asset); - if (newID == null) + MakeRequest("POST", uri, asset, 25); + if (newID == null || newID == "") { newID = UUID.Zero.ToString(); } -- cgit v1.1 From 39ae1def85fcaf56761c88ad0a000e659941162c Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 3 Jul 2010 06:10:02 -0700 Subject: Re-implement the Undo stack as a List; the old implementation was buggy --- OpenSim/Framework/UndoStack.cs | 51 +++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 33 deletions(-) diff --git a/OpenSim/Framework/UndoStack.cs b/OpenSim/Framework/UndoStack.cs index 4d800ae..3799180 100644 --- a/OpenSim/Framework/UndoStack.cs +++ b/OpenSim/Framework/UndoStack.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections.Generic; namespace OpenSim.Framework { @@ -36,33 +37,30 @@ namespace OpenSim.Framework [Serializable] public class UndoStack { - private int m_new = 1; - private int m_old = 0; - private T[] m_Undos; + private List m_undolist; + private int m_max; public UndoStack(int capacity) { - m_Undos = new T[capacity + 1]; + m_undolist = new List(); + m_max = capacity; } public bool IsFull { - get { return m_new == m_old; } + get { return m_undolist.Count >= m_max; } } public int Capacity { - get { return m_Undos.Length - 1; } + get { return m_max; } } public int Count { get { - int count = m_new - m_old - 1; - if (count < 0) - count += m_Undos.Length; - return count; + return m_undolist.Count; } } @@ -70,45 +68,32 @@ namespace OpenSim.Framework { if (IsFull) { - m_old++; - if (m_old >= m_Undos.Length) - m_old -= m_Undos.Length; + m_undolist.RemoveAt(0); } - if (++m_new >= m_Undos.Length) - m_new -= m_Undos.Length; - m_Undos[m_new] = item; + m_undolist.Add(item); } public T Pop() { - if (Count > 0) + if (m_undolist.Count > 0) { - T deleted = m_Undos[m_new]; - m_Undos[m_new--] = default(T); - if (m_new < 0) - m_new += m_Undos.Length; - return deleted; + int ind = m_undolist.Count - 1; + T item = m_undolist[ind]; + m_undolist.RemoveAt(ind); + return item; } else - throw new InvalidOperationException("Cannot pop from emtpy stack"); + throw new InvalidOperationException("Cannot pop from empty stack"); } public T Peek() { - return m_Undos[m_new]; + return m_undolist[m_undolist.Count - 1]; } public void Clear() { - if (Count > 0) - { - for (int i = 0; i < m_Undos.Length; i++) - { - m_Undos[i] = default(T); - } - m_new = 1; - m_old = 0; - } + m_undolist.Clear(); } } } -- cgit v1.1 From fe2b044d38f3bd3aa669334d34567fd991a67b3e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 3 Jul 2010 06:10:55 -0700 Subject: Fix Undo! Made a lot of changes to Undo state saving; it now considers that groups of objects can be moved and not just individual prims.. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 39 ++++++++++----- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 16 ++++++- OpenSim/Region/Framework/Scenes/UndoState.cs | 55 ++++++++++++++++++---- 3 files changed, 87 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index c48ce3b..da664da 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -349,7 +349,21 @@ namespace OpenSim.Region.Framework.Scenes public virtual Quaternion Rotation { get { return m_rotation; } - set { m_rotation = value; } + set { + lockPartsForRead(true); + try + { + foreach(SceneObjectPart p in m_parts.Values) + { + p.StoreUndoState(true); + } + } + finally + { + lockPartsForRead(false); + } + m_rotation = value; + } } public Quaternion GroupRotation @@ -421,6 +435,7 @@ namespace OpenSim.Region.Framework.Scenes get { return m_rootPart.GroupPosition; } set { + Vector3 val = value; if ((m_scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || m_scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) @@ -431,7 +446,10 @@ namespace OpenSim.Region.Framework.Scenes } lockPartsForRead(true); - + foreach (SceneObjectPart part in m_parts.Values) + { + part.IgnoreUndoUpdate = true; + } if (RootPart.GetStatusSandbox()) { if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) @@ -443,12 +461,12 @@ namespace OpenSim.Region.Framework.Scenes return; } } - foreach (SceneObjectPart part in m_parts.Values) { + part.IgnoreUndoUpdate = false; + part.StoreUndoState(true); part.GroupPosition = val; } - lockPartsForRead(false); //if (m_rootPart.PhysActor != null) @@ -724,7 +742,6 @@ namespace OpenSim.Region.Framework.Scenes { foreach (SceneObjectPart part in m_parts.Values) { - Vector3 partscale = part.Scale; Vector3 partoffset = part.OffsetPosition; @@ -3132,7 +3149,6 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = GetChildPart(localID); if (part != null) { - part.IgnoreUndoUpdate = true; if (scale.X > m_scene.m_maxNonphys) scale.X = m_scene.m_maxNonphys; if (scale.Y > m_scene.m_maxNonphys) @@ -3218,8 +3234,7 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - obPart.IgnoreUndoUpdate = false; - obPart.StoreUndoState(); + } } } @@ -3229,13 +3244,17 @@ namespace OpenSim.Region.Framework.Scenes Vector3 prevScale = part.Scale; prevScale.X *= x; prevScale.Y *= y; - prevScale.Z *= z; + prevScale.Z *= z;; + part.IgnoreUndoUpdate = true; part.Resize(prevScale); + part.IgnoreUndoUpdate = false; lockPartsForRead(true); { foreach (SceneObjectPart obPart in m_parts.Values) { + obPart.IgnoreUndoUpdate = false; + obPart.StoreUndoState(true); obPart.IgnoreUndoUpdate = true; if (obPart.UUID != m_rootPart.UUID) { @@ -3251,7 +3270,6 @@ namespace OpenSim.Region.Framework.Scenes obPart.UpdateOffSet(currentpos); } obPart.IgnoreUndoUpdate = false; - obPart.StoreUndoState(); } } lockPartsForRead(false); @@ -3263,7 +3281,6 @@ namespace OpenSim.Region.Framework.Scenes } part.IgnoreUndoUpdate = false; - part.StoreUndoState(); HasGroupChanged = true; ScheduleGroupForTerseUpdate(); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 5b007e6..72ad281 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3504,9 +3504,12 @@ namespace OpenSim.Region.Framework.Scenes m_parentGroup.ScheduleGroupForTerseUpdate(); //m_parentGroup.ScheduleGroupForFullUpdate(); } - public void StoreUndoState() { + StoreUndoState(false); + } + public void StoreUndoState(bool group) + { if (!Undoing) { if (!IgnoreUndoUpdate) @@ -3528,7 +3531,7 @@ namespace OpenSim.Region.Framework.Scenes if (m_parentGroup.GetSceneMaxUndo() > 0) { UndoState nUndo = new UndoState(this); - + nUndo.GroupChange = group; m_undo.Push(nUndo); } @@ -4010,6 +4013,15 @@ namespace OpenSim.Region.Framework.Scenes nUndo = new UndoState(this); } UndoState goback = m_undo.Pop(); + m_log.Debug("Got goback"); + if (goback == null) + { + m_log.Debug("it's null"); + } + else + { + m_log.Debug(goback.GroupPosition.ToString()); + } if (goback != null) { goback.PlaybackState(this); diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index 55e407e..77381ab 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs @@ -35,6 +35,10 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 Position = Vector3.Zero; public Vector3 Scale = Vector3.Zero; public Quaternion Rotation = Quaternion.Identity; + public bool GroupChange = false; + public Vector3 GroupPosition = Vector3.Zero; + public Quaternion GroupRotation = Quaternion.Identity; + public Vector3 GroupScale = Vector3.Zero; public UndoState(SceneObjectPart part) { @@ -42,12 +46,24 @@ namespace OpenSim.Region.Framework.Scenes { if (part.ParentID == 0) { - Position = part.ParentGroup.AbsolutePosition; + GroupScale = part.Shape.Scale; + + //FUBAR WARNING: Do NOT get the group's absoluteposition here + //or you'll experience a loop and/or a stack issue + GroupPosition = part.ParentGroup.RootPart.AbsolutePosition; + GroupRotation = part.ParentGroup.Rotation; + Position = part.ParentGroup.RootPart.AbsolutePosition; Rotation = part.RotationOffset; Scale = part.Shape.Scale; } else { + GroupScale = part.Shape.Scale; + + //FUBAR WARNING: Do NOT get the group's absoluteposition here + //or you'll experience a loop and/or a stack issue + GroupPosition = part.ParentGroup.RootPart.AbsolutePosition; + GroupRotation = part.ParentGroup.Rotation; Position = part.OffsetPosition; Rotation = part.RotationOffset; Scale = part.Shape.Scale; @@ -61,14 +77,14 @@ namespace OpenSim.Region.Framework.Scenes { if (part.ParentID == 0) { - if (Position == part.ParentGroup.AbsolutePosition && Rotation == part.ParentGroup.Rotation) + if (Position == part.ParentGroup.RootPart.AbsolutePosition && Rotation == part.ParentGroup.Rotation && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale) return true; else return false; } else { - if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale) + if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale) return true; else return false; @@ -84,10 +100,10 @@ namespace OpenSim.Region.Framework.Scenes { part.Undoing = true; - if (part.ParentID == 0) + if (part.ParentID == 0 && GroupChange == false) { if (Position != Vector3.Zero) - part.ParentGroup.AbsolutePosition = Position; + part.ParentGroup.AbsolutePosition = Position; part.RotationOffset = Rotation; if (Scale != Vector3.Zero) part.Resize(Scale); @@ -95,11 +111,30 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (Position != Vector3.Zero) - part.OffsetPosition = Position; - part.UpdateRotation(Rotation); - if (Scale != Vector3.Zero) - part.Resize(Scale); part.ScheduleTerseUpdate(); + if (GroupChange) + { + if (Position != Vector3.Zero) + { + //Calculate the scale... + Vector3 gs = part.Shape.Scale; + float scale = GroupScale.Z / gs.Z; + + //Scale first since it can affect our position + part.ParentGroup.GroupResize(gs * scale, part.LocalId); + part.ParentGroup.AbsolutePosition = GroupPosition; + part.ParentGroup.Rotation = GroupRotation; + + } + } + else + { + if (Position != Vector3.Zero) //We can use this for all the updates since all are set + { + part.OffsetPosition = Position; + part.UpdateRotation(Rotation); + part.Resize(Scale); part.ScheduleTerseUpdate(); + } + } } part.Undoing = false; -- cgit v1.1 From 4cd5e642319b31e1da838ca6fda97ae2992b2c79 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 3 Jul 2010 09:22:58 -0700 Subject: Use SendTransferAbort in a more sensible place --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 14b716b..4dfd5d1 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -11511,12 +11511,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP // m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); - if (!m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived)) - { - //We need to send a TransferAbort here, so the client doesn't wait forever for the asset, - //which causes it to not request any more for a while. Which is bad. - SendTransferAbort(transferRequest); - } + + //Note, the bool returned from the below function is useless since it is always false. + m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); + } /// @@ -11565,8 +11563,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP } //m_log.DebugFormat("[ASSET CACHE]: Asset transfer request for asset which is {0} already known to be missing. Dropping", requestID); - - // FIXME: We never tell the client about assets which do not exist when requested by this transfer mechanism, which can't be right. + + //We need to send a TransferAbort here, so the client doesn't wait forever for the asset, + //which causes it to not request any more for a while. Which is bad. + SendTransferAbort(transferRequest); return; } -- cgit v1.1 From edcfaf60c99b7cde324621c2ffcfbb16e4eb4c5e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 3 Jul 2010 20:27:00 +0200 Subject: Fix IMs the right way. This sets it up so that timestamps are actually in PST (to match viewer time), does correct storage and retrieval of IMs, corrects the session ID and makes sure IMs don't get marked "saved" if they're live. Removes the group IM save option, which our group IM module never had in the first place, as saving group chatter makes no sense at all. --- .../Avatar/InstantMessage/InstantMessageModule.cs | 27 +++++++-- .../Avatar/InstantMessage/OfflineMessageModule.cs | 65 +++++++++++++--------- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 7 ++- .../Shared/Api/Implementation/LSL_Api.cs | 22 +++++++- 4 files changed, 86 insertions(+), 35 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs index a7aa4ea..ffdac58 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs @@ -156,16 +156,31 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage return; } - // Force timestamp to server time to avoid "Saved on" headers - // being generated for online users - im.timestamp = (uint)Util.UnixTimeSinceEpoch(); + DateTime dt = DateTime.UtcNow; - if (dialog == (byte)InstantMessageDialog.MessageFromAgent || - dialog == (byte)InstantMessageDialog.MessageFromObject) + // Ticks from UtcNow, but make it look like local. Evil, huh? + dt = DateTime.SpecifyKind(dt, DateTimeKind.Local); + + try + { + // Convert that to the PST timezone + TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles"); + dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo); + } + catch { - im.offline = 1; + m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp."); } + // And make it look local again to fool the unix time util + dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc); + + im.timestamp = (uint)Util.ToUnixTime(dt); + + // If client is null, this message comes from storage and IS offline + if (client != null) + im.offline = 0; + if (m_TransferModule != null) { m_TransferModule.SendInstantMessage(im, diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index a2dc91f..feeb9e6 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -192,6 +192,17 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // Needed for proper state management for stored group // invitations // + + im.offline = 1; + + // Reconstruct imSessionID + if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) + { + UUID fromAgentID = new UUID(im.fromAgentID); + UUID sessionID = fromAgentID ^ client.AgentId; + im.imSessionID = new Guid(sessionID.ToString()); + } + Scene s = FindScene(client.AgentId); if (s != null) s.EventManager.TriggerIncomingInstantMessage(im); @@ -201,35 +212,37 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage private void UndeliveredMessage(GridInstantMessage im) { - if (im.dialog == 19) - im.offline = 1; // We want them pushed out to the server - if ((im.offline != 0) - && (!im.fromGroup || (im.fromGroup && m_ForwardOfflineGroupMessages))) + if (im.dialog != (byte)InstantMessageDialog.MessageFromObject && + im.dialog != (byte)InstantMessageDialog.MessageFromAgent && + im.dialog != (byte)InstantMessageDialog.GroupNotice && + im.dialog != (byte)InstantMessageDialog.InventoryOffered) { - // It's not delivered. Make sure the scope id is saved - // We don't need the imSessionID here anymore, overwrite it - Scene scene = FindScene(new UUID(im.fromAgentID)); - if (scene == null) - scene = m_SceneList[0]; - im.imSessionID = new Guid(scene.RegionInfo.ScopeID.ToString()); + return; + } - bool success = SynchronousRestObjectPoster.BeginPostObject( - "POST", m_RestURL+"/SaveMessage/", im); + // It's not delivered. Make sure the scope id is saved + // We don't need the imSessionID here anymore, overwrite it + Scene scene = FindScene(new UUID(im.fromAgentID)); + if (scene == null) + scene = m_SceneList[0]; + im.imSessionID = new Guid(scene.RegionInfo.ScopeID.ToString()); - if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) - { - IClientAPI client = FindClient(new UUID(im.fromAgentID)); - if (client == null) - return; - - client.SendInstantMessage(new GridInstantMessage( - null, new UUID(im.toAgentID), - "System", new UUID(im.fromAgentID), - (byte)InstantMessageDialog.MessageFromAgent, - "User is not logged in. "+ - (success ? "Message saved." : "Message not saved"), - false, new Vector3())); - } + bool success = SynchronousRestObjectPoster.BeginPostObject( + "POST", m_RestURL+"/SaveMessage/", im); + + if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) + { + IClientAPI client = FindClient(new UUID(im.fromAgentID)); + if (client == null) + return; + + client.SendInstantMessage(new GridInstantMessage( + null, new UUID(im.toAgentID), + "System", new UUID(im.fromAgentID), + (byte)InstantMessageDialog.MessageFromAgent, + "User is not logged in. "+ + (success ? "Message saved." : "Message not saved"), + false, new Vector3())); } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 4a4cac9..e51d9ee 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3730,8 +3730,11 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); { CollidingMessage.Colliders = colliding; - foreach (SceneObjectGroup att in Attachments) - Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage); + lock (m_attachments) + { + foreach (SceneObjectGroup att in m_attachments) + Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 11d7c2b..f153504 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3252,7 +3252,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here // m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); // m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); - msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; + DateTime dt = DateTime.UtcNow; + + // Ticks from UtcNow, but make it look like local. Evil, huh? + dt = DateTime.SpecifyKind(dt, DateTimeKind.Local); + + try + { + // Convert that to the PST timezone + TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("America/Los_Angeles"); + dt = TimeZoneInfo.ConvertTime(dt, timeZoneInfo); + } + catch + { + // No logging here, as it could be VERY spammy + } + + // And make it look local again to fool the unix time util + dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc); + + msg.timestamp = (uint)Util.ToUnixTime(dt); + //if (client != null) //{ msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; -- cgit v1.1 From 3368e3853ae931e8e7137dc10a410265b4afbd5a Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 4 Jul 2010 06:45:04 -0700 Subject: Check cached asset to make sure it contains data, and if not, re-request --- OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index 1f40312..ad18a23 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -151,8 +151,8 @@ namespace OpenSim.Services.Connectors AssetBase asset = null; if (m_Cache != null) asset = m_Cache.Get(id); - - if (asset == null) + + if (asset == null || asset.Data == null || asset.Data.Length == 0) { asset = SynchronousRestObjectRequester. MakeRequest("GET", uri, 0); @@ -229,7 +229,7 @@ namespace OpenSim.Services.Connectors if (m_Cache != null) asset = m_Cache.Get(id); - if (asset == null) + if (asset == null || asset.Data == null || asset.Data.Length == 0) { bool result = false; -- cgit v1.1 From f3e902092af7924f5104ffef15937820df532108 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 4 Jul 2010 12:51:48 -0700 Subject: Add System.Core assembly reference to two projects so that TimeZoneInfo can be used --- prebuild.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/prebuild.xml b/prebuild.xml index 4158ed1..9b81542 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1407,6 +1407,7 @@ ../../../bin/ + @@ -2405,6 +2406,7 @@ ../../../../../../bin/ + -- cgit v1.1 From 7665013ad8c7ac876955dc803619405dfa2af71d Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 4 Jul 2010 19:25:54 -0700 Subject: Correct positioning of timeout modifier in the SynchronousRestObjectRequester --- OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs index bb3b8b1..f07f7ab 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs @@ -77,6 +77,7 @@ namespace OpenSim.Framework.Servers.HttpServer WebRequest request = WebRequest.Create(requestUrl); request.Method = verb; + request.Timeout = pTimeout * 1000; if ((verb == "POST") || (verb == "PUT")) { @@ -96,7 +97,6 @@ namespace OpenSim.Framework.Servers.HttpServer int length = (int) buffer.Length; request.ContentLength = length; - request.Timeout = pTimeout * 1000; Stream requestStream = null; try { -- cgit v1.1 From 5b68343361cbd000a2f024b37797ec235abb7207 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 4 Jul 2010 19:28:39 -0700 Subject: The majority of the Undo fix. There is still an issue with Rotation which i'll address next; however position undo and scale undo should be working just fine now. Also removed some residual debug logging. --- OpenSim/Framework/UndoStack.cs | 9 ++- .../Region/Framework/Scenes/SceneObjectGroup.cs | 38 +++++----- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 61 ++++++++--------- .../Scenes/Serialization/SceneObjectSerializer.cs | 4 +- OpenSim/Region/Framework/Scenes/UndoState.cs | 80 ++++++++++++++++++++-- 5 files changed, 135 insertions(+), 57 deletions(-) diff --git a/OpenSim/Framework/UndoStack.cs b/OpenSim/Framework/UndoStack.cs index 3799180..4cd779a 100644 --- a/OpenSim/Framework/UndoStack.cs +++ b/OpenSim/Framework/UndoStack.cs @@ -88,7 +88,14 @@ namespace OpenSim.Framework public T Peek() { - return m_undolist[m_undolist.Count - 1]; + if (m_undolist.Count > 0) + { + return m_undolist[m_undolist.Count - 1]; + } + else + { + return default(T); + } } public void Clear() diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index da664da..34712b8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -355,7 +355,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach(SceneObjectPart p in m_parts.Values) { - p.StoreUndoState(true); + p.StoreUndoState(UndoType.STATE_GROUP_ROTATION); } } finally @@ -435,7 +435,6 @@ namespace OpenSim.Region.Framework.Scenes get { return m_rootPart.GroupPosition; } set { - Vector3 val = value; if ((m_scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || m_scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) @@ -464,7 +463,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in m_parts.Values) { part.IgnoreUndoUpdate = false; - part.StoreUndoState(true); + part.StoreUndoState(UndoType.STATE_GROUP_POSITION); part.GroupPosition = val; } lockPartsForRead(false); @@ -1488,7 +1487,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) { - part.StoreUndoState(); + part.StoreUndoState(UndoType.STATE_PRIM_ALL); part.OnGrab(offsetPos, remoteClient); } @@ -3245,6 +3244,9 @@ namespace OpenSim.Region.Framework.Scenes prevScale.X *= x; prevScale.Y *= y; prevScale.Z *= z;; + + part.IgnoreUndoUpdate = false; + part.StoreUndoState(UndoType.STATE_GROUP_SCALE); part.IgnoreUndoUpdate = true; part.Resize(prevScale); part.IgnoreUndoUpdate = false; @@ -3253,11 +3255,12 @@ namespace OpenSim.Region.Framework.Scenes { foreach (SceneObjectPart obPart in m_parts.Values) { - obPart.IgnoreUndoUpdate = false; - obPart.StoreUndoState(true); - obPart.IgnoreUndoUpdate = true; if (obPart.UUID != m_rootPart.UUID) { + obPart.IgnoreUndoUpdate = false; + obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE); + obPart.IgnoreUndoUpdate = true; + Vector3 currentpos = new Vector3(obPart.OffsetPosition); currentpos.X *= x; currentpos.Y *= y; @@ -3296,14 +3299,11 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateGroupPosition(Vector3 pos) { - foreach (SceneObjectPart part in Children.Values) - { - part.StoreUndoState(); - } if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) { if (IsAttachment) { + m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION); m_rootPart.AttachedPos = pos; } if (RootPart.GetStatusSandbox()) @@ -3336,7 +3336,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = GetChildPart(localID); foreach (SceneObjectPart parts in Children.Values) { - parts.StoreUndoState(); + parts.StoreUndoState(UndoType.STATE_PRIM_POSITION); } if (part != null) { @@ -3361,7 +3361,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (SceneObjectPart part in Children.Values) { - part.StoreUndoState(); + part.StoreUndoState(UndoType.STATE_PRIM_POSITION); } Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); Vector3 oldPos = @@ -3409,7 +3409,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (SceneObjectPart parts in Children.Values) { - parts.StoreUndoState(); + parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION); } m_rootPart.UpdateRotation(rot); @@ -3433,7 +3433,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (SceneObjectPart parts in Children.Values) { - parts.StoreUndoState(); + parts.StoreUndoState(UndoType.STATE_GROUP_ROTATION); } m_rootPart.UpdateRotation(rot); @@ -3460,7 +3460,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = GetChildPart(localID); foreach (SceneObjectPart parts in Children.Values) { - parts.StoreUndoState(); + parts.StoreUndoState(UndoType.STATE_PRIM_ROTATION); } if (part != null) { @@ -3496,7 +3496,7 @@ namespace OpenSim.Region.Framework.Scenes part.UpdateRotation(rot); part.OffsetPosition = pos; part.IgnoreUndoUpdate = false; - part.StoreUndoState(); + part.StoreUndoState(UndoType.STATE_PRIM_ROTATION); } } } @@ -3510,7 +3510,7 @@ namespace OpenSim.Region.Framework.Scenes Quaternion axRot = rot; Quaternion oldParentRot = m_rootPart.RotationOffset; - m_rootPart.StoreUndoState(); + m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION); m_rootPart.UpdateRotation(rot); if (m_rootPart.PhysActor != null) { @@ -3542,7 +3542,7 @@ namespace OpenSim.Region.Framework.Scenes if (childpart != m_rootPart) { childpart.IgnoreUndoUpdate = false; - childpart.StoreUndoState(); + childpart.StoreUndoState(UndoType.STATE_PRIM_ROTATION); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 72ad281..93a23ca 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -697,7 +697,7 @@ namespace OpenSim.Region.Framework.Scenes get { return m_offsetPosition; } set { - StoreUndoState(); + StoreUndoState(UndoType.STATE_PRIM_POSITION); m_offsetPosition = value; if (ParentGroup != null && !ParentGroup.IsDeleted) @@ -759,7 +759,7 @@ namespace OpenSim.Region.Framework.Scenes set { - StoreUndoState(); + StoreUndoState(UndoType.STATE_PRIM_ROTATION); m_rotationOffset = value; PhysicsActor actor = PhysActor; @@ -958,7 +958,7 @@ namespace OpenSim.Region.Framework.Scenes get { return m_shape.Scale; } set { - StoreUndoState(); + StoreUndoState(UndoType.STATE_PRIM_SCALE); if (m_shape != null) { m_shape.Scale = value; @@ -1522,7 +1522,7 @@ namespace OpenSim.Region.Framework.Scenes { m_redo.Clear(); } - StoreUndoState(); + StoreUndoState(UndoType.STATE_ALL); } public byte ConvertScriptUintToByte(uint indata) @@ -2721,7 +2721,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void Resize(Vector3 scale) { - StoreUndoState(); + StoreUndoState(UndoType.STATE_PRIM_SCALE); m_shape.Scale = scale; ParentGroup.HasGroupChanged = true; @@ -3504,13 +3504,11 @@ namespace OpenSim.Region.Framework.Scenes m_parentGroup.ScheduleGroupForTerseUpdate(); //m_parentGroup.ScheduleGroupForFullUpdate(); } - public void StoreUndoState() + public void StoreUndoState(UndoType type) { - StoreUndoState(false); - } - public void StoreUndoState(bool group) - { - if (!Undoing) + + + if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing)) { if (!IgnoreUndoUpdate) { @@ -3521,17 +3519,25 @@ namespace OpenSim.Region.Framework.Scenes if (m_undo.Count > 0) { UndoState last = m_undo.Peek(); - if (last != null) - { - if (last.Compare(this)) - return; - } + } if (m_parentGroup.GetSceneMaxUndo() > 0) { - UndoState nUndo = new UndoState(this); - nUndo.GroupChange = group; + UndoState lastUndo = m_undo.Peek(); + + UndoState nUndo = new UndoState(this, type); + + if (lastUndo != null) + { + TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated); + if (ts.TotalMilliseconds < 500) + { + //Delete the last entry since it was less than 500 milliseconds ago + nUndo.Merge(lastUndo); + m_undo.Pop(); + } + } m_undo.Push(nUndo); } @@ -4008,20 +4014,13 @@ namespace OpenSim.Region.Framework.Scenes if (m_undo.Count > 0) { UndoState nUndo = null; - if (m_parentGroup.GetSceneMaxUndo() > 0) - { - nUndo = new UndoState(this); - } UndoState goback = m_undo.Pop(); - m_log.Debug("Got goback"); - if (goback == null) - { - m_log.Debug("it's null"); - } - else + if (m_parentGroup.GetSceneMaxUndo() > 0) { - m_log.Debug(goback.GroupPosition.ToString()); + nUndo = new UndoState(this, goback.Type); } + + if (goback != null) { goback.PlaybackState(this); @@ -4036,13 +4035,13 @@ namespace OpenSim.Region.Framework.Scenes { lock (m_redo) { + UndoState gofwd = m_redo.Pop(); if (m_parentGroup.GetSceneMaxUndo() > 0) { - UndoState nUndo = new UndoState(this); + UndoState nUndo = new UndoState(this, gofwd.Type); m_undo.Push(nUndo); } - UndoState gofwd = m_redo.Pop(); if (gofwd != null) gofwd.PlayfwdState(this); } diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 5bdaa17..77e477f 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -105,7 +105,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization sceneObject.AddPart(part); part.LinkNum = linkNum; part.TrimPermissions(); - part.StoreUndoState(); + part.StoreUndoState(UndoType.STATE_ALL); reader.Close(); sr.Close(); } @@ -231,7 +231,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization if (originalLinkNum != 0) part.LinkNum = originalLinkNum; - part.StoreUndoState(); + part.StoreUndoState(UndoType.STATE_ALL); reader.Close(); sr.Close(); } diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index 77381ab..ad05351 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs @@ -27,26 +27,43 @@ using OpenMetaverse; using OpenSim.Region.Framework.Interfaces; +using System; namespace OpenSim.Region.Framework.Scenes { + [Flags] + public enum UndoType + { + STATE_PRIM_POSITION = 1, + STATE_PRIM_ROTATION = 2, + STATE_PRIM_SCALE = 4, + STATE_PRIM_ALL = 7, + STATE_GROUP_POSITION = 8, + STATE_GROUP_ROTATION = 16, + STATE_GROUP_SCALE = 32, + STATE_GROUP_ALL = 56, + STATE_ALL = 63 + } + public class UndoState { public Vector3 Position = Vector3.Zero; public Vector3 Scale = Vector3.Zero; public Quaternion Rotation = Quaternion.Identity; - public bool GroupChange = false; public Vector3 GroupPosition = Vector3.Zero; public Quaternion GroupRotation = Quaternion.Identity; public Vector3 GroupScale = Vector3.Zero; + public DateTime LastUpdated = DateTime.Now; + public UndoType Type; - public UndoState(SceneObjectPart part) + public UndoState(SceneObjectPart part, UndoType type) { + Type = type; if (part != null) { if (part.ParentID == 0) { - GroupScale = part.Shape.Scale; + GroupScale = part.ParentGroup.RootPart.Shape.Scale; //FUBAR WARNING: Do NOT get the group's absoluteposition here //or you'll experience a loop and/or a stack issue @@ -55,6 +72,7 @@ namespace OpenSim.Region.Framework.Scenes Position = part.ParentGroup.RootPart.AbsolutePosition; Rotation = part.RotationOffset; Scale = part.Shape.Scale; + LastUpdated = DateTime.Now; } else { @@ -67,10 +85,54 @@ namespace OpenSim.Region.Framework.Scenes Position = part.OffsetPosition; Rotation = part.RotationOffset; Scale = part.Shape.Scale; + LastUpdated = DateTime.Now; } } } - + public void Merge(UndoState last) + { + if ((Type & UndoType.STATE_GROUP_POSITION) == 0 || ((last.Type & UndoType.STATE_GROUP_POSITION) >= (Type & UndoType.STATE_GROUP_POSITION))) + { + GroupPosition = last.GroupPosition; + Position = last.Position; + } + if ((Type & UndoType.STATE_GROUP_SCALE) == 0 || ((last.Type & UndoType.STATE_GROUP_SCALE) >= (Type & UndoType.STATE_GROUP_SCALE))) + { + Console.WriteLine("Setting groupscale to " + last.GroupScale.ToString()); + GroupScale = last.GroupScale; + Scale = last.Scale; + } + if ((Type & UndoType.STATE_GROUP_ROTATION) == 0 || ((last.Type & UndoType.STATE_GROUP_ROTATION) >= (Type & UndoType.STATE_GROUP_ROTATION))) + { + GroupRotation = last.GroupRotation; + Rotation = last.Rotation; + } + if ((Type & UndoType.STATE_PRIM_POSITION) == 0 || ((last.Type & UndoType.STATE_PRIM_POSITION) >= (Type & UndoType.STATE_PRIM_POSITION))) + { + Position = last.Position; + } + if ((Type & UndoType.STATE_PRIM_SCALE) == 0 || ((last.Type & UndoType.STATE_PRIM_SCALE) >= (Type & UndoType.STATE_PRIM_SCALE))) + { + Scale = last.Scale; + } + if ((Type & UndoType.STATE_PRIM_ROTATION) == 0 || ((last.Type & UndoType.STATE_PRIM_ROTATION) >= (Type & UndoType.STATE_PRIM_ROTATION))) + { + Rotation = last.Rotation; + } + Type = Type | last.Type; + } + public bool Compare(UndoState undo) + { + if (undo == null || Position == null) return false; + if (undo.Position == Position && undo.Rotation == Rotation && undo.Scale == Scale && undo.GroupPosition == GroupPosition && undo.GroupScale == GroupScale && undo.GroupRotation == GroupRotation) + { + return true; + } + else + { + return false; + } + } public bool Compare(SceneObjectPart part) { if (part != null) @@ -96,6 +158,14 @@ namespace OpenSim.Region.Framework.Scenes public void PlaybackState(SceneObjectPart part) { + bool GroupChange = false; + if ((Type & UndoType.STATE_GROUP_POSITION) != 0 + || (Type & UndoType.STATE_GROUP_ROTATION) != 0 + || (Type & UndoType.STATE_GROUP_SCALE) != 0) + { + GroupChange = true; + } + if (part != null) { part.Undoing = true; @@ -113,6 +183,7 @@ namespace OpenSim.Region.Framework.Scenes { if (GroupChange) { + part.ParentGroup.RootPart.Undoing = true; if (Position != Vector3.Zero) { //Calculate the scale... @@ -125,6 +196,7 @@ namespace OpenSim.Region.Framework.Scenes part.ParentGroup.Rotation = GroupRotation; } + part.ParentGroup.RootPart.Undoing = false; } else { -- cgit v1.1 From c616335019dc9419460407930af4e40e84663efa Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 4 Jul 2010 19:58:52 -0700 Subject: Rotation undo fix and remove a debug chatter i missed. Still not working: Individual child prim rotational undo and special cases where the root prim was moved or rotated (all the children then need to restore their offsets). Coming shortly. --- OpenSim/Region/Framework/Scenes/UndoState.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index ad05351..f9601e6 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs @@ -68,7 +68,7 @@ namespace OpenSim.Region.Framework.Scenes //FUBAR WARNING: Do NOT get the group's absoluteposition here //or you'll experience a loop and/or a stack issue GroupPosition = part.ParentGroup.RootPart.AbsolutePosition; - GroupRotation = part.ParentGroup.Rotation; + GroupRotation = part.ParentGroup.GroupRotation; Position = part.ParentGroup.RootPart.AbsolutePosition; Rotation = part.RotationOffset; Scale = part.Shape.Scale; @@ -98,7 +98,6 @@ namespace OpenSim.Region.Framework.Scenes } if ((Type & UndoType.STATE_GROUP_SCALE) == 0 || ((last.Type & UndoType.STATE_GROUP_SCALE) >= (Type & UndoType.STATE_GROUP_SCALE))) { - Console.WriteLine("Setting groupscale to " + last.GroupScale.ToString()); GroupScale = last.GroupScale; Scale = last.Scale; } @@ -184,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes if (GroupChange) { part.ParentGroup.RootPart.Undoing = true; - if (Position != Vector3.Zero) + if (GroupPosition != Vector3.Zero) { //Calculate the scale... Vector3 gs = part.Shape.Scale; @@ -193,7 +192,7 @@ namespace OpenSim.Region.Framework.Scenes //Scale first since it can affect our position part.ParentGroup.GroupResize(gs * scale, part.LocalId); part.ParentGroup.AbsolutePosition = GroupPosition; - part.ParentGroup.Rotation = GroupRotation; + part.ParentGroup.UpdateGroupRotationR(GroupRotation); } part.ParentGroup.RootPart.Undoing = false; -- cgit v1.1 From 8849b9af8bd3260152dede0ccf61fd98137ef6c5 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 4 Jul 2010 20:45:11 -0700 Subject: Fix single prim rotation undo. All UNDO functions are now working correctly except for when the root prim is moved or rotated as a single prim (coming soon). --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 34712b8..7492601 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3492,11 +3492,11 @@ namespace OpenSim.Region.Framework.Scenes } else { + part.StoreUndoState(UndoType.STATE_PRIM_ROTATION); part.IgnoreUndoUpdate = true; part.UpdateRotation(rot); part.OffsetPosition = pos; part.IgnoreUndoUpdate = false; - part.StoreUndoState(UndoType.STATE_PRIM_ROTATION); } } } -- cgit v1.1 From be5dd04150bae69745de3cf5efde3d5be288dd71 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 5 Jul 2010 03:58:18 -0700 Subject: Bring "Redo" up to date with "Undo" so it works too --- OpenSim/Region/Framework/Scenes/UndoState.cs | 41 +++++++--------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index f9601e6..2af3316 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs @@ -123,7 +123,7 @@ namespace OpenSim.Region.Framework.Scenes public bool Compare(UndoState undo) { if (undo == null || Position == null) return false; - if (undo.Position == Position && undo.Rotation == Rotation && undo.Scale == Scale && undo.GroupPosition == GroupPosition && undo.GroupScale == GroupScale && undo.GroupRotation == GroupRotation) + if (undo.Position == Position && undo.Rotation == Rotation && undo.Scale == Scale && undo.GroupPosition == GroupPosition && undo.GroupScale == GroupScale && undo.GroupRotation == GroupRotation) { return true; } @@ -155,7 +155,7 @@ namespace OpenSim.Region.Framework.Scenes return false; } - public void PlaybackState(SceneObjectPart part) + private void RestoreState(SceneObjectPart part) { bool GroupChange = false; if ((Type & UndoType.STATE_GROUP_POSITION) != 0 @@ -172,7 +172,7 @@ namespace OpenSim.Region.Framework.Scenes if (part.ParentID == 0 && GroupChange == false) { if (Position != Vector3.Zero) - part.ParentGroup.AbsolutePosition = Position; + part.ParentGroup.AbsolutePosition = Position; part.RotationOffset = Rotation; if (Scale != Vector3.Zero) part.Resize(Scale); @@ -193,7 +193,7 @@ namespace OpenSim.Region.Framework.Scenes part.ParentGroup.GroupResize(gs * scale, part.LocalId); part.ParentGroup.AbsolutePosition = GroupPosition; part.ParentGroup.UpdateGroupRotationR(GroupRotation); - + } part.ParentGroup.RootPart.Undoing = false; } @@ -211,35 +211,13 @@ namespace OpenSim.Region.Framework.Scenes } } + public void PlaybackState(SceneObjectPart part) + { + RestoreState(part); + } public void PlayfwdState(SceneObjectPart part) { - if (part != null) - { - part.Undoing = true; - - if (part.ParentID == 0) - { - if (Position != Vector3.Zero) - part.ParentGroup.AbsolutePosition = Position; - if (Rotation != Quaternion.Identity) - part.UpdateRotation(Rotation); - if (Scale != Vector3.Zero) - part.Resize(Scale); - part.ParentGroup.ScheduleGroupForTerseUpdate(); - } - else - { - if (Position != Vector3.Zero) - part.OffsetPosition = Position; - if (Rotation != Quaternion.Identity) - part.UpdateRotation(Rotation); - if (Scale != Vector3.Zero) - part.Resize(Scale); - part.ScheduleTerseUpdate(); - } - part.Undoing = false; - - } + RestoreState(part); } } public class LandUndoState @@ -267,3 +245,4 @@ namespace OpenSim.Region.Framework.Scenes } } } + -- cgit v1.1 From e947d04038f7b42929368d9f7b6d440be139e675 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 5 Jul 2010 05:44:35 -0700 Subject: Undo fix is now complete. This commit repairs the special case of the root prim moving or rotating independently of the rest of the group. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 49 +++++++++++++++++----- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 - OpenSim/Region/Framework/Scenes/UndoState.cs | 5 ++- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 7492601..f85d3d9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -3386,10 +3386,27 @@ namespace OpenSim.Region.Framework.Scenes } lockPartsForRead(false); - AbsolutePosition = newPos; + //We have to set undoing here because otherwise an undo state will be saved + if (!m_rootPart.Undoing) + { + m_rootPart.Undoing = true; + AbsolutePosition = newPos; + m_rootPart.Undoing = false; + } + else + { + AbsolutePosition = newPos; + } HasGroupChanged = true; - ScheduleGroupForTerseUpdate(); + if (m_rootPart.Undoing) + { + ScheduleGroupForFullUpdate(); + } + else + { + ScheduleGroupForTerseUpdate(); + } } public void OffsetForNewRegion(Vector3 offset) @@ -3488,7 +3505,16 @@ namespace OpenSim.Region.Framework.Scenes if (part.UUID == m_rootPart.UUID) { UpdateRootRotation(rot); - AbsolutePosition = pos; + if (!m_rootPart.Undoing) + { + m_rootPart.Undoing = true; + AbsolutePosition = pos; + m_rootPart.Undoing = false; + } + else + { + AbsolutePosition = pos; + } } else { @@ -3511,6 +3537,12 @@ namespace OpenSim.Region.Framework.Scenes Quaternion oldParentRot = m_rootPart.RotationOffset; m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION); + bool cancelUndo = false; + if (!m_rootPart.Undoing) + { + m_rootPart.Undoing = true; + cancelUndo = true; + } m_rootPart.UpdateRotation(rot); if (m_rootPart.PhysActor != null) { @@ -3534,18 +3566,13 @@ namespace OpenSim.Region.Framework.Scenes newRot *= Quaternion.Inverse(axRot); prim.RotationOffset = newRot; prim.ScheduleTerseUpdate(); + prim.IgnoreUndoUpdate = false; } } - - foreach (SceneObjectPart childpart in Children.Values) + if (cancelUndo == true) { - if (childpart != m_rootPart) - { - childpart.IgnoreUndoUpdate = false; - childpart.StoreUndoState(UndoType.STATE_PRIM_ROTATION); - } + m_rootPart.Undoing = false; } - lockPartsForRead(false); m_rootPart.ScheduleTerseUpdate(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 93a23ca..3327b1e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3506,8 +3506,6 @@ namespace OpenSim.Region.Framework.Scenes } public void StoreUndoState(UndoType type) { - - if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing)) { if (!IgnoreUndoUpdate) diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs index 2af3316..f71b507 100644 --- a/OpenSim/Region/Framework/Scenes/UndoState.cs +++ b/OpenSim/Region/Framework/Scenes/UndoState.cs @@ -172,8 +172,9 @@ namespace OpenSim.Region.Framework.Scenes if (part.ParentID == 0 && GroupChange == false) { if (Position != Vector3.Zero) - part.ParentGroup.AbsolutePosition = Position; - part.RotationOffset = Rotation; + + part.ParentGroup.UpdateSinglePosition(Position, part.LocalId); + part.ParentGroup.UpdateSingleRotation(Rotation, part.LocalId); if (Scale != Vector3.Zero) part.Resize(Scale); part.ParentGroup.ScheduleGroupForTerseUpdate(); -- cgit v1.1 From 90c5555d6d542a0c8605759c0036af1c83601ddf Mon Sep 17 00:00:00 2001 From: Mike Rieker Date: Tue, 6 Jul 2010 02:22:47 +0000 Subject: rewrote hanging llParseStringKeepNulls() --- .../Shared/Api/Implementation/LSL_Api.cs | 315 ++++++++++----------- 1 file changed, 145 insertions(+), 170 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index fb191e6..1459778 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -562,23 +562,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api double sqx = q1.x*q1.x; double sqy = q1.z*q1.z; double sqz = q1.y*q1.y; - double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor - double test = q1.x*q1.z + q1.y*q1.s; - if (test > 0.4999*unit) { // singularity at north pole - eul.z = 2 * Math.Atan2(q1.x,q1.s); - eul.y = Math.PI/2; - eul.x = 0; - return eul; - } - if (test < -0.4999*unit) { // singularity at south pole - eul.z = -2 * Math.Atan2(q1.x,q1.s); - eul.y = -Math.PI/2; - eul.x = 0; - return eul; - } + double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor + double test = q1.x*q1.z + q1.y*q1.s; + if (test > 0.4999*unit) { // singularity at north pole + eul.z = 2 * Math.Atan2(q1.x,q1.s); + eul.y = Math.PI/2; + eul.x = 0; + return eul; + } + if (test < -0.4999*unit) { // singularity at south pole + eul.z = -2 * Math.Atan2(q1.x,q1.s); + eul.y = -Math.PI/2; + eul.x = 0; + return eul; + } eul.z = Math.Atan2(2*q1.z*q1.s-2*q1.x*q1.y , sqx - sqy - sqz + sqw); - eul.y = Math.Asin(2*test/unit); - eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw); + eul.y = Math.Asin(2*test/unit); + eul.x = Math.Atan2(2*q1.x*q1.s-2*q1.z*q1.y , -sqx + sqy - sqz + sqw); return eul; } @@ -804,53 +804,53 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // This method mimics the 180 errors found in SL // See www.euclideanspace.com... angleBetween - LSL_Vector vec_a = a; - LSL_Vector vec_b = b; - - // Eliminate zero length - LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a); - LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b); - if (vec_a_mag < 0.00001 || - vec_b_mag < 0.00001) - { - return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); - } - - // Normalize - vec_a = llVecNorm(vec_a); - vec_b = llVecNorm(vec_b); - - // Calculate axis and rotation angle - LSL_Vector axis = vec_a % vec_b; - LSL_Float cos_theta = vec_a * vec_b; - - // Check if parallel - if (cos_theta > 0.99999) - { - return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); - } - - // Check if anti-parallel - else if (cos_theta < -0.99999) - { - LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a); - if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0); - return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0); - } - else // other rotation - { - LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f; - axis = llVecNorm(axis); - double x, y, z, s, t; - s = Math.Cos(theta); - t = Math.Sin(theta); - x = axis.x * t; - y = axis.y * t; - z = axis.z * t; - return new LSL_Rotation(x,y,z,s); - } - } - + LSL_Vector vec_a = a; + LSL_Vector vec_b = b; + + // Eliminate zero length + LSL_Float vec_a_mag = LSL_Vector.Mag(vec_a); + LSL_Float vec_b_mag = LSL_Vector.Mag(vec_b); + if (vec_a_mag < 0.00001 || + vec_b_mag < 0.00001) + { + return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + + // Normalize + vec_a = llVecNorm(vec_a); + vec_b = llVecNorm(vec_b); + + // Calculate axis and rotation angle + LSL_Vector axis = vec_a % vec_b; + LSL_Float cos_theta = vec_a * vec_b; + + // Check if parallel + if (cos_theta > 0.99999) + { + return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + + // Check if anti-parallel + else if (cos_theta < -0.99999) + { + LSL_Vector orthog_axis = new LSL_Vector(1.0, 0.0, 0.0) - (vec_a.x / (vec_a * vec_a) * vec_a); + if (LSL_Vector.Mag(orthog_axis) < 0.000001) orthog_axis = new LSL_Vector(0.0, 0.0, 1.0); + return new LSL_Rotation((float)orthog_axis.x, (float)orthog_axis.y, (float)orthog_axis.z, 0.0); + } + else // other rotation + { + LSL_Float theta = (LSL_Float)Math.Acos(cos_theta) * 0.5f; + axis = llVecNorm(axis); + double x, y, z, s, t; + s = Math.Cos(theta); + t = Math.Sin(theta); + x = axis.x * t; + y = axis.y * t; + z = axis.z * t; + return new LSL_Rotation(x,y,z,s); + } + } + public void llWhisper(int channelID, string text) { m_host.AddScriptLPS(1); @@ -8627,130 +8627,105 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) { - int beginning = 0; - int srclen = src.Length; - int seplen = separators.Length; - object[] separray = separators.Data; - int spclen = spacers.Length; - object[] spcarray = spacers.Data; - int mlen = seplen+spclen; + int srclen = src.Length; + int seplen = separators.Length; + object[] separray = separators.Data; + int spclen = spacers.Length; + object[] spcarray = spacers.Data; - int[] offset = new int[mlen+1]; - bool[] active = new bool[mlen]; + int outlen = 0; + LSL_String[] outarray = new LSL_String[srclen*2+1]; - int best; - int j; - - // Initial capacity reduces resize cost - - LSL_List tokens = new LSL_List(); + int i, j, lastUsed; m_host.AddScriptLPS(1); - // All entries are initially valid - - for (int i = 0; i < mlen; i++) - active[i] = true; - - offset[mlen] = srclen; - - while (beginning < srclen) - { - - best = mlen; // as bad as it gets + /* + * Point to beginning of current non-delimeter string. + */ + lastUsed = 0; - // Scan for separators + /* + * Scan through source string from beginning to end. + */ + for (i = 0; i < srclen;) { - for (j = 0; j < seplen; j++) - { - if (active[j]) - { - // scan all of the markers - if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) - { - // not present at all - active[j] = false; - } - else - { - // present and correct - if (offset[j] < offset[best]) - { - // closest so far - best = j; - if (offset[best] == beginning) - break; - } - } + /* + * See if rest of string (starting at i) matches any separator. + */ + string rest = src.Substring(i); + for (j = 0; j < seplen; j ++) { + string sep = separray[j].ToString(); + if ((sep.Length > 0) && rest.StartsWith(sep)) { + + /* + * Separator matched, output string from end of last delimeter to beginning of this one. + */ + outarray[outlen++] = new LSL_String(src.Substring(lastUsed,i-lastUsed)); + + /* + * Remove separator from input string. + */ + i += sep.Length; + + /* + * Next non-delimeter starts where this separator left off. + */ + lastUsed = i; + goto nextsrc; } } - // Scan for spacers - - if (offset[best] != beginning) - { - for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) - { - if (active[j]) - { - // scan all of the markers - if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1) - { - // not present at all - active[j] = false; - } - else - { - // present and correct - if (offset[j] < offset[best]) - { - // closest so far - best = j; - } - } - } + /* + * See if rest of string (starting at i) matches any spacer. + */ + for (j = 0; j < spclen; j ++) { + string spc = spcarray[j].ToString(); + if ((spc.Length > 0) && rest.StartsWith(spc)) { + + /* + * Spacer matched, output string from end of last delimeter to beginning of this one. + * Then output the spacer itself. + */ + outarray[outlen++] = new LSL_String(src.Substring(lastUsed,i-lastUsed)); + outarray[outlen++] = new LSL_String(spc); + + /* + * Remove spacer from input string. + */ + i += spc.Length; + + /* + * Next non-delimeter starts where this spacer left off. + */ + lastUsed = i; + goto nextsrc; } } - // This is the normal exit from the scanning loop - - if (best == mlen) - { - // no markers were found on this pass - // so we're pretty much done - tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning))); - break; - } - - // Otherwise we just add the newly delimited token - // and recalculate where the search should continue. - - tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); - - if (best < seplen) - { - beginning = offset[best] + (separray[best].ToString()).Length; - } - else - { - beginning = offset[best] + (spcarray[best - seplen].ToString()).Length; - tokens.Add(new LSL_String(spcarray[best - seplen].ToString())); - } + /* + * Didn't match any separator or spacer, skip over it and it + * becomes part of the non-delimeter string starting with + * lastUsed. + */ + i ++; + nextsrc:; } - // This an awkward an not very intuitive boundary case. If the - // last substring is a tokenizer, then there is an implied trailing - // null list entry. Hopefully the single comparison will not be too - // arduous. Alternatively the 'break' could be replced with a return - // but that's shabby programming. + /* + * Output last non-delimeter (including a possible null string if + * delimeter ran to end of source string). + */ + outarray[outlen++] = new LSL_String(src.Substring(lastUsed)); - if (beginning == srclen) - { - if (srclen != 0) - tokens.Add(new LSL_String("")); + /* + * Make up an exact-sized output array suitable for an LSL_List object. + */ + object[] outlist = new object[outlen]; + for (i = 0; i < outlen; i ++) { + outlist[i] = outarray[i]; } - - return tokens; + return new LSL_List(outlist); } public LSL_Integer llGetObjectPermMask(int mask) -- cgit v1.1 From faaef1b498a09d9f12a77c46391f2379af8ec7ac Mon Sep 17 00:00:00 2001 From: Mike Rieker Date: Tue, 6 Jul 2010 23:59:06 +0000 Subject: minimizes temp garbage for llParseStringKeepNulls() and uses common routine for llParseStringKeepNulls()/llParseString2List() --- .../Shared/Api/Implementation/LSL_Api.cs | 201 +++++++-------------- 1 file changed, 67 insertions(+), 134 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index b9b3318..b335ae6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5877,74 +5877,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers) { - m_host.AddScriptLPS(1); - LSL_List ret = new LSL_List(); - LSL_List spacers = new LSL_List(); - if (in_spacers.Length > 0 && separators.Length > 0) - { - for (int i = 0; i < in_spacers.Length; i++) - { - object s = in_spacers.Data[i]; - for (int j = 0; j < separators.Length; j++) - { - if (separators.Data[j].ToString() == s.ToString()) - { - s = null; - break; - } - } - if (s != null) - { - spacers.Add(s); - } - } - } - object[] delimiters = new object[separators.Length + spacers.Length]; - separators.Data.CopyTo(delimiters, 0); - spacers.Data.CopyTo(delimiters, separators.Length); - bool dfound = false; - do - { - dfound = false; - int cindex = -1; - string cdeli = ""; - for (int i = 0; i < delimiters.Length; i++) - { - int index = str.IndexOf(delimiters[i].ToString()); - bool found = index != -1; - if (found && String.Empty != delimiters[i].ToString()) - { - if ((cindex > index) || (cindex == -1)) - { - cindex = index; - cdeli = delimiters[i].ToString(); - } - dfound = dfound || found; - } - } - if (cindex != -1) - { - if (cindex > 0) - { - ret.Add(new LSL_String(str.Substring(0, cindex))); - } - // Cannot use spacers.Contains() because spacers may be either type String or LSLString - for (int j = 0; j < spacers.Length; j++) - { - if (spacers.Data[j].ToString() == cdeli) - { - ret.Add(new LSL_String(cdeli)); - break; - } - } - str = str.Substring(cindex + cdeli.Length); - } - } while (dfound); - if (str != "") - { - ret.Add(new LSL_String(str)); - } - return ret; + return ParseString2List(str, separators, in_spacers, false); } public LSL_Integer llOverMyLand(string id) @@ -8616,8 +8549,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // The function returns an ordered list // representing the tokens found in the supplied // sources string. If two successive tokenizers - // are encountered, then a NULL entry is added - // to the list. + // are encountered, then a null-string entry is + // added to the list. // // It is a precondition that the source and // toekizer lisst are non-null. If they are null, @@ -8625,7 +8558,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // while their lengths are being determined. // // A small amount of working memoryis required - // of approximately 8*#tokenizers. + // of approximately 8*#tokenizers + 8*srcstrlen. // // There are many ways in which this function // can be implemented, this implementation is @@ -8641,109 +8574,109 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // and eliminates redundant tokenizers as soon // as is possible. // - // The implementation tries to avoid any copying - // of arrays or other objects. + // The implementation tries to minimize temporary + // garbage generation. // public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) { + return ParseString2List(src, separators, spacers, true); + } + + private LSL_List ParseString2List(string src, LSL_List separators, LSL_List spacers, bool keepNulls) + { int srclen = src.Length; int seplen = separators.Length; object[] separray = separators.Data; int spclen = spacers.Length; object[] spcarray = spacers.Data; + int dellen = 0; + string[] delarray = new string[seplen+spclen]; int outlen = 0; - LSL_String[] outarray = new LSL_String[srclen*2+1]; + string[] outarray = new string[srclen*2+1]; - int i, j, lastUsed; + int i, j; + string d; m_host.AddScriptLPS(1); /* - * Point to beginning of current non-delimeter string. + * Convert separator and spacer lists to C# strings. + * Also filter out null strings so we don't hang. */ - lastUsed = 0; + for (i = 0; i < seplen; i ++) { + d = separray[i].ToString(); + if (d.Length > 0) { + delarray[dellen++] = d; + } + } + seplen = dellen; + + for (i = 0; i < spclen; i ++) { + d = spcarray[i].ToString(); + if (d.Length > 0) { + delarray[dellen++] = d; + } + } /* * Scan through source string from beginning to end. */ - for (i = 0; i < srclen;) { + for (i = 0;;) { /* - * See if rest of string (starting at i) matches any separator. + * Find earliest delimeter in src starting at i (if any). */ - string rest = src.Substring(i); - for (j = 0; j < seplen; j ++) { - string sep = separray[j].ToString(); - if ((sep.Length > 0) && rest.StartsWith(sep)) { - - /* - * Separator matched, output string from end of last delimeter to beginning of this one. - */ - outarray[outlen++] = new LSL_String(src.Substring(lastUsed,i-lastUsed)); - - /* - * Remove separator from input string. - */ - i += sep.Length; - - /* - * Next non-delimeter starts where this separator left off. - */ - lastUsed = i; - goto nextsrc; + int earliestDel = -1; + int earliestSrc = srclen; + string earliestStr = null; + for (j = 0; j < dellen; j ++) { + d = delarray[j]; + if (d != null) { + int index = src.IndexOf(d, i); + if (index < 0) { + delarray[j] = null; // delim nowhere in src, don't check it anymore + } else if (index < earliestSrc) { + earliestSrc = index; // where delimeter starts in source string + earliestDel = j; // where delimeter is in delarray[] + earliestStr = d; // the delimeter string from delarray[] + if (index == i) break; // can't do any better than found at beg of string + } } } /* - * See if rest of string (starting at i) matches any spacer. + * Output source string starting at i through start of earliest delimeter. */ - for (j = 0; j < spclen; j ++) { - string spc = spcarray[j].ToString(); - if ((spc.Length > 0) && rest.StartsWith(spc)) { - - /* - * Spacer matched, output string from end of last delimeter to beginning of this one. - * Then output the spacer itself. - */ - outarray[outlen++] = new LSL_String(src.Substring(lastUsed,i-lastUsed)); - outarray[outlen++] = new LSL_String(spc); - - /* - * Remove spacer from input string. - */ - i += spc.Length; - - /* - * Next non-delimeter starts where this spacer left off. - */ - lastUsed = i; - goto nextsrc; - } + if (keepNulls || (earliestSrc > i)) { + outarray[outlen++] = src.Substring(i, earliestSrc - i); } /* - * Didn't match any separator or spacer, skip over it and it - * becomes part of the non-delimeter string starting with - * lastUsed. + * If no delimeter found at or after i, we're done scanning. */ - i ++; - nextsrc:; - } + if (earliestDel < 0) break; - /* - * Output last non-delimeter (including a possible null string if - * delimeter ran to end of source string). - */ - outarray[outlen++] = new LSL_String(src.Substring(lastUsed)); + /* + * If delimeter was a spacer, output the spacer. + */ + if (earliestDel >= seplen) { + outarray[outlen++] = earliestStr; + } + + /* + * Look at rest of src string following delimeter. + */ + i = earliestSrc + earliestStr.Length; + } /* * Make up an exact-sized output array suitable for an LSL_List object. */ object[] outlist = new object[outlen]; for (i = 0; i < outlen; i ++) { - outlist[i] = outarray[i]; + outlist[i] = new LSL_String(outarray[i]); } return new LSL_List(outlist); } -- cgit v1.1 From 0116b80795af199c8a68c6ba536c208ea82253d3 Mon Sep 17 00:00:00 2001 From: dahlia Date: Thu, 8 Jul 2010 10:14:02 -0700 Subject: fix a potential division by zero --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 1ea52c5..326f327 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -257,12 +257,17 @@ namespace OpenSim.Region.ScriptEngine.Shared public static double Mag(Vector3 v) { return Math.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z); - } - - public static Vector3 Norm(Vector3 vector) - { - double mag = Mag(vector); - return new Vector3(vector.x / mag, vector.y / mag, vector.z / mag); + } + + public static Vector3 Norm(Vector3 vector) + { + double mag = Mag(vector); + if (mag > 0.0) + { + double invMag = 1.0 / mag; + return vector * invMag; + } + return new Vector3(0, 0, 0); } #endregion -- cgit v1.1 From 05b35eb57ce7cc9fa068f34b5798a6c7c3fc09a8 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 8 Jul 2010 18:17:02 +0100 Subject: Correct a merge artefact --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 27 ---------------------- 1 file changed, 27 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 9f29420..ecfc68f 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -11496,33 +11496,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP //m_log.Debug("asset request " + requestID); } - if (null == asset) - { - if ((m_hyperAssets != null) && (transferRequest.TransferInfo.SourceType < 2000)) - { - // Try the user's inventory, but only if it's different from the regions' - string userAssets = m_hyperAssets.GetUserAssetServer(AgentId); - if ((userAssets != string.Empty) && (userAssets != m_hyperAssets.GetSimAssetServer())) - { - m_log.DebugFormat("[CLIENT]: asset {0} not found in local asset storage. Trying user's storage.", id); - if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) - transferRequest.TransferInfo.SourceType = 2222; // marker - else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) - transferRequest.TransferInfo.SourceType = 3333; // marker - - m_assetService.Get(userAssets + "/" + id, transferRequest, AssetReceived); - return; - } - } - - //m_log.DebugFormat("[ASSET CACHE]: Asset transfer request for asset which is {0} already known to be missing. Dropping", requestID); - - //We need to send a TransferAbort here, so the client doesn't wait forever for the asset, - //which causes it to not request any more for a while. Which is bad. - SendTransferAbort(transferRequest); - return; - } - // Scripts cannot be retrieved by direct request if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset && asset.Type == 10) return; -- cgit v1.1 From c7a2e1b2d40dff80bf7b65ee01b9e7916de0f5e4 Mon Sep 17 00:00:00 2001 From: dahlia Date: Thu, 8 Jul 2010 10:17:28 -0700 Subject: llVecNorm() now returns a zero-length vector when one is supplied as input. Addresses Mantis #4752 --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e4e087f..eaaa9eb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -450,13 +450,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llVecNorm(LSL_Vector v) { - m_host.AddScriptLPS(1); - double mag = LSL_Vector.Mag(v); - LSL_Vector nor = new LSL_Vector(); - nor.x = v.x / mag; - nor.y = v.y / mag; - nor.z = v.z / mag; - return nor; + m_host.AddScriptLPS(1); + return LSL_Vector.Norm(v); } public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) -- cgit v1.1 From 8aa5f30082f667fc23ccfdb839e04ba8b72f872c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 10 Jul 2010 10:51:49 +0200 Subject: Make taken items go back to the folder they came from --- .../Framework/InventoryAccess/InventoryAccessModule.cs | 14 ++++++++++++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 3 +++ 2 files changed, 17 insertions(+) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 90b7b51..2057c65 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -322,6 +322,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } + // Override and put into where it came from, if it came + // from anywhere in inventory + // + if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) + { + if (objectGroup.RootPart.FromFolderID != UUID.Zero) + { + InventoryFolderBase f = new InventoryFolderBase(objectGroup.RootPart.FromFolderID, userID); + folder = m_Scene.InventoryService.GetFolder(f); + } + } + if (folder == null) // None of the above { folder = new InventoryFolderBase(folderID); @@ -485,6 +497,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); + group.RootPart.FromFolderID = item.Folder; + if (!m_Scene.Permissions.CanRezObject( group.Children.Count, remoteClient.AgentId, pos) && !attachment) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 3327b1e..b552cdc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -180,6 +180,9 @@ namespace OpenSim.Region.Framework.Scenes public UUID FromItemID; [XmlIgnore] + public UUID FromFolderID; + + [XmlIgnore] public int STATUS_ROTATE_X; [XmlIgnore] -- cgit v1.1 From cecd660388e0cda34115be44955758e8221a77d1 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 10 Jul 2010 18:48:49 -0700 Subject: Fix an issue where the SynchronousRestObjectRequester will fail if a webserver does not report a content length (-1), but the content is still valid --- OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs index f07f7ab..077a1e8 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestObjectRequester.cs @@ -118,7 +118,7 @@ namespace OpenSim.Framework.Servers.HttpServer { using (WebResponse resp = request.GetResponse()) { - if (resp.ContentLength > 0) + if (resp.ContentLength != 0) { Stream respStream = resp.GetResponseStream(); XmlSerializer deserializer = new XmlSerializer(typeof(TResponse)); -- cgit v1.1 From cea856cfc294fb546332bb86abe9f70d791013d5 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 10 Jul 2010 19:00:12 -0700 Subject: Fix the synchronousrestformsrequester so it will successfully handle a response from a server which does not provide a valid content length header --- OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs index b0cf34d..92a6caa 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs @@ -99,7 +99,7 @@ namespace OpenSim.Framework.Servers.HttpServer { using (WebResponse resp = request.GetResponse()) { - if (resp.ContentLength > 0) + if (resp.ContentLength != 0) { Stream respStream = null; try -- cgit v1.1 From 7f0f11304f0979355d75538ab7326b687b62e76e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 11 Jul 2010 14:26:57 +0200 Subject: Add scripted controllers into agent intersim messaging --- OpenSim/Framework/ChildAgentDataUpdate.cs | 65 ++++++++++++++++++++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 4 ++ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 33 +++++++++++ 3 files changed, 102 insertions(+) diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index a1ac84c..89ee39c 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -265,6 +265,46 @@ namespace OpenSim.Framework } } + public class ControllerData + { + public UUID ItemID; + public uint IgnoreControls; + public uint EventControls; + + public ControllerData(UUID item, uint ignore, uint ev) + { + ItemID = item; + IgnoreControls = ignore; + EventControls = ev; + } + + public ControllerData(OSDMap args) + { + UnpackUpdateMessage(args); + } + + public OSDMap PackUpdateMessage() + { + OSDMap controldata = new OSDMap(); + controldata["item"] = OSD.FromUUID(ItemID); + controldata["ignore"] = OSD.FromInteger(IgnoreControls); + controldata["event"] = OSD.FromInteger(EventControls); + + return controldata; + } + + + public void UnpackUpdateMessage(OSDMap args) + { + if (args["item"] != null) + ItemID = args["item"].AsUUID(); + if (args["ignore"] != null) + IgnoreControls = (uint)args["ignore"].AsInteger(); + if (args["event"] != null) + EventControls = (uint)args["event"].AsInteger(); + } + } + public class AgentData : IAgentData { private UUID m_id; @@ -313,6 +353,9 @@ namespace OpenSim.Framework public UUID[] Wearables; public AttachmentData[] Attachments; + // Scripted + public ControllerData[] Controllers; + public string CallbackURI; public virtual OSDMap Pack() @@ -403,6 +446,14 @@ namespace OpenSim.Framework args["attachments"] = attachs; } + if ((Controllers != null) && (Controllers.Length > 0)) + { + OSDArray controls = new OSDArray(Controllers.Length); + foreach (ControllerData ctl in Controllers) + controls.Add(ctl.PackUpdateMessage()); + args["controllers"] = controls; + } + if ((CallbackURI != null) && (!CallbackURI.Equals(""))) args["callback_uri"] = OSD.FromString(CallbackURI); @@ -559,6 +610,20 @@ namespace OpenSim.Framework } } + if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) + { + OSDArray controls = (OSDArray)(args["controllers"]); + Controllers = new ControllerData[controls.Count]; + int i = 0; + foreach (OSD o in controls) + { + if (o.Type == OSDType.Map) + { + Controllers[i++] = new ControllerData((OSDMap)o); + } + } + } + if (args["callback_uri"] != null) CallbackURI = args["callback_uri"].AsString(); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b552cdc..e87766e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4145,6 +4145,10 @@ namespace OpenSim.Region.Framework.Scenes case 16: _nextOwnerMask = ApplyMask(_nextOwnerMask, set, mask) & baseMask; + // Prevent the client from creating no mod, no copy + // objects + if ((_nextOwnerMask & (uint)PermissionMask.Copy) == 0) + _nextOwnerMask |= (uint)PermissionMask.Transfer; break; } SendFullUpdateToAllClients(); diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 5ac7755..efe3365 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3365,6 +3365,18 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); cAgent.Attachments = attachs; } + lock (scriptedcontrols) + { + ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; + int i = 0; + + foreach (ScriptControllers c in scriptedcontrols.Values) + { + controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); + } + cAgent.Controllers = controls; + } + // Animations try { @@ -3446,6 +3458,27 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); } catch { } + try + { + lock (scriptedcontrols) + { + if (cAgent.Controllers != null) + { + scriptedcontrols.Clear(); + + foreach (ControllerData c in cAgent.Controllers) + { + ScriptControllers sc = new ScriptControllers(); + sc.itemID = c.ItemID; + sc.ignoreControls = (ScriptControlled)c.IgnoreControls; + sc.eventControls = (ScriptControlled)c.EventControls; + + scriptedcontrols[sc.itemID] = sc; + } + } + } + } + catch { } // Animations try { -- cgit v1.1 From 5f4105d48c9776423a730e6480a2587bd64550a5 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Mon, 12 Jul 2010 13:55:56 -0700 Subject: Removed the CHANGED_COLOR event post from the Color accessor in SOP. This is not the correct usage of this changed event - it's only supposed to be posted when the /textures/ change colour or alpha transparency, not the floating text. This fixes several race conditions in scripts ported from SL. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index e87766e..f8ae321 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -882,7 +882,6 @@ namespace OpenSim.Region.Framework.Scenes set { m_color = value; - TriggerScriptChangedEvent(Changed.COLOR); /* ScheduleFullUpdate() need not be called b/c after * setting the color, the text will be set, so then -- cgit v1.1 From 31cbd6d113c8039c70f874479039cb3eaf689c2a Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 13 Jul 2010 18:23:23 +0200 Subject: Add CreateSelected flag onto objects rezzed from inventory --- .../CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 2057c65..e5f1e70 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -498,6 +498,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); group.RootPart.FromFolderID = item.Folder; + group.RootPart.CreateSelected = true if (!m_Scene.Permissions.CanRezObject( group.Children.Count, remoteClient.AgentId, pos) -- cgit v1.1 From 89c1c5c35a7665315e66e46276d1b6066f3cf2b8 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 13 Jul 2010 20:40:23 +0200 Subject: Revamp the permissions propagation. This MAY mess up. Please test. Change the slam bit from 3 to 4. Assume the old slam bit is always set. The new slam bit is a "changed owner" bit, correcting a bug where an item passed from the creator to another with less than full perms, then back (sale test) would arrive back full perm. Lots of in-code docs. --- OpenSim/Data/Tests/RegionTests.cs | 2 +- .../InventoryAccess/InventoryAccessModule.cs | 54 ++++++--- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 134 +++++++++++++++------ OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- .../Framework/Scenes/SceneObjectGroup.Inventory.cs | 5 +- .../Framework/Scenes/SceneObjectPartInventory.cs | 1 - 6 files changed, 140 insertions(+), 58 deletions(-) diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 1f654d3..2506678 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -781,7 +781,7 @@ namespace OpenSim.Data.Tests // Ownership changes when you drop an object into an object // owned by someone else Assert.That(t.OwnerID,Is.EqualTo(sog.RootPart.OwnerID), "Assert.That(t.OwnerID,Is.EqualTo(sog.RootPart.OwnerID))"); - Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 8), "Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 8))"); + Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 16), "Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 8))"); Assert.That(t.ParentID,Is.EqualTo(sog.RootPart.FolderID), "Assert.That(t.ParentID,Is.EqualTo(sog.RootPart.FolderID))"); Assert.That(t.ParentPartID,Is.EqualTo(sog.RootPart.UUID), "Assert.That(t.ParentPartID,Is.EqualTo(sog.RootPart.UUID))"); } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index e5f1e70..1a7da61 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -381,12 +381,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if ((nextPerms & (uint)PermissionMask.Modify) == 0) perms &= ~(uint)PermissionMask.Modify; + // Make sure all bits but the ones we want are clear + // on take. + // This will be applied to the current perms, so + // it will do what we want. + objectGroup.RootPart.NextOwnerMask &= + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify); + objectGroup.RootPart.NextOwnerMask |= + (uint)PermissionMask.Move; + item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask; item.CurrentPermissions = item.BasePermissions; item.NextPermissions = objectGroup.RootPart.NextOwnerMask; item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask; item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask; - item.CurrentPermissions |= 8; // Slam! + + // Magic number badness. Maybe this deserves an enum. + // bit 4 (16) is the "Slam" bit, it means treat as passed + // and apply next owner perms on rez + item.CurrentPermissions |= 16; // Slam! } else { @@ -396,7 +411,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask; item.GroupPermissions = objectGroup.RootPart.GroupMask; - item.CurrentPermissions |= 8; // Slam! + item.CurrentPermissions &= + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify | + (uint)PermissionMask.Move | + 7); // Preserve folded permissions } // TODO: add the new fields (Flags, Sale info, etc) @@ -498,7 +518,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); group.RootPart.FromFolderID = item.Folder; - group.RootPart.CreateSelected = true + + // If it's rezzed in world, select it. Much easier to + // find small items. + // + if (!attachment) + group.RootPart.CreateSelected = true; if (!m_Scene.Permissions.CanRezObject( group.Children.Count, remoteClient.AgentId, pos) @@ -572,7 +597,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess List partList = new List(group.Children.Values); group.SetGroup(remoteClient.ActiveGroupId, remoteClient); - if (rootPart.OwnerID != item.Owner) + if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; @@ -580,14 +605,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (m_Scene.Permissions.PropagatePermissions()) { - if ((item.CurrentPermissions & 8) != 0) + foreach (SceneObjectPart part in partList) { - foreach (SceneObjectPart part in partList) - { - part.EveryoneMask = item.EveryOnePermissions; - part.NextOwnerMask = item.NextPermissions; - part.GroupMask = 0; // DO NOT propagate here - } + part.EveryoneMask = item.EveryOnePermissions; + part.NextOwnerMask = item.NextPermissions; + part.GroupMask = 0; // DO NOT propagate here } group.ApplyNextOwnerPermissions(); @@ -596,19 +618,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess foreach (SceneObjectPart part in partList) { - if (part.OwnerID != item.Owner) + if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); - } - else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam! - { - part.EveryoneMask = item.EveryOnePermissions; - part.NextOwnerMask = item.NextPermissions; - part.GroupMask = 0; // DO NOT propagate here } + part.EveryoneMask = item.EveryOnePermissions; + part.NextOwnerMask = item.NextPermissions; } rootPart.TrimPermissions(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 38a5456..5796194 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -280,6 +280,10 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, UUID itemID, InventoryItemBase itemUpd) { + // This one will let people set next perms on items in agent + // inventory. Rut-Roh. Whatever. Make this secure. Yeah. + // + // Passing something to another avatar or a an object will already InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = InventoryService.GetItem(item); @@ -289,11 +293,9 @@ namespace OpenSim.Region.Framework.Scenes { item.Name = itemUpd.Name; item.Description = itemUpd.Description; - item.NextPermissions = itemUpd.NextPermissions; - item.CurrentPermissions |= 8; // Slam! - item.EveryOnePermissions = itemUpd.EveryOnePermissions; - item.GroupPermissions = itemUpd.GroupPermissions; - + item.NextPermissions = itemUpd.NextPermissions & item.BasePermissions; + item.EveryOnePermissions = itemUpd.EveryOnePermissions & item.BasePermissions; + item.GroupPermissions = itemUpd.GroupPermissions & item.BasePermissions; item.GroupID = itemUpd.GroupID; item.GroupOwned = itemUpd.GroupOwned; item.CreationDate = itemUpd.CreationDate; @@ -399,28 +401,96 @@ namespace OpenSim.Region.Framework.Scenes if (Permissions.PropagatePermissions() && recipient != senderId) { - // First, make sore base is limited to the next perms - itemCopy.BasePermissions = item.BasePermissions & (item.NextPermissions | (uint)PermissionMask.Move); - // By default, current equals base - itemCopy.CurrentPermissions = itemCopy.BasePermissions & item.CurrentPermissions; - - // If this is an object, replace current perms - // with folded perms + // Trying to do this right this time. This is evil. If + // you believe in Good, go elsewhere. Vampires and other + // evil creatores only beyond this point. You have been + // warned. + + // We're going to mask a lot of things by the next perms + // Tweak the next perms to be nicer to our data + // + // In this mask, all the bits we do NOT want to mess + // with are set. These are: + // + // Transfer + // Copy + // Modufy + uint permsMask = ~ ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify); + + // Now, reduce the next perms to the mask bits + // relevant to the operation + uint nextPerms = permsMask | (item.NextPermissions & + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify)); + + // nextPerms now has all bits set, except for the actual + // next permission bits. + + // This checks for no mod, no copy, no trans. + // This indicates an error or messed up item. Do it like + // SL and assume trans + if (nextPerms == permsMask) + nextPerms |= (uint)PermissionMask.Transfer; + + // Inventory owner perms are the logical AND of the + // folded perms and the root prim perms, however, if + // the root prim is mod, the inventory perms will be + // mod. This happens on "take" and is of little concern + // here, save for preventing escalation + + // This hack ensures that items previously permalocked + // get unlocked when they're passed or rezzed + uint basePerms = item.BasePermissions | + (uint)PermissionMask.Move; + uint ownerPerms = item.CurrentPermissions; + + // Mask the base permissions. This is a conservative + // approach altering only the three main perms + basePerms &= nextPerms; + + // If this is an object, root prim perms may be more + // permissive than folded perms. Use folded perms as + // a mask if (item.InvType == (int)InventoryType.Object) { - itemCopy.CurrentPermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); - itemCopy.CurrentPermissions |= (item.CurrentPermissions & 7) << 13; + // Create a safe mask for the current perms + uint foldedPerms = (item.CurrentPermissions & 7) << 13; + foldedPerms |= permsMask; + + bool isRootMod = (item.CurrentPermissions & + (uint)PermissionMask.Modify) != 0 ? + true : false; + + // Mask the owner perms to the folded perms + ownerPerms &= foldedPerms; + + // If the root was mod, let the mask reflect that + if (isRootMod) + ownerPerms |= (uint)PermissionMask.Modify; } - // Ensure there is no escalation - itemCopy.CurrentPermissions &= (item.NextPermissions | (uint)PermissionMask.Move); + // These will be applied to the root prim at next rez. + // The slam bit (bit 3) and folded permission (bits 0-2) + // are preserved due to the above mangling + ownerPerms &= nextPerms; - // Need slam bit on xfer - itemCopy.CurrentPermissions |= 8; + // Assign to the actual item. Make sure the slam bit is + // set, if it wasn't set before. + itemCopy.BasePermissions = basePerms; + itemCopy.CurrentPermissions = ownerPerms | 16; // Slam itemCopy.NextPermissions = item.NextPermissions; - itemCopy.EveryOnePermissions = 0; + // This preserves "everyone can move" + itemCopy.EveryOnePermissions = item.EveryOnePermissions & + nextPerms; + + // Intentionally killing "share with group" here, as + // the recipient will not have the group this is + // set to itemCopy.GroupPermissions = 0; } else @@ -922,7 +992,7 @@ namespace OpenSim.Region.Framework.Scenes else agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; - agentItem.CurrentPermissions |= 8; + agentItem.CurrentPermissions |= 16; // Slam agentItem.NextPermissions = taskItem.NextPermissions; agentItem.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; @@ -1113,7 +1183,7 @@ namespace OpenSim.Region.Framework.Scenes (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); destTaskItem.BasePermissions = srcTaskItem.BasePermissions & (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); - destTaskItem.CurrentPermissions |= 8; // Slam! + destTaskItem.CurrentPermissions |= 16; // Slam! } } @@ -1497,7 +1567,7 @@ namespace OpenSim.Region.Framework.Scenes srcTaskItem.NextPermissions; destTaskItem.BasePermissions = srcTaskItem.BasePermissions & srcTaskItem.NextPermissions; - destTaskItem.CurrentPermissions |= 8; // Slam! + destTaskItem.CurrentPermissions |= 16; // Slam! } } @@ -1889,17 +1959,14 @@ namespace OpenSim.Region.Framework.Scenes group.SetGroup(sourcePart.GroupID, null); - if (rootPart.OwnerID != item.OwnerID) + if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0) { if (Permissions.PropagatePermissions()) { - if ((item.CurrentPermissions & 8) != 0) + foreach (SceneObjectPart part in partList) { - foreach (SceneObjectPart part in partList) - { - part.EveryoneMask = item.EveryonePermissions; - part.NextOwnerMask = item.NextPermissions; - } + part.EveryoneMask = item.EveryonePermissions; + part.NextOwnerMask = item.NextPermissions; } group.ApplyNextOwnerPermissions(); } @@ -1907,17 +1974,14 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in partList) { - if (part.OwnerID != item.OwnerID) + if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.OwnerID; part.Inventory.ChangeInventoryOwner(item.OwnerID); } - else if ((item.CurrentPermissions & 8) != 0) // Slam! - { - part.EveryoneMask = item.EveryonePermissions; - part.NextOwnerMask = item.NextPermissions; - } + part.EveryoneMask = item.EveryonePermissions; + part.NextOwnerMask = item.NextPermissions; } rootPart.TrimPermissions(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c5fb198..d323e19 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4818,7 +4818,7 @@ namespace OpenSim.Region.Framework.Scenes part.NextOwnerMask; item.GroupPermissions = part.GroupMask & part.NextOwnerMask; - item.CurrentPermissions |= 8; // Slam! + item.CurrentPermissions |= 16; // Slam! item.CreationDate = Util.UnixTimeSinceEpoch(); if (InventoryService.AddItem(item)) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 1149a20..70b37fb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -170,13 +170,14 @@ namespace OpenSim.Region.Framework.Scenes taskItem.GroupPermissions = item.GroupPermissions & item.NextPermissions; taskItem.NextPermissions = item.NextPermissions; - taskItem.CurrentPermissions |= 8; + // We're adding this to a prim we don't own. Force + // owner change + taskItem.CurrentPermissions |= 16; // Slam } else { taskItem.BasePermissions = item.BasePermissions; taskItem.CurrentPermissions = item.CurrentPermissions; - taskItem.CurrentPermissions |= 8; taskItem.EveryonePermissions = item.EveryOnePermissions; taskItem.GroupPermissions = item.GroupPermissions; taskItem.NextPermissions = item.NextPermissions; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 2cde8f3..0066158 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -1082,7 +1082,6 @@ namespace OpenSim.Region.Framework.Scenes item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) item.CurrentPermissions &= ~(uint)PermissionMask.Modify; - item.CurrentPermissions |= 8; } item.OwnerChanged = true; item.CurrentPermissions &= item.NextPermissions; -- cgit v1.1 From 7ab103c96f3e82cac592f20d61358e1928da8e27 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Tue, 13 Jul 2010 20:37:13 +0000 Subject: Rewrite collision dictionary handling, cleans up deleted obects/avs. Fixes occasional collision event failure. ChOde only. --- .gitignore | 3 + OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs | 90 +++++++++++++++++----- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 67 +++++++--------- OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs | 6 ++ 4 files changed, 106 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index 8d3f2b2..e2bef71 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .project .settings +.gitignore *.csproj *.csproj.user *.build @@ -10,6 +11,7 @@ *.pidb *.dll.build *.dll +*.log *.VisualState.xml */*/obj */*/*/obj @@ -23,6 +25,7 @@ */*/*/*/*/bin */*/*/*/*/*/bin */*/*/*/*/*/*/bin +addon-modules/ bin/Debug/*.dll bin/*.dll.mdb bin/*.db diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index 38c38b6..61c16b8 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -565,7 +565,29 @@ namespace OpenSim.Region.Physics.OdePlugin CAPSULE_RADIUS = 0.01f; } + + if(Shell != IntPtr.Zero) + { + try + { + d.GeomDestroy(Shell); + } + catch (System.AccessViolationException) + { + m_log.Error("[PHYSICS]: PrimGeom dead"); + } + // Remove any old entries +//string tShell; +//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell); +//Console.WriteLine("**** Remove {0}", tShell); + if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell); + if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell); + } + Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); + _parent_scene.geom_name_map[Shell] = m_name; + _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; +//Console.WriteLine("**** Create {2} Dicts: actor={0} name={1}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, m_name); d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); d.GeomSetCollideBits(Shell, (int)m_collisionFlags); @@ -931,10 +953,23 @@ namespace OpenSim.Region.Physics.OdePlugin Body = IntPtr.Zero; } - if (Shell != IntPtr.Zero) + if(Shell != IntPtr.Zero) { - d.GeomDestroy(Shell); - _parent_scene.geom_name_map.Remove(Shell); + try + { + d.GeomDestroy(Shell); + } + catch (System.AccessViolationException) + { + m_log.Error("[PHYSICS]: PrimGeom dead"); + } + // Remove any old entries +//string tShell; +//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell); +//Console.WriteLine("**** Remove {0}", tShell); + + if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell); + if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell); Shell = IntPtr.Zero; } @@ -1097,11 +1132,24 @@ namespace OpenSim.Region.Physics.OdePlugin Body = IntPtr.Zero; } - - if (Shell != IntPtr.Zero) + + if(Shell != IntPtr.Zero) { - d.GeomDestroy(Shell); - _parent_scene.geom_name_map.Remove(Shell); + try + { + d.GeomDestroy(Shell); + } + catch (System.AccessViolationException) + { + m_log.Error("[PHYSICS]: PrimGeom dead"); + } + // Remove any old entries +//string tShell; +//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell); +//Console.WriteLine("**** Remove {0}", tShell); + + if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell); + if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell); Shell = IntPtr.Zero; } } @@ -1277,9 +1325,6 @@ namespace OpenSim.Region.Physics.OdePlugin + (Amotor!=IntPtr.Zero ? "Amotor ":"")); } AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor); - - _parent_scene.geom_name_map[Shell] = m_name; - _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; _parent_scene.AddCharacter(this); } else @@ -1299,17 +1344,28 @@ namespace OpenSim.Region.Physics.OdePlugin { //kill the body d.BodyDestroy(Body); - Body = IntPtr.Zero; } - if (Shell != IntPtr.Zero) + if(Shell != IntPtr.Zero) { - d.GeomDestroy(Shell); - _parent_scene.geom_name_map.Remove(Shell); + try + { + d.GeomDestroy(Shell); + } + catch (System.AccessViolationException) + { + m_log.Error("[PHYSICS]: PrimGeom dead"); + } + // Remove any old entries +//string tShell; +//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell); +//Console.WriteLine("**** Remove {0}", tShell); + + if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell); + if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell); Shell = IntPtr.Zero; } - } m_isPhysical = m_tainted_isPhysical; @@ -1327,13 +1383,9 @@ namespace OpenSim.Region.Physics.OdePlugin CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); d.BodyDestroy(Body); - d.GeomDestroy(Shell); AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); Velocity = Vector3.Zero; - - _parent_scene.geom_name_map[Shell] = m_name; - _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; } else { diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 7ce01dc..6b17ce7 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -142,7 +142,7 @@ namespace OpenSim.Region.Physics.OdePlugin private OdeScene _parent_scene; public IntPtr m_targetSpace = IntPtr.Zero; public IntPtr prim_geom; - public IntPtr prev_geom; +// public IntPtr prev_geom; public IntPtr _triMeshData; private IntPtr _linkJointGroup = IntPtr.Zero; @@ -274,7 +274,7 @@ namespace OpenSim.Region.Physics.OdePlugin prim_geom = IntPtr.Zero; - prev_geom = IntPtr.Zero; +// prev_geom = IntPtr.Zero; if (!pos.IsFinite()) { @@ -776,13 +776,26 @@ namespace OpenSim.Region.Physics.OdePlugin public void SetGeom(IntPtr geom) { - prev_geom = prim_geom; + if(prim_geom != IntPtr.Zero) + { + // Remove any old entries +//string tPA; +//_parent_scene.geom_name_map.TryGetValue(prim_geom, out tPA); +//Console.WriteLine("**** Remove {0}", tPA); + if(_parent_scene.geom_name_map.ContainsKey(prim_geom)) _parent_scene.geom_name_map.Remove(prim_geom); + if(_parent_scene.actor_name_map.ContainsKey(prim_geom)) _parent_scene.actor_name_map.Remove(prim_geom); + d.GeomDestroy(prim_geom); + } + prim_geom = geom; //Console.WriteLine("SetGeom to " + prim_geom + " for " + m_primName); if (prim_geom != IntPtr.Zero) { + _parent_scene.geom_name_map[prim_geom] = this.m_primName; + _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this; d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); +//Console.WriteLine("**** Create {2} Dicts: actor={0} name={1}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, this.m_primName); } if (childPrim) @@ -1774,17 +1787,17 @@ namespace OpenSim.Region.Physics.OdePlugin public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) { //Console.WriteLine("CreateGeom:"); - if (_mesh != null) + if (_mesh != null) // Special - make mesh { setMesh(_parent_scene, _mesh); } - else + else // not a mesh { - if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) // special profile?? { - if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) // Equi-size { - if (((_size.X / 2f) > 0f)) + if (((_size.X / 2f) > 0f)) // Has size { _parent_scene.waitForSpaceUnlock(m_targetSpace); try @@ -1815,7 +1828,7 @@ namespace OpenSim.Region.Physics.OdePlugin } } } - else + else // not equi-size { _parent_scene.waitForSpaceUnlock(m_targetSpace); try @@ -1832,7 +1845,7 @@ namespace OpenSim.Region.Physics.OdePlugin } } - else + else // not special profile { _parent_scene.waitForSpaceUnlock(m_targetSpace); try @@ -1894,9 +1907,6 @@ namespace OpenSim.Region.Physics.OdePlugin } } - _parent_scene.geom_name_map[prim_geom] = this.m_primName; - _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this; - changeSelectedStatus(timestep); m_taintadd = false; @@ -2045,22 +2055,7 @@ Console.WriteLine(" JointCreateFixed"); { if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) { - - - if (prim_geom != IntPtr.Zero) - { - try - { - d.GeomDestroy(prim_geom); - prim_geom = IntPtr.Zero; - _mesh = null; - } - catch (System.AccessViolationException) - { - prim_geom = IntPtr.Zero; - m_log.Error("[PHYSICS]: PrimGeom dead"); - } - } + _mesh = null; //Console.WriteLine("changePhysicsStatus for " + m_primName ); changeadd(2f); } @@ -2120,8 +2115,6 @@ Console.WriteLine(" JointCreateFixed"); _parent_scene.waitForSpaceUnlock(m_targetSpace); d.SpaceRemove(m_targetSpace, prim_geom); } - d.GeomDestroy(prim_geom); - prim_geom = IntPtr.Zero; // we don't need to do space calculation because the client sends a position update also. // Construction of new prim @@ -2223,16 +2216,8 @@ Console.WriteLine(" JointCreateFixed"); disableBody(); } } - try - { - d.GeomDestroy(prim_geom); - } - catch (System.AccessViolationException) - { - prim_geom = IntPtr.Zero; - m_log.Error("[PHYSICS]: PrimGeom dead"); - } - prim_geom = IntPtr.Zero; + + // we don't need to do space calculation because the client sends a position update also. if (_size.X <= 0) _size.X = 0.01f; if (_size.Y <= 0) _size.Y = 0.01f; diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs index 79e2986..ab084fd 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs @@ -2206,6 +2206,12 @@ namespace OpenSim.Region.Physics.OdePlugin { if (prim.prim_geom != IntPtr.Zero) { + +//string tPA; +//geom_name_map.TryGetValue(prim.prim_geom, out tPA); +//Console.WriteLine("**** Remove {0}", tPA); + if(geom_name_map.ContainsKey(prim.prim_geom)) geom_name_map.Remove(prim.prim_geom); + if(actor_name_map.ContainsKey(prim.prim_geom)) actor_name_map.Remove(prim.prim_geom); d.GeomDestroy(prim.prim_geom); prim.prim_geom = IntPtr.Zero; } -- cgit v1.1 From 8c26c8bbc6d4ee34b5b9255d3807fb4def88367f Mon Sep 17 00:00:00 2001 From: sacha Date: Tue, 13 Jul 2010 21:10:26 +0000 Subject: adding the 'wearble' case for llGetLocalPos. Still not working cause the offsets are not updated (always <0,0,0>) --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5492266..27034ed 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -74,7 +74,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi { - //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected IScriptEngine m_ScriptEngine; protected SceneObjectPart m_host; protected uint m_localID; @@ -2136,6 +2136,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGetLocalPos() { m_host.AddScriptLPS(1); + if (m_host.IsAttachment == true) { +//m_log.DebugFormat("[localpos]: {0}) {1} {2}",m_host.OffsetPosition.X,m_host.OffsetPosition.Y,m_host.OffsetPosition.Z); + return new LSL_Vector(m_host.OffsetPosition.X, + m_host.OffsetPosition.Y, + m_host.OffsetPosition.Z); + } + if (m_host.ParentID != 0) { return new LSL_Vector(m_host.OffsetPosition.X, -- cgit v1.1 From 7270cd0ade15ac7175e8394e085e48955ccb280c Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 13 Jul 2010 14:57:50 -0700 Subject: Second part of the fix for llGetLocalPos; get attachment offset in the root prim of an attachment. This function now behaves in line with SL. --- .../Shared/Api/Implementation/LSL_Api.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 27034ed..976a9ff 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2136,12 +2136,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGetLocalPos() { m_host.AddScriptLPS(1); - if (m_host.IsAttachment == true) { -//m_log.DebugFormat("[localpos]: {0}) {1} {2}",m_host.OffsetPosition.X,m_host.OffsetPosition.Y,m_host.OffsetPosition.Z); - return new LSL_Vector(m_host.OffsetPosition.X, - m_host.OffsetPosition.Y, - m_host.OffsetPosition.Z); - } + if (m_host.IsAttachment == true) { + if (m_host.IsRoot == true) + { + return new LSL_Vector(m_host.AbsolutePosition.X, + m_host.AbsolutePosition.Y, + m_host.AbsolutePosition.Z); + + } + else + { + return new LSL_Vector(m_host.OffsetPosition.X, + m_host.OffsetPosition.Y, + m_host.OffsetPosition.Z); + } + } if (m_host.ParentID != 0) { -- cgit v1.1 From c5891c14c7547dc0cbbf1bd5bf3a0d2923616f25 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Tue, 13 Jul 2010 15:32:35 -0700 Subject: Bail out in AttachToBackup if the group is an attachment --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f85d3d9..7053c02 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -679,6 +679,7 @@ namespace OpenSim.Region.Framework.Scenes ///
public virtual void AttachToBackup() { + if (IsAttachment) return; m_scene.SceneGraph.FireAttachToBackup(this); if (InSceneBackup) -- cgit v1.1 From a7f0af41ab157e09d84aca4ca9135a8aed0757d6 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 13 Jul 2010 23:36:05 +0100 Subject: replace o with ; in oXmlRpcPort in OpenSim.ini.example Thanks to Nebadon for the spot --- bin/OpenSim.ini.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index c1c5639..c296c35 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -1403,4 +1403,4 @@ ; to use to send XMLRPC requests to that script ;XmlRpcRouterModule = "XmlRpcRouterModule" - oXmlRpcPort = 20800 + ;XmlRpcPort = 20800 -- cgit v1.1 From af13c80d6835d7440994e6ad50ff40a8e3aeb99e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 14 Jul 2010 03:59:26 +0200 Subject: Remove getting the object capacity from the money module. It is now set directly from the Region Info (and the region ini file) --- OpenSim/Region/CoreModules/World/Land/LandObject.cs | 4 ++-- OpenSim/Region/Framework/Scenes/Scene.cs | 18 +----------------- .../World/MoneyModule/SampleMoneyModule.cs | 7 +++---- 3 files changed, 6 insertions(+), 23 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 3945142..2a87da2 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -146,7 +146,7 @@ namespace OpenSim.Region.CoreModules.World.Land else { // Normal Calculations - return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.objectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); + return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); } } public int GetSimulatorMaxPrimCount(ILandObject thisObject) @@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.World.Land else { //Normal Calculations - return m_scene.objectCapacity; + return m_scene.RegionInfo.ObjectCapacity; } } #endregion diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d323e19..7c25e87 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -492,8 +492,6 @@ namespace OpenSim.Region.Framework.Scenes set { m_sceneGraph.RestorePresences = value; } } - public int objectCapacity = 45000; - #endregion #region BinaryStats @@ -703,7 +701,7 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.OnSendStatsResult += SendSimStatsPackets; StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; - StatsReporter.SetObjectCapacity(objectCapacity); + StatsReporter.SetObjectCapacity(RegionInfo.ObjectCapacity); // Old /* @@ -4206,20 +4204,6 @@ namespace OpenSim.Region.Framework.Scenes #region Other Methods - public void SetObjectCapacity(int objects) - { - // Region specific config overrides global - // - if (RegionInfo.ObjectCapacity != 0) - objects = RegionInfo.ObjectCapacity; - - if (StatsReporter != null) - { - StatsReporter.SetObjectCapacity(objects); - } - objectCapacity = objects; - } - #endregion public void HandleObjectPermissionsUpdate(IClientAPI controller, UUID agentID, UUID sessionID, byte field, uint localId, uint mask, byte set) diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index 6f5ef9e..653f856 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -138,8 +138,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule public void AddRegion(Scene scene) { // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter. - scene.SetObjectCapacity(ObjectCapacity); - if (m_enabled) { scene.RegisterModuleInterface(this); @@ -252,7 +250,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule if (config == "Economy" && startupConfig != null) { - ObjectCapacity = startupConfig.GetInt("ObjectCapacity", 45000); PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100); PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10); PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4); @@ -701,7 +698,9 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule if (user != null) { - user.SendEconomyData(EnergyEfficiency, ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, + Scene s = LocateSceneClientIn(user.AgentId); + + user.SendEconomyData(EnergyEfficiency, s.RegionInfo.ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor, PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload, TeleportMinPrice, TeleportPriceExponent); -- cgit v1.1 From cbb3a8ab94f8df6963f8045a3ca3795bcbcfe0b5 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 14 Jul 2010 16:21:55 +0200 Subject: Fix a permissions issue --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 15 +++++++++++---- .../Framework/Scenes/SceneObjectGroup.Inventory.cs | 18 +++++++++++------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 5796194..e972382 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -447,10 +447,6 @@ namespace OpenSim.Region.Framework.Scenes (uint)PermissionMask.Move; uint ownerPerms = item.CurrentPermissions; - // Mask the base permissions. This is a conservative - // approach altering only the three main perms - basePerms &= nextPerms; - // If this is an object, root prim perms may be more // permissive than folded perms. Use folded perms as // a mask @@ -466,10 +462,17 @@ namespace OpenSim.Region.Framework.Scenes // Mask the owner perms to the folded perms ownerPerms &= foldedPerms; + basePerms &= foldedPerms; // If the root was mod, let the mask reflect that + // We also need to adjust the base here, because + // we should be able to edit in-inventory perms + // for the root prim, if it's mod. if (isRootMod) + { ownerPerms |= (uint)PermissionMask.Modify; + basePerms |= (uint)PermissionMask.Modify; + } } // These will be applied to the root prim at next rez. @@ -477,6 +480,10 @@ namespace OpenSim.Region.Framework.Scenes // are preserved due to the above mangling ownerPerms &= nextPerms; + // Mask the base permissions. This is a conservative + // approach altering only the three main perms + basePerms &= nextPerms; + // Assign to the actual item. Make sure the slam bit is // set, if it wasn't set before. itemCopy.BasePermissions = basePerms; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 70b37fb..abb4de6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -280,7 +280,7 @@ namespace OpenSim.Region.Framework.Scenes PermissionMask.Move | PermissionMask.Transfer) | 7; - uint ownerMask = 0x7ffffff; + uint ownerMask = 0x7fffffff; foreach (SceneObjectPart part in m_parts.Values) { ownerMask &= part.OwnerMask; @@ -294,12 +294,16 @@ namespace OpenSim.Region.Framework.Scenes if ((ownerMask & (uint)PermissionMask.Transfer) == 0) perms &= ~(uint)PermissionMask.Transfer; - if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Modify) == 0) - perms &= ~((uint)PermissionMask.Modify >> 13); - if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Copy) == 0) - perms &= ~((uint)PermissionMask.Copy >> 13); - if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Transfer) == 0) - perms &= ~((uint)PermissionMask.Transfer >> 13); + // If root prim permissions are applied here, this would screw + // with in-inventory manipulation of the next owner perms + // in a major way. So, let's move this to the give itself. + // Yes. I know. Evil. +// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Modify) == 0) +// perms &= ~((uint)PermissionMask.Modify >> 13); +// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Copy) == 0) +// perms &= ~((uint)PermissionMask.Copy >> 13); +// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Transfer) == 0) +// perms &= ~((uint)PermissionMask.Transfer >> 13); return perms; } -- cgit v1.1 From 0c445239a68688311d6fa7405ef13ceb3e773930 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 14 Jul 2010 19:21:01 +0200 Subject: Remove useless quaternion parameter from AttachObject sig --- OpenSim/Framework/IClientAPI.cs | 2 +- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 2 +- .../Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 8 ++++---- OpenSim/Region/DataSnapshot/ObjectSnapshot.cs | 2 +- OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs | 4 ++-- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index d85b101..100c861 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -57,7 +57,7 @@ namespace OpenSim.Framework RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects); public delegate void ObjectAttach( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent); + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent); public delegate void ModifyTerrain(UUID user, float height, float seconds, byte size, byte action, float north, float west, float south, float east, diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index ecfc68f..82b9958 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -5744,7 +5744,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (att.ObjectData.Length > 0) { - handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation, false); + handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, false); } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index d3d6f25..08b2315 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments get { return false; } } - public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent) + public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent) { m_log.Debug("[ATTACHMENTS MODULE]: Invoking AttachObject"); @@ -86,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return; // Calls attach with a Zero position - if (AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false)) + if (AttachObject(remoteClient, objectLocalID, AttachmentPt, Vector3.Zero, false)) { m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); @@ -109,7 +109,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } public bool AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Vector3 attachPos, bool silent) { SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); if (group != null) @@ -246,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments tainted = true; AttachObject( - remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false); + remoteClient, objatt.LocalId, AttachmentPt, objatt.AbsolutePosition, false); //objatt.ScheduleGroupForFullUpdate(); if (tainted) diff --git a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs index 6e69902..00f6918 100644 --- a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs +++ b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.DataSnapshot.Providers client.OnGrabUpdate += delegate(UUID objectID, Vector3 offset, Vector3 grapPos, IClientAPI remoteClient, List surfaceArgs) { this.Stale = true; }; client.OnObjectAttach += delegate(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, - Quaternion rot, bool silent) { this.Stale = true; }; + bool silent) { this.Stale = true; }; client.OnObjectDuplicate += delegate(uint localID, Vector3 offset, uint dupeFlags, UUID AgentID, UUID GroupID) { this.Stale = true; }; client.OnObjectDuplicateOnRay += delegate(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 958847b..11887e6 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -45,7 +45,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// void AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent); + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent); /// /// Attach an object to an avatar. @@ -58,7 +58,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// true if the object was successfully attached, false otherwise bool AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent); + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Vector3 attachPos, bool silent); /// /// Rez an attachment from user inventory and change inventory status to match. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7c25e87..873a11d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2633,7 +2633,7 @@ namespace OpenSim.Region.Framework.Scenes if (AttachmentsModule != null) AttachmentsModule.AttachObject( - sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false); + sp.ControllingClient, grp.LocalId, (uint)0, grp.AbsolutePosition, false); } else -- cgit v1.1 From bebbe407ee166a0aa22f0ec8d14ada780924f9af Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 14 Jul 2010 19:58:23 +0200 Subject: Major attachments cleanup. Remove unused AttachObject ClientView method Clean up use of AttachObject throughout, reduce number of overloads and number of parameters --- OpenSim/Client/MXP/ClientStack/MXPClientView.cs | 5 - .../Sirikata/ClientStack/SirikataClientView.cs | 5 - .../Client/VWoHTTP/ClientStack/VWHClientView.cs | 5 - OpenSim/Framework/IClientAPI.cs | 1 - .../Region/ClientStack/LindenUDP/LLClientView.cs | 24 ----- .../Avatar/Attachments/AttachmentsModule.cs | 101 ++++++++++----------- .../Region/Examples/SimpleModule/MyNpcCharacter.cs | 4 - .../Framework/Interfaces/IAttachmentsModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +- .../Server/IRCClientView.cs | 5 - .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 4 - .../Shared/Api/Implementation/LSL_Api.cs | 9 -- OpenSim/Tests/Common/Mock/TestClient.cs | 4 - 13 files changed, 49 insertions(+), 123 deletions(-) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 5798a64..ce2e9a1 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -1047,11 +1047,6 @@ namespace OpenSim.Client.MXP.ClientStack // Minimap function, not used. } - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - // Need to translate to MXP somehow - } - public void SetChildAgentThrottle(byte[] throttle) { // Need to translate to MXP somehow diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index 906947e..2063616 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -602,11 +602,6 @@ namespace OpenSim.Client.Sirikata.ClientStack throw new System.NotImplementedException(); } - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - throw new System.NotImplementedException(); - } - public void SetChildAgentThrottle(byte[] throttle) { throw new System.NotImplementedException(); diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 13a27f5..841f9a4 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -608,11 +608,6 @@ namespace OpenSim.Client.VWoHTTP.ClientStack throw new System.NotImplementedException(); } - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - throw new System.NotImplementedException(); - } - public void SetChildAgentThrottle(byte[] throttle) { throw new System.NotImplementedException(); diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 100c861..95aec94 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1019,7 +1019,6 @@ namespace OpenSim.Framework void SendCoarseLocationUpdate(List users, List CoarseLocations); - void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID); void SetChildAgentThrottle(byte[] throttle); void SendAvatarDataImmediate(ISceneEntity avatar); diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 82b9958..754127d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3687,30 +3687,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Primitive Packet/Data Sending Methods - /// - /// - /// - /// - /// - /// - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; - - ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); - // TODO: don't create new blocks if recycling an old packet - attach.AgentData.AgentID = AgentId; - attach.AgentData.SessionID = m_sessionId; - attach.AgentData.AttachmentPoint = attachPoint; - attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; - attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); - attach.ObjectData[0].ObjectLocalID = localID; - attach.ObjectData[0].Rotation = rotation; - attach.Header.Zerocoded = true; - OutPacket(attach, ThrottleOutPacketType.Task); - } - void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) { if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 08b2315..902fb88 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -71,6 +71,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments get { return false; } } + // Called by client + // public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent) { m_log.Debug("[ATTACHMENTS MODULE]: Invoking AttachObject"); @@ -86,7 +88,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return; // Calls attach with a Zero position - if (AttachObject(remoteClient, objectLocalID, AttachmentPt, Vector3.Zero, false)) + if (AttachObject(remoteClient, part.ParentGroup, AttachmentPt, false)) { m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); @@ -108,72 +110,64 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } - public bool AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Vector3 attachPos, bool silent) + public bool AttachObject(IClientAPI remoteClient, SceneObjectGroup group, uint AttachmentPt, bool silent) { - SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); - if (group != null) + Vector3 attachPos = group.AbsolutePosition; + + if (m_scene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) { - if (m_scene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) + // If the attachment point isn't the same as the one previously used + // set it's offset position = 0 so that it appears on the attachment point + // and not in a weird location somewhere unknown. + if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint()) { - // If the attachment point isn't the same as the one previously used - // set it's offset position = 0 so that it appears on the attachment point - // and not in a weird location somewhere unknown. - if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint()) - { - attachPos = Vector3.Zero; - } - - // AttachmentPt 0 means the client chose to 'wear' the attachment. - if (AttachmentPt == 0) - { - // Check object for stored attachment point - AttachmentPt = (uint)group.GetAttachmentPoint(); - } - - // if we still didn't find a suitable attachment point....... - if (AttachmentPt == 0) - { - // Stick it on left hand with Zero Offset from the attachment point. - AttachmentPt = (uint)AttachmentPoint.LeftHand; - attachPos = Vector3.Zero; - } + attachPos = Vector3.Zero; + } - group.SetAttachmentPoint((byte)AttachmentPt); - group.AbsolutePosition = attachPos; + // AttachmentPt 0 means the client chose to 'wear' the attachment. + if (AttachmentPt == 0) + { + // Check object for stored attachment point + AttachmentPt = (uint)group.GetAttachmentPoint(); + } - // Saves and gets itemID - UUID itemId; + // if we still didn't find a suitable attachment point....... + if (AttachmentPt == 0) + { + // Stick it on left hand with Zero Offset from the attachment point. + AttachmentPt = (uint)AttachmentPoint.LeftHand; + attachPos = Vector3.Zero; + } - if (group.GetFromItemID() == UUID.Zero) - { - m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId); - } - else - { - itemId = group.GetFromItemID(); - } + group.SetAttachmentPoint((byte)AttachmentPt); + group.AbsolutePosition = attachPos; - SetAttachmentInventoryStatus(remoteClient, AttachmentPt, itemId, group); + // Saves and gets itemID + UUID itemId; - group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); - - // In case it is later dropped again, don't let - // it get cleaned up - group.RootPart.RemFlag(PrimFlags.TemporaryOnRez); - group.HasGroupChanged = false; + if (group.GetFromItemID() == UUID.Zero) + { + m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId); } else { - remoteClient.SendAgentAlertMessage( - "You don't have sufficient permissions to attach this object", false); - - return false; + itemId = group.GetFromItemID(); } + + SetAttachmentInventoryStatus(remoteClient, AttachmentPt, itemId, group); + + group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); + + // In case it is later dropped again, don't let + // it get cleaned up + group.RootPart.RemFlag(PrimFlags.TemporaryOnRez); + group.HasGroupChanged = false; } else { - m_log.DebugFormat("[ATTACHMENTS MODULE]: AttachObject found no such scene object {0}", objectLocalID); + remoteClient.SendAgentAlertMessage( + "You don't have sufficient permissions to attach this object", false); + return false; } @@ -245,8 +239,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) tainted = true; - AttachObject( - remoteClient, objatt.LocalId, AttachmentPt, objatt.AbsolutePosition, false); + AttachObject(remoteClient, objatt, AttachmentPt, false); //objatt.ScheduleGroupForFullUpdate(); if (tainted) diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 8ec5bb5..4db8f9e 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -536,10 +536,6 @@ namespace OpenSim.Region.Examples.SimpleModule { } - public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 11887e6..9fe6d96 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -58,7 +58,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// true if the object was successfully attached, false otherwise bool AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Vector3 attachPos, bool silent); + IClientAPI remoteClient, SceneObjectGroup grp, uint AttachmentPt, bool silent); /// /// Rez an attachment from user inventory and change inventory status to match. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 873a11d..daad3d2 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2632,8 +2632,7 @@ namespace OpenSim.Region.Framework.Scenes RootPrim.RemFlag(PrimFlags.TemporaryOnRez); if (AttachmentsModule != null) - AttachmentsModule.AttachObject( - sp.ControllingClient, grp.LocalId, (uint)0, grp.AbsolutePosition, false); + AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); } else diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index d72ee6f..c7a9484 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1064,11 +1064,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - - } - public void SendAvatarDataImmediate(ISceneEntity avatar) { diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index c3edba2..23255fb 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -627,10 +627,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 976a9ff..defe633 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3160,15 +3160,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(m_host.OwnerID); - /* - IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; - if (attachmentsModule != null) - { - attachmentsModule.AttachObject( - presence.ControllingClient, grp.LocalId, - (uint)attachment, Quaternion.Identity, Vector3.Zero, false); - } - */ grp.AttachToAgent(m_host.OwnerID, (uint)attachment, Vector3.Zero, false); } } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index f8304c0..2993b46 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -630,10 +630,6 @@ namespace OpenSim.Tests.Common.Mock { } - public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } -- cgit v1.1 From d665f0ae66adc82ada320e3150a580be2fcb928f Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 14 Jul 2010 20:46:26 +0200 Subject: Detach attachments displaced by other attachments --- .../Avatar/Attachments/AttachmentsModule.cs | 24 +++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 902fb88..34198d2 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -142,19 +142,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments group.SetAttachmentPoint((byte)AttachmentPt); group.AbsolutePosition = attachPos; - // Saves and gets itemID - UUID itemId; + // Remove any previous attachments + ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); + UUID itemID = UUID.Zero; + if (sp != null) + { + foreach(SceneObjectGroup grp in sp.Attachments) + { + if (grp.GetAttachmentPoint() == (byte)AttachmentPt) + { + itemID = grp.GetFromItemID(); + break; + } + } + if (itemID != UUID.Zero) + DetachSingleAttachmentToInv(itemID, remoteClient); + } if (group.GetFromItemID() == UUID.Zero) { - m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId); + m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemID); } else { - itemId = group.GetFromItemID(); + itemID = group.GetFromItemID(); } - SetAttachmentInventoryStatus(remoteClient, AttachmentPt, itemId, group); + SetAttachmentInventoryStatus(remoteClient, AttachmentPt, itemID, group); group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); -- cgit v1.1 From ddfff55cc76144607086fbca03c86df57a271ed0 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 14 Jul 2010 21:06:49 +0200 Subject: Preserve attachment data while a prim is in world. Allows attachment editing on the ground without losing attachpoint and position --- .../Framework/InventoryAccess/InventoryAccessModule.cs | 10 ++++++++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 1a7da61..1bf3a66 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -219,6 +219,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess Vector3 originalPosition = objectGroup.AbsolutePosition; + // Restore attachment data after trip through the sim + if (objectGroup.RootPart.AttachPoint > 0) + inventoryStoredPosition = objectGroup.RootPart.AttachOffset; + objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint; + objectGroup.AbsolutePosition = inventoryStoredPosition; string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup); @@ -516,6 +521,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess string xmlData = Utils.BytesToString(rezAsset.Data); SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); + Vector3 storedPosition = group.AbsolutePosition; group.RootPart.FromFolderID = item.Folder; @@ -635,6 +641,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { if (group.RootPart.Shape.PCode == (byte)PCode.Prim) { + // Save attachment data + group.RootPart.AttachPoint = group.RootPart.Shape.State; + group.RootPart.AttachOffset = storedPosition; + group.ClearPartAttachmentData(); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index f8ae321..87b2d74 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -182,6 +182,14 @@ namespace OpenSim.Region.Framework.Scenes [XmlIgnore] public UUID FromFolderID; + // The following two are to hold the attachment data + // while an object is inworld + [XmlIgnore] + public byte AttachPoint = 0; + + [XmlIgnore] + public Vector3 AttachOffset = Vector3.Zero; + [XmlIgnore] public int STATUS_ROTATE_X; -- cgit v1.1 From 50d56c54a383f636aec67a6c3e98ddcd9f32f859 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 14 Jul 2010 20:46:26 +0200 Subject: Detach attachments displaced by other attachments --- .../Avatar/Attachments/AttachmentsModule.cs | 24 +++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 902fb88..34198d2 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -142,19 +142,33 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments group.SetAttachmentPoint((byte)AttachmentPt); group.AbsolutePosition = attachPos; - // Saves and gets itemID - UUID itemId; + // Remove any previous attachments + ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); + UUID itemID = UUID.Zero; + if (sp != null) + { + foreach(SceneObjectGroup grp in sp.Attachments) + { + if (grp.GetAttachmentPoint() == (byte)AttachmentPt) + { + itemID = grp.GetFromItemID(); + break; + } + } + if (itemID != UUID.Zero) + DetachSingleAttachmentToInv(itemID, remoteClient); + } if (group.GetFromItemID() == UUID.Zero) { - m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId); + m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemID); } else { - itemId = group.GetFromItemID(); + itemID = group.GetFromItemID(); } - SetAttachmentInventoryStatus(remoteClient, AttachmentPt, itemId, group); + SetAttachmentInventoryStatus(remoteClient, AttachmentPt, itemID, group); group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); -- cgit v1.1 From 8d2b4b7b487f7a35b610d894c03619e638866473 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 15 Jul 2010 20:03:08 +0200 Subject: Fix a few permissions vulnerability. Owners could cause permissions escalation on items contained in prims using a hacked viewer --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 35 ++++++++++++++++++++-- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 3 ++ .../Framework/Scenes/SceneObjectPartInventory.cs | 6 ---- 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index c77efc7..e1674be 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1359,16 +1359,45 @@ namespace OpenSim.Region.Framework.Scenes { agentTransactions.HandleTaskItemUpdateFromTransaction( remoteClient, part, transactionID, currentItem); - } - if (part.Inventory.UpdateInventoryItem(itemInfo)) - { + if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) remoteClient.SendAgentAlertMessage("Notecard saved", false); else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) remoteClient.SendAgentAlertMessage("Script saved", false); else remoteClient.SendAgentAlertMessage("Item saved", false); + } + // Check if we're allowed to mess with permissions + if (!Permissions.IsGod(remoteClient.AgentId)) // Not a god + { + if (remoteClient.AgentId != part.OwnerID) // Not owner + { + // Friends and group members can't change any perms + itemInfo.BasePermissions = currentItem.BasePermissions; + itemInfo.EveryonePermissions = currentItem.EveryonePermissions; + itemInfo.GroupPermissions = currentItem.GroupPermissions; + itemInfo.NextPermissions = currentItem.NextPermissions; + itemInfo.CurrentPermissions = currentItem.CurrentPermissions; + } + else + { + // Owner can't change base, and can change other + // only up to base + // Base ALWAYS has move + currentItem.BasePermissions |= (uint)PermissionMask.Move; + itemInfo.BasePermissions = currentItem.BasePermissions; + itemInfo.EveryonePermissions &= currentItem.BasePermissions; + itemInfo.GroupPermissions &= currentItem.BasePermissions; + itemInfo.CurrentPermissions &= currentItem.BasePermissions; + itemInfo.NextPermissions &= currentItem.BasePermissions; + // Next ALWAYS has move + itemInfo.NextPermissions |= (uint)PermissionMask.Move; + } + + } + if (part.Inventory.UpdateInventoryItem(itemInfo)) + { part.GetProperties(remoteClient); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 87b2d74..b19c443 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4156,6 +4156,9 @@ namespace OpenSim.Region.Framework.Scenes // objects if ((_nextOwnerMask & (uint)PermissionMask.Copy) == 0) _nextOwnerMask |= (uint)PermissionMask.Transfer; + + _nextOwnerMask |= (uint)PermissionMask.Move; + break; } SendFullUpdateToAllClients(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 0066158..2a3727a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -762,12 +762,6 @@ namespace OpenSim.Region.Framework.Scenes else if ((InventoryType)item.Type == InventoryType.Notecard) { ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID); - - if (presence != null) - { - presence.ControllingClient.SendAgentAlertMessage( - "Notecard saved", false); - } } m_items[item.ItemID] = item; -- cgit v1.1 From 3f91805afbff1b69ebebcee4ed2593671cf12e12 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 15 Jul 2010 20:28:18 +0200 Subject: prevent hacked viewers from being able to delete arbitrary items from any prim. Allow friends with perms and shared group members to move or copy things out of prims --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index e1674be..4575068 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -935,6 +935,9 @@ namespace OpenSim.Region.Framework.Scenes } if (part != null && group != null) { + if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) + return; + TaskInventoryItem item = group.GetInventoryItem(localID, itemID); if (item == null) return; @@ -1074,9 +1077,21 @@ namespace OpenSim.Region.Framework.Scenes return; } - // Only owner can copy - if (remoteClient.AgentId != taskItem.OwnerID) - return; + TaskInventoryItem item = part.Inventory.GetInventoryItem(itemId); + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + { + // If the item to be moved is no copy, we need to be able to + // edit the prim. + if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) + return; + } + else + { + // If the item is copiable, then we just need to have perms + // on it. The delete check is a pure rights check + if (!Permissions.CanDeleteObject(part.UUID, remoteClient.AgentId)) + return; + } MoveTaskInventoryItem(remoteClient, folderId, part, itemId); } -- cgit v1.1 From 2e5f200b3b571575c6fefe58d2a4a37bf0745303 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 16 Jul 2010 20:23:41 +0200 Subject: Fix showing CreateSelected on all parts of a rez --- .../CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 1bf3a66..c300250 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -529,7 +529,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // find small items. // if (!attachment) + { group.RootPart.CreateSelected = true; + foreach (SceneObjectPart child in group.Children.Values) + child.CreateSelected = true; + } if (!m_Scene.Permissions.CanRezObject( group.Children.Count, remoteClient.AgentId, pos) -- cgit v1.1 From 236c0f8e8b5f9ef86c8614b53e5f404754c9e8d9 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Fri, 16 Jul 2010 22:17:06 +0000 Subject: Fix llSetForecAndTorque([0]) stops linear motion. Mantis #187 --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 6b17ce7..7e70db9 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -1735,6 +1735,13 @@ namespace OpenSim.Region.Physics.OdePlugin if (m_isphysical) { disableBodySoft(); + + if (Body != IntPtr.Zero) + { + d.BodySetLinearVel(Body, 0f, 0f, 0f); + d.BodySetForce(Body, 0, 0, 0); + enableBodySoft(); + } } } else @@ -1756,6 +1763,7 @@ namespace OpenSim.Region.Physics.OdePlugin d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); } +/* Uhhh - stop the motion if the object is _selected_!! if (m_isphysical) { if (Body != IntPtr.Zero) @@ -1765,6 +1773,7 @@ namespace OpenSim.Region.Physics.OdePlugin enableBodySoft(); } } +*/ } resetCollisionAccounting(); -- cgit v1.1 From 61f9b3c2cf1c39dd0d1c58eed7d322d29029c2c0 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 9 Jul 2010 12:58:16 -0400 Subject: Bug in 0.6.9 sometimes restoring script state causes region console to crash due to unhandled file lock exception. Attempt to resolve by wrapping several instances of file create / read logic in using statements and added some error handling for locked file exceptions. If it is IDisposable, it must be disposed! The close statements are unnecessary but harmless so I have left those in. The end of the using block will close and dispose automagically. --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 123 +++++++++++++++++-------- 1 file changed, 84 insertions(+), 39 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 73ef570..cc37225 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1317,10 +1317,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine try { - FileStream tfs = File.Open(assemName + ".text", - FileMode.Open, FileAccess.Read); - tfs.Read(tdata, 0, tdata.Length); - tfs.Close(); + using (FileStream tfs = File.Open(assemName + ".text", + FileMode.Open, FileAccess.Read)) + { + tfs.Read(tdata, 0, tdata.Length); + tfs.Close(); + } assem = new System.Text.ASCIIEncoding().GetString(tdata); } @@ -1340,9 +1342,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine try { - FileStream fs = File.Open(assemName, FileMode.Open, FileAccess.Read); - fs.Read(data, 0, data.Length); - fs.Close(); + using (FileStream fs = File.Open(assemName, FileMode.Open, FileAccess.Read)) + { + fs.Read(data, 0, data.Length); + fs.Close(); + } assem = System.Convert.ToBase64String(data); } @@ -1358,13 +1362,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (File.Exists(fn + ".map")) { - FileStream mfs = File.Open(fn + ".map", FileMode.Open, FileAccess.Read); - StreamReader msr = new StreamReader(mfs); - - map = msr.ReadToEnd(); - - msr.Close(); - mfs.Close(); + using (FileStream mfs = File.Open(fn + ".map", FileMode.Open, FileAccess.Read)) + { + using (StreamReader msr = new StreamReader(mfs)) + { + map = msr.ReadToEnd(); + msr.Close(); + } + mfs.Close(); + } } XmlElement assemblyData = doc.CreateElement("", "Assembly", ""); @@ -1452,30 +1458,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine { Byte[] filedata = Convert.FromBase64String(base64); - FileStream fs = File.Create(path); - fs.Write(filedata, 0, filedata.Length); - fs.Close(); - - fs = File.Create(path + ".text"); - StreamWriter sw = new StreamWriter(fs); - - sw.Write(base64); - - sw.Close(); - fs.Close(); + try + { + using (FileStream fs = File.Create(path)) + { + fs.Write(filedata, 0, filedata.Length); + fs.Close(); + } + } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", path, ex.Message); + } + try + { + using (FileStream fs = File.Create(path + ".text")) + { + using (StreamWriter sw = new StreamWriter(fs)) + { + sw.Write(base64); + sw.Close(); + } + fs.Close(); + } + } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", path, ex.Message); + } } } string statepath = Path.Combine("ScriptEngines", World.RegionInfo.RegionID.ToString()); statepath = Path.Combine(statepath, itemID.ToString() + ".state"); - FileStream sfs = File.Create(statepath); - StreamWriter ssw = new StreamWriter(sfs); - - ssw.Write(stateE.OuterXml); - - ssw.Close(); - sfs.Close(); + try + { + using (FileStream sfs = File.Create(statepath)) + { + using (StreamWriter ssw = new StreamWriter(sfs)) + { + ssw.Write(stateE.OuterXml); + ssw.Close(); + } + sfs.Close(); + } + } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", statepath, ex.Message); + } XmlNodeList mapL = rootE.GetElementsByTagName("LineMap"); if (mapL.Count > 0) @@ -1485,13 +1520,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine string mappath = Path.Combine("ScriptEngines", World.RegionInfo.RegionID.ToString()); mappath = Path.Combine(mappath, mapE.GetAttribute("Filename")); - FileStream mfs = File.Create(mappath); - StreamWriter msw = new StreamWriter(mfs); - - msw.Write(mapE.InnerText); - - msw.Close(); - mfs.Close(); + try + { + using (FileStream mfs = File.Create(mappath)) + { + using (StreamWriter msw = new StreamWriter(mfs)) + { + msw.Write(mapE.InnerText); + msw.Close(); + } + mfs.Close(); + } + } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", statepath, ex.Message); + } } return true; -- cgit v1.1 From 4ae04dd0a8de4d3597ef96d951f5573fedc4e847 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 17 Jul 2010 01:00:23 +0100 Subject: extend exception catching for DoCreateChildAgentCall() from just WebException to Exception on feedback from Chris Hart. See http://opensimulator.org/mantis/view.php?id=4810 --- OpenSim/Framework/Communications/Clients/RegionClient.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenSim/Framework/Communications/Clients/RegionClient.cs b/OpenSim/Framework/Communications/Clients/RegionClient.cs index ee7dec8..a5d4ce5 100644 --- a/OpenSim/Framework/Communications/Clients/RegionClient.cs +++ b/OpenSim/Framework/Communications/Clients/RegionClient.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -164,9 +164,9 @@ namespace OpenSim.Framework.Communications.Clients } } } - catch (WebException ex) + catch (Exception ex) { - m_log.InfoFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex.Message); + m_log.DebugFormat("[REST COMMS]: exception on reply of DoCreateChildAgentCall {0}", ex.Message); // ignore, really } finally @@ -176,7 +176,6 @@ namespace OpenSim.Framework.Communications.Clients } return true; - } public bool DoChildAgentUpdateCall(GridRegion region, IAgentData cAgentData) -- cgit v1.1 From 95d9c773d94573026907d112a7ce82cf362bdd61 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Sat, 17 Jul 2010 01:18:43 +0100 Subject: Stop occasional permanently high 100% utilization when the server is started with many scripts See http://opensimulator.org/mantis/view.php?id=4799 for more details This is the equivalent patch that was applied to master 3.5 weeks ago, seemingly without bad consequences Thanks Snoopy! --- .../Framework/Scenes/SceneObjectPartInventory.cs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index d175695..256e3b0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -31,6 +31,7 @@ using System.IO; using System.Collections.Generic; using System.Collections; using System.Reflection; +using System.Threading; using OpenMetaverse; using log4net; using OpenSim.Framework; @@ -201,6 +202,7 @@ namespace OpenSim.Region.Framework.Scenes if ((int)InventoryType.LSL == item.InvType) { CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); + Thread.Sleep(10); // workaround for Mono cpu utilization > 100% bug } } } @@ -258,7 +260,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.InfoFormat( // "[PRIM INVENTORY]: " + // "Starting script {0}, {1} in prim {2}, {3}", - // item.Name, item.ItemID, Name, UUID); + // item.Name, item.ItemID, m_part.Name, m_part.UUID); if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) return; @@ -296,20 +298,20 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (m_part.ParentGroup.m_savedScriptState != null) - RestoreSavedScriptState(item.OldItemID, item.ItemID); - lock (m_items) { + if (m_part.ParentGroup.m_savedScriptState != null) + RestoreSavedScriptState(item.OldItemID, item.ItemID); + m_items[item.ItemID].PermsMask = 0; m_items[item.ItemID].PermsGranter = UUID.Zero; + + string script = Utils.BytesToString(asset.Data); + m_part.ParentGroup.Scene.EventManager.TriggerRezScript( + m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); + m_part.ParentGroup.AddActiveScriptCount(1); + m_part.ScheduleFullUpdate(); } - - string script = Utils.BytesToString(asset.Data); - m_part.ParentGroup.Scene.EventManager.TriggerRezScript( - m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); - m_part.ParentGroup.AddActiveScriptCount(1); - m_part.ScheduleFullUpdate(); } } ); -- cgit v1.1 From 9bf6179d24cc7fd63643627914272adc78385f1e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 17 Jul 2010 02:26:09 +0200 Subject: Fix scripted give of items --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index defe633..b196642 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4177,7 +4177,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api byte[] bucket = new byte[17]; bucket[0] = (byte)assetType; - byte[] objBytes = objId.GetBytes(); + byte[] objBytes = agentItem.ID.GetBytes(); Array.Copy(objBytes, 0, bucket, 1, 16); Console.WriteLine("Giving inventory"); -- cgit v1.1 From e06b7ee3689bdfd8d71ef3199edb2fb220ec5c21 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 17 Jul 2010 02:38:00 +0200 Subject: Make webloading more robust by addign retries --- .../RegionLoader/Web/RegionLoaderWebServer.cs | 48 ++++++++++------------ 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs index 0ec4af5..dd224cd 100644 --- a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs +++ b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs @@ -48,6 +48,9 @@ namespace OpenSim.Framework.RegionLoader.Web public RegionInfo[] LoadRegions() { + int tries = 3; + int wait = 2000; + if (m_configSource == null) { m_log.Error("[WEBLOADER]: Unable to load configuration source!"); @@ -64,35 +67,28 @@ namespace OpenSim.Framework.RegionLoader.Web } else { - HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(url); - webRequest.Timeout = 30000; //30 Second Timeout - m_log.Debug("[WEBLOADER]: Sending Download Request..."); - HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse(); - m_log.Debug("[WEBLOADER]: Downloading Region Information From Remote Server..."); - StreamReader reader = new StreamReader(webResponse.GetResponseStream()); - string xmlSource = String.Empty; - string tempStr = reader.ReadLine(); - while (tempStr != null) - { - xmlSource = xmlSource + tempStr; - tempStr = reader.ReadLine(); - } - m_log.Debug("[WEBLOADER]: Done downloading region information from server. Total Bytes: " + - xmlSource.Length); - XmlDocument xmlDoc = new XmlDocument(); - xmlDoc.LoadXml(xmlSource); - if (xmlDoc.FirstChild.Name == "Regions") + while (tries > 0) { - RegionInfo[] regionInfos = new RegionInfo[xmlDoc.FirstChild.ChildNodes.Count]; - int i; - for (i = 0; i < xmlDoc.FirstChild.ChildNodes.Count; i++) + HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(url); + webRequest.Timeout = 30000; //30 Second Timeout + m_log.Debug("[WEBLOADER]: Sending Download Request..."); + HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse(); + m_log.Debug("[WEBLOADER]: Downloading Region Information From Remote Server..."); + StreamReader reader = new StreamReader(webResponse.GetResponseStream()); + string xmlSource = String.Empty; + string tempStr = reader.ReadLine(); + while (tempStr != null) { - m_log.Debug(xmlDoc.FirstChild.ChildNodes[i].OuterXml); - regionInfos[i] = - new RegionInfo("REGION CONFIG #" + (i + 1), xmlDoc.FirstChild.ChildNodes[i],false,m_configSource); + xmlSource = xmlSource + tempStr; + tempStr = reader.ReadLine(); + } + m_log.Debug("[WEBLOADER]: Request yielded no regions."); + tries--; + if (tries > 0) + { + m_log.Debug("[WEBLOADER]: Retrying"); + System.Threading.Thread.Sleep(wait); } - - return regionInfos; } return null; } -- cgit v1.1 From d1040c9ff9b47b143e456d06801bd6be148bb1b9 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 17 Jul 2010 02:46:04 +0200 Subject: Replace the screenful of code i deleted. --- .../RegionLoader/Web/RegionLoaderWebServer.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs index dd224cd..f0ffc2c 100644 --- a/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs +++ b/OpenSim/Framework/RegionLoader/Web/RegionLoaderWebServer.cs @@ -82,6 +82,25 @@ namespace OpenSim.Framework.RegionLoader.Web xmlSource = xmlSource + tempStr; tempStr = reader.ReadLine(); } + m_log.Debug("[WEBLOADER]: Done downloading region information from server. Total Bytes: " + + xmlSource.Length); + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(xmlSource); + if (xmlDoc.FirstChild.Name == "Regions") + { + RegionInfo[] regionInfos = new RegionInfo[xmlDoc.FirstChild.ChildNodes.Count]; + int i; + for (i = 0; i < xmlDoc.FirstChild.ChildNodes.Count; i++) + { + m_log.Debug(xmlDoc.FirstChild.ChildNodes[i].OuterXml); + regionInfos[i] = + new RegionInfo("REGION CONFIG #" + (i + 1), xmlDoc.FirstChild.ChildNodes[i],false,m_configSource); + } + + if (i > 0) + return regionInfos; + } + m_log.Debug("[WEBLOADER]: Request yielded no regions."); tries--; if (tries > 0) -- cgit v1.1 From 373ac901560b3aaa4b531512152da9206bf89dcf Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 17 Jul 2010 07:19:58 +0100 Subject: Allow Megaregions to start properly after an unclean shutdown --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +++ OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7089368..62ee574 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -145,6 +145,7 @@ namespace OpenSim.Region.Framework.Scenes protected SceneCommunicationService m_sceneGridService; public bool LoginsDisabled = true; + public bool LoadingPrims = false; public new float TimeDilation { @@ -1650,6 +1651,7 @@ namespace OpenSim.Region.Framework.Scenes /// public virtual void LoadPrimsFromStorage(UUID regionID) { + LoadingPrims = true; m_log.Info("[SCENE]: Loading objects from datastore"); List PrimsFromDB = m_storageManager.DataStore.LoadObjects(regionID); @@ -1673,6 +1675,7 @@ namespace OpenSim.Region.Framework.Scenes } m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)"); + LoadingPrims = false; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index fe5e948..aa41354 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -294,7 +294,7 @@ namespace OpenSim.Region.Framework.Scenes if ((m_scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || m_scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) || m_scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || m_scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) - && !IsAttachmentCheckFull()) + && !IsAttachmentCheckFull() && (!m_scene.LoadingPrims)) { m_scene.CrossPrimGroupIntoNewRegion(val, this, true); } -- cgit v1.1 From c41d418380789255de778499c426d293969760f5 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 17 Jul 2010 16:32:55 +0200 Subject: Allow communicating with blue box dialogs across a region border via a child agent --- OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index 4e36c5d..fb0bd1a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -86,14 +86,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { ScenePresence sp = m_scene.GetScenePresence(agentID); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendAgentAlertMessage(message, modal); } public void SendAlertToUser(string firstName, string lastName, string message, bool modal) { ScenePresence presence = m_scene.GetScenePresence(firstName, lastName); - if (presence != null && !presence.IsChildAgent) + if (presence != null) presence.ControllingClient.SendAgentAlertMessage(message, modal); } @@ -101,8 +101,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { m_scene.ForEachScenePresence(delegate(ScenePresence presence) { - if (!presence.IsChildAgent) - presence.ControllingClient.SendAlertMessage(message); + presence.ControllingClient.SendAlertMessage(message); }); } @@ -124,7 +123,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog } ScenePresence sp = m_scene.GetScenePresence(avatarID); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); } @@ -133,7 +132,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { ScenePresence sp = m_scene.GetScenePresence(avatarID); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); } @@ -154,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog ScenePresence sp = m_scene.GetScenePresence(avatarid); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendTextBoxRequest(message, chatChannel, name, ownerFirstName, ownerLastName, objectid); } @@ -218,4 +217,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog return result; } } -} \ No newline at end of file +} -- cgit v1.1 From d52fb4d2e944db4a31ddafaefcdda3690f1c6bb7 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 17 Jul 2010 16:35:14 +0200 Subject: Shorten LLEmail delay to 15s. With the external spam protection, we can afford to do that --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index b196642..a947b3d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3314,7 +3314,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } emailModule.SendEmail(m_host.UUID, address, subject, message); - ScriptSleep(20000); + ScriptSleep(15000); } public void llGetNextEmail(string address, string subject) -- cgit v1.1 From ef6565470f587a3b5b065c8278ddb9d9b1691250 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 17 Jul 2010 06:54:46 -0700 Subject: XGitminster: Update config options; commitFrameInterval -> CommitInterval and a new option DisableNonEssentialCommits --- bin/OpenSim.ini.example | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 559a734..1527334 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -884,8 +884,11 @@ Enabled = true RepoPath = "git" -;How many frames between the scheduled commits? -CommitFrameInterval = 360000 +;How many seconds between the scheduled commits? +CommitInterval = 21600 + +;Disable all except the initial commit? +DisableNonEssentialCommits = false ;Should we automatically commit when necessary to avoid objects never making it into the repo? UseSafetyCommit = true -- cgit v1.1 From 17412389f3cbc4a98c3fb11963ebec821fcd5e11 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 17 Jul 2010 14:34:35 -0700 Subject: Revert 233c872.. "* Call client.Start() sunchronously. Calling thos async avoids some stuttering", pending fix for the core issue --- OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index f2bcc0b..cda461c 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -900,16 +900,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Start the IClientAPI // Spin it off so that it doesn't clog up the LLUDPServer - //Util.FireAndForget(delegate(object o) { client.Start(); }); - - // NOTE: DO NOT CALL THIS ASYNCHRONOUSLY!!!!! - // This method will ultimately cause the modules to hook - // client events in OnNewClient. If they can't do this - // before further packets are processed, packets WILL BE LOST. - // This includes the all-important EconomyDataRequest! - // So using FireAndForget here WILL screw up money. Badly. - // You have been warned! - client.Start(); + Util.FireAndForget(delegate(object o) { client.Start(); }); } else { -- cgit v1.1 From fabe2206db37be39a90254da8a7fff973f2dd977 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 17 Jul 2010 15:08:59 -0700 Subject: Ensure that packets do NOT get delivered to a client before the modules that can deal with the client's response have finished loading. --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 9 +++++++++ .../Region/ClientStack/LindenUDP/LLUDPClient.cs | 10 ++++++++++ .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 23 +++++++++++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 754127d..a9f9d60 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -334,6 +334,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // protected HashSet m_attachmentsSent; private int m_moneyBalance; + private bool m_deliverPackets = true; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; private AgentUpdateArgs lastarg; @@ -378,6 +379,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP get { return m_startpos; } set { m_startpos = value; } } + public bool DeliverPackets + { + get { return m_deliverPackets; } + set { + m_deliverPackets = value; + m_udpClient.m_deliverPackets = value; + } + } public UUID AgentId { get { return m_agentId; } } public UUID ActiveGroupId { get { return m_activeGroupID; } } public string ActiveGroupName { get { return m_activeGroupName; } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 6232c48..eebbfa5 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -149,6 +149,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private int m_defaultRTO = 3000; private int m_maxRTO = 60000; + public bool m_deliverPackets = true; /// /// Default constructor @@ -389,6 +390,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (category >= 0 && category < m_packetOutboxes.Length) { OpenSim.Framework.LocklessQueue queue = m_packetOutboxes[category]; + + if (m_deliverPackets == false) + { + queue.Enqueue(packet); + return true; + } + TokenBucket bucket = m_throttleCategories[category]; if (bucket.RemoveTokens(packet.Buffer.DataLength)) @@ -419,6 +427,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// True if any packets were sent, otherwise false public bool DequeueOutgoing() { + if (m_deliverPackets == false) return false; + OutgoingPacket packet; OpenSim.Framework.LocklessQueue queue; TokenBucket bucket; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index cda461c..3b63bcd 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -900,7 +900,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Start the IClientAPI // Spin it off so that it doesn't clog up the LLUDPServer - Util.FireAndForget(delegate(object o) { client.Start(); }); + + //First, and very importantly: + // + //Set our DeliverPackets flag in the client to *false* + //this will prevent us from missing important messages + //before the modules are bound + client.DeliverPackets = false; + + Util.FireAndForget( + delegate + { + try + { + client.Start(); + } + finally + { + //Now, release the hounds. er, packets. + client.DeliverPackets = true; + } + } + ); } else { -- cgit v1.1 From c088397ec72916dfb2914b44f2be8df827fd89d9 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sun, 18 Jul 2010 06:01:26 -0700 Subject: If the client requests that an object be deleted, and the SOG/SOP is null and/or is marked as deleted, just send the KillObject --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 4575068..989ec37 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1700,11 +1700,19 @@ namespace OpenSim.Region.Framework.Scenes // Invalid id SceneObjectPart part = GetSceneObjectPart(localID); if (part == null) + { + //Client still thinks the object exists, kill it + SendKillObject(localID); continue; + } // Already deleted by someone else if (part.ParentGroup == null || part.ParentGroup.IsDeleted) + { + //Client still thinks the object exists, kill it + SendKillObject(localID); continue; + } // Can't delete child prims if (part != part.ParentGroup.RootPart) -- cgit v1.1 From c263fc54ac04ab494a62b6157623d936d966940c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 18 Jul 2010 21:05:50 +0200 Subject: Add a state change method to the Async commands handler to allow timers and http requests to survive state changes --- .../Shared/Api/Implementation/AsyncCommandManager.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs index ee32755..61e4934 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs @@ -248,6 +248,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } + public static void StateChange(IScriptEngine engine, uint localID, UUID itemID) + { + // Remove a specific script + + // Remove dataserver events + m_Dataserver[engine].RemoveEvents(localID, itemID); + + IWorldComm comms = engine.World.RequestModuleInterface(); + if (comms != null) + comms.DeleteListener(itemID); + + IXMLRPC xmlrpc = engine.World.RequestModuleInterface(); + xmlrpc.DeleteChannels(itemID); + xmlrpc.CancelSRDRequests(itemID); + + // Remove Sensors + m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID); + + } + public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) { List data = new List(); -- cgit v1.1 From 54da64acacec9703b95f375aab58890766cc16a4 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 20 Jul 2010 00:46:39 +0200 Subject: Remove exception badness in the LSL Types. Who ever came up with that.....?! --- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index c9049e2..bab5156 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -615,10 +615,10 @@ namespace OpenSim.Region.ScriptEngine.Shared { int la = -1; int lb = -1; - try { la = a.Length; } - catch (NullReferenceException) { } - try { lb = b.Length; } - catch (NullReferenceException) { } + if (a != null) + la = a.Length; + if (b != null) + lb = b.Length; return la == lb; } @@ -627,10 +627,10 @@ namespace OpenSim.Region.ScriptEngine.Shared { int la = -1; int lb = -1; - try { la = a.Length; } - catch (NullReferenceException) { } - try {lb = b.Length;} - catch (NullReferenceException) { } + if (a != null) + la = a.Length; + if (b != null) + lb = b.Length; return la != lb; } -- cgit v1.1 From 191bee2ed0903b23f5d93f79650daf7662480b17 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 20 Jul 2010 00:55:31 +0200 Subject: Remove the null checks altogether --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 9 +-------- OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs | 16 ++++------------ 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a947b3d..138bcc9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5027,14 +5027,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - if (src == null) - { - return 0; - } - else - { - return src.Length; - } + return src.Length; } public LSL_Integer llList2Integer(LSL_List src, int index) diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index bab5156..a3a2fdf 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -613,24 +613,16 @@ namespace OpenSim.Region.ScriptEngine.Shared public static bool operator ==(list a, list b) { - int la = -1; - int lb = -1; - if (a != null) - la = a.Length; - if (b != null) - lb = b.Length; + int la = a.Length; + int lb = b.Length; return la == lb; } public static bool operator !=(list a, list b) { - int la = -1; - int lb = -1; - if (a != null) - la = a.Length; - if (b != null) - lb = b.Length; + int la = a.Length; + int lb = b.Length; return la != lb; } -- cgit v1.1 From fd66ee57f3b091e6e4b6c619645595b300c94fbb Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 20 Jul 2010 14:45:46 +0200 Subject: When a god uses mass permission setting, the V bit is cleared from next perms, rendering the item unmoveable for the next owenr. Make god mods conform to the rules, too. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 989ec37..59731f7 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1383,6 +1383,9 @@ namespace OpenSim.Region.Framework.Scenes remoteClient.SendAgentAlertMessage("Item saved", false); } + // Base ALWAYS has move + currentItem.BasePermissions |= (uint)PermissionMask.Move; + // Check if we're allowed to mess with permissions if (!Permissions.IsGod(remoteClient.AgentId)) // Not a god { @@ -1399,18 +1402,18 @@ namespace OpenSim.Region.Framework.Scenes { // Owner can't change base, and can change other // only up to base - // Base ALWAYS has move - currentItem.BasePermissions |= (uint)PermissionMask.Move; itemInfo.BasePermissions = currentItem.BasePermissions; itemInfo.EveryonePermissions &= currentItem.BasePermissions; itemInfo.GroupPermissions &= currentItem.BasePermissions; itemInfo.CurrentPermissions &= currentItem.BasePermissions; itemInfo.NextPermissions &= currentItem.BasePermissions; - // Next ALWAYS has move - itemInfo.NextPermissions |= (uint)PermissionMask.Move; } } + + // Next ALWAYS has move + itemInfo.NextPermissions |= (uint)PermissionMask.Move; + if (part.Inventory.UpdateInventoryItem(itemInfo)) { part.GetProperties(remoteClient); -- cgit v1.1 From 1d6735f0ece1adda715d35ed8e62e9adbddbe4d2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 29 Jun 2010 21:50:52 +0100 Subject: Fix the XML serializationt to provide an empty script state element if the script hasn't yet saved state, or can't save state because of a loop --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 32 ++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index cc37225..92fb934 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1279,9 +1279,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine string xml = instance.GetXMLState(); XmlDocument sdoc = new XmlDocument(); - sdoc.LoadXml(xml); - XmlNodeList rootL = sdoc.GetElementsByTagName("ScriptState"); - XmlNode rootNode = rootL[0]; + bool loadedState = true; + try + { + sdoc.LoadXml(xml); + } + catch (System.Xml.XmlException e) + { + loadedState = false; + } + + XmlNodeList rootL = null; + XmlNode rootNode = null; + if (loadedState) + { + rootL = sdoc.GetElementsByTagName("ScriptState"); + rootNode = rootL[0]; + } // Create XmlDocument doc = new XmlDocument(); @@ -1297,8 +1311,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine stateData.Attributes.Append(engineName); doc.AppendChild(stateData); + XmlNode xmlstate = null; + // Add ... - XmlNode xmlstate = doc.ImportNode(rootNode, true); + if (loadedState) + { + xmlstate = doc.ImportNode(rootNode, true); + } + else + { + xmlstate = doc.CreateElement("", "ScriptState", ""); + } + stateData.AppendChild(xmlstate); string assemName = instance.GetAssemblyName(); -- cgit v1.1 From 4ccc141764083ae6dfc0b5b8e303a4395e66b684 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 20 Jul 2010 21:49:31 +0100 Subject: Resync with master --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 44b76b7..8b4f0ed 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -749,13 +749,7 @@ namespace OpenSim.Region.Framework.Scenes item.GroupID = m_part.GroupID; if (item.AssetID == UUID.Zero) - item.AssetID = it.AssetID; - - lock (m_items) - { - m_items[item.ItemID] = item; - m_inventorySerial++; - } + item.AssetID = m_items[item.ItemID].AssetID; m_items[item.ItemID] = item; m_inventorySerial++; -- cgit v1.1 From c72c84b4559ea164bcb77c2d64a046729662bf04 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 21 Jul 2010 12:16:17 +0200 Subject: Refine autoreturn a bit --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 5 ++++- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 10 ---------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 7053c02..e738dd2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1681,7 +1681,10 @@ namespace OpenSim.Region.Framework.Scenes try { - if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart + if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart + m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things + m_scene.LoadingPrims) // Land may not be valid yet + { ILandObject parcel = m_scene.LandChannel.GetLandObject( m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1d4c235..a6f0cdd 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6348,16 +6348,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api prules.OuterAngle = (float)tempf; prules.PartFlags |= 0x02; // Set new angle format. break; - - case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: - tempf = (float)rules.GetLSLFloatItem(i + 1); - prules.InnerAngle = (float)tempf; - break; - - case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: - tempf = (float)rules.GetLSLFloatItem(i + 1); - prules.OuterAngle = (float)tempf; - break; } } -- cgit v1.1 From fb89d0ff4eb4636a6a70fd45c85b935e0a6b388a Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 21 Jul 2010 12:31:59 +0200 Subject: Allow megaregions to be used in M7, should we so decide --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 ++ OpenSim/Region/Framework/Scenes/SceneGraph.cs | 47 ++++++++++++++------------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index f79bd23..2a498cc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -137,6 +137,7 @@ namespace OpenSim.Region.Framework.Scenes protected SceneCommunicationService m_sceneGridService; public bool LoginsDisabled = true; public bool LoadingPrims = false; + public bool CombineRegions = false; public new float TimeDilation { @@ -768,6 +769,7 @@ namespace OpenSim.Region.Framework.Scenes } m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); + CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); #region BinaryStats diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index a36800b..12c1c20 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -283,30 +283,33 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { - // KF: Check for out-of-region, move inside and make static. - Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, - sceneObject.RootPart.GroupPosition.Y, - sceneObject.RootPart.GroupPosition.Z); - if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || - npos.X > Constants.RegionSize || - npos.Y > Constants.RegionSize)) - { - if (npos.X < 0.0) npos.X = 1.0f; - if (npos.Y < 0.0) npos.Y = 1.0f; - if (npos.Z < 0.0) npos.Z = 0.0f; - if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; - if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; - - foreach (SceneObjectPart part in sceneObject.Children.Values) + if (!m_parentScene.CombineRegions) + { + // KF: Check for out-of-region, move inside and make static. + Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, + sceneObject.RootPart.GroupPosition.Y, + sceneObject.RootPart.GroupPosition.Z); + if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || + npos.X > Constants.RegionSize || + npos.Y > Constants.RegionSize)) { - part.GroupPosition = npos; + if (npos.X < 0.0) npos.X = 1.0f; + if (npos.Y < 0.0) npos.Y = 1.0f; + if (npos.Z < 0.0) npos.Z = 0.0f; + if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; + if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; + + foreach (SceneObjectPart part in sceneObject.Children.Values) + { + part.GroupPosition = npos; + } + sceneObject.RootPart.Velocity = Vector3.Zero; + sceneObject.RootPart.AngularVelocity = Vector3.Zero; + sceneObject.RootPart.Acceleration = Vector3.Zero; + sceneObject.RootPart.Velocity = Vector3.Zero; } - sceneObject.RootPart.Velocity = Vector3.Zero; - sceneObject.RootPart.AngularVelocity = Vector3.Zero; - sceneObject.RootPart.Acceleration = Vector3.Zero; - sceneObject.RootPart.Velocity = Vector3.Zero; - } - + } + if (!alreadyPersisted) { sceneObject.ForceInventoryPersistence(); -- cgit v1.1 From 316854dc137709d4aeb0bf20351de1c75af20fe5 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 21 Jul 2010 12:31:59 +0200 Subject: Allow megaregions to be used in M7, should we so decide --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 ++ OpenSim/Region/Framework/Scenes/SceneGraph.cs | 47 ++++++++++++++------------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8e860fb..8af7514 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -146,6 +146,7 @@ namespace OpenSim.Region.Framework.Scenes protected SceneCommunicationService m_sceneGridService; public bool LoginsDisabled = true; public bool LoadingPrims = false; + public bool CombineRegions = false; public new float TimeDilation { @@ -656,6 +657,7 @@ namespace OpenSim.Region.Framework.Scenes } m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); + CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); IConfig interest_management_config = m_config.Configs["InterestManagement"]; if (interest_management_config != null) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 5a1922a..1d126b6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -226,30 +226,33 @@ namespace OpenSim.Region.Framework.Scenes protected internal bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { - // KF: Check for out-of-region, move inside and make static. - Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, - sceneObject.RootPart.GroupPosition.Y, - sceneObject.RootPart.GroupPosition.Z); - if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || - npos.X > Constants.RegionSize || - npos.Y > Constants.RegionSize)) - { - if (npos.X < 0.0) npos.X = 1.0f; - if (npos.Y < 0.0) npos.Y = 1.0f; - if (npos.Z < 0.0) npos.Z = 0.0f; - if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; - if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; - - foreach (SceneObjectPart part in sceneObject.Children.Values) + if (!m_parentScene.CombineRegions) + { + // KF: Check for out-of-region, move inside and make static. + Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X, + sceneObject.RootPart.GroupPosition.Y, + sceneObject.RootPart.GroupPosition.Z); + if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 || + npos.X > Constants.RegionSize || + npos.Y > Constants.RegionSize)) { - part.GroupPosition = npos; + if (npos.X < 0.0) npos.X = 1.0f; + if (npos.Y < 0.0) npos.Y = 1.0f; + if (npos.Z < 0.0) npos.Z = 0.0f; + if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f; + if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f; + + foreach (SceneObjectPart part in sceneObject.Children.Values) + { + part.GroupPosition = npos; + } + sceneObject.RootPart.Velocity = Vector3.Zero; + sceneObject.RootPart.AngularVelocity = Vector3.Zero; + sceneObject.RootPart.Acceleration = Vector3.Zero; + sceneObject.RootPart.Velocity = Vector3.Zero; } - sceneObject.RootPart.Velocity = Vector3.Zero; - sceneObject.RootPart.AngularVelocity = Vector3.Zero; - sceneObject.RootPart.Acceleration = Vector3.Zero; - sceneObject.RootPart.Velocity = Vector3.Zero; - } - + } + if (!alreadyPersisted) { sceneObject.ForceInventoryPersistence(); -- cgit v1.1 From ce8b9b41815f518488e123a16e0ef85f7c467631 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 22 Jul 2010 19:20:09 +0200 Subject: LSL compatibility fix. Add 0.1 s sleep to llSetLinkPrimitiveParams so fade scripts will time correctly. The -Fast version works without a delay --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a6f0cdd..de00db3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7165,7 +7165,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api SetPrimParams(m_host, rules); } - public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) + public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) { m_host.AddScriptLPS(1); @@ -7191,9 +7191,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) + public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) { llSetLinkPrimitiveParams(linknumber, rules); + ScriptSleep(100); } protected void SetPrimParams(ScenePresence av, LSL_List rules) -- cgit v1.1 From 7ebabf185ef96c193f6afbe3bdfcdc92c0a2150e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 22 Jul 2010 19:31:02 +0200 Subject: change the delay to 0.2s. My bad. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index de00db3..fb79356 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7194,7 +7194,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) { llSetLinkPrimitiveParams(linknumber, rules); - ScriptSleep(100); + ScriptSleep(200); } protected void SetPrimParams(ScenePresence av, LSL_List rules) -- cgit v1.1 From 9ce2f95f37c6234c9750c611106730c65ec6f1f5 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 22 Jul 2010 10:46:57 -0700 Subject: Add config option securePermissionsLoading which will stop the region from loading if the specified permissions modules fail to load. --- OpenSim/Region/Application/OpenSimBase.cs | 21 +++++++++++++++++++++ bin/OpenSim.ini.example | 3 +++ 2 files changed, 24 insertions(+) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 1ec96a0..b21793e 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -91,6 +91,10 @@ namespace OpenSim protected List m_plugins = new List(); + private List m_permsModules; + + private bool m_securePermissionsLoading = true; + /// /// The config information passed into the OpenSimulator region server. /// @@ -188,6 +192,11 @@ namespace OpenSim CreatePIDFile(pidFile); userStatsURI = startupConfig.GetString("Stats_URI", String.Empty); + + m_securePermissionsLoading = startupConfig.GetBoolean("SecurePermissionsLoading", true); + + string permissionModules = startupConfig.GetString("permissionmodules", "DefaultPermissionsModule"); + m_permsModules = new List(permissionModules.Split(',')); } base.StartupSpecific(); @@ -345,6 +354,18 @@ namespace OpenSim } else m_log.Error("[MODULES]: The new RegionModulesController is missing..."); + if (m_securePermissionsLoading) + { + foreach (string s in m_permsModules) + { + if (!scene.RegionModules.ContainsKey(s)) + { + m_log.Fatal("[MODULES]: Required module " + s + " not found."); + Environment.Exit(0); + } + } + } + scene.SetModuleInterfaces(); // First Step of bootreport sequence if (scene.SnmpService != null) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 526bae7..f37e3f3 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -202,6 +202,9 @@ ;permissionmodules = "DefaultPermissionsModule" + ;If any of the specified permissions modules fail to load, quit? + SecurePermissionsLoading = true + ; If set to false, then, in theory, the server never carries out permission checks (allowing anybody to copy ; any item, etc. This may not yet be implemented uniformally. ; If set to true, then all permissions checks are carried out -- cgit v1.1 From 83aec1ec94e6c946862794d3e13bc9541d1e10dc Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 22 Jul 2010 23:47:10 +0200 Subject: Fix a little infinite recursion i added just for sh.ts and giggles. NOT. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index fb79356..8dc83c3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7193,7 +7193,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) { - llSetLinkPrimitiveParams(linknumber, rules); + llSetLinkPrimitiveParamsFast(linknumber, rules); ScriptSleep(200); } -- cgit v1.1 From 64cc76bd7922e32b0799023faed49904694cf1b4 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 23 Jul 2010 01:32:29 +0200 Subject: Fix up the name of the default permissions module to match it's config name --- OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index e11e23a..f18e6db 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -384,7 +384,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions public string Name { - get { return "PermissionsModule"; } + get { return "DefaultPermissionsModule"; } } public bool IsSharedModule -- cgit v1.1 From da5b7e199a5c2902657a747b14552be842b284aa Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 22 Jul 2010 18:04:55 -0700 Subject: First, change DefaultPermissionsModule so it returns the correct name... --- OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index e11e23a..f18e6db 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -384,7 +384,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions public string Name { - get { return "PermissionsModule"; } + get { return "DefaultPermissionsModule"; } } public bool IsSharedModule -- cgit v1.1 From bfd883f5330d18def06d3bf7ca4ade00e2c1b4cd Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Thu, 22 Jul 2010 18:05:56 -0700 Subject: ... Then, make sure we also check the old-style module stack before we throw a tantrum --- OpenSim/Region/Application/OpenSimBase.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index b21793e..65dac66 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -360,8 +360,19 @@ namespace OpenSim { if (!scene.RegionModules.ContainsKey(s)) { - m_log.Fatal("[MODULES]: Required module " + s + " not found."); - Environment.Exit(0); + bool found = false; + foreach (IRegionModule m in modules) + { + if (m.Name == s) + { + found = true; + } + } + if (!found) + { + m_log.Fatal("[MODULES]: Required module " + s + " not found."); + Environment.Exit(0); + } } } } -- cgit v1.1 From 81186e76b68e9f6ba8c03a48fb5f7a43b0eea7a1 Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 24 Jul 2010 10:43:57 -0700 Subject: Add an m_enabled flag to XmlRpcRouterModule so it won't try to bind the xmlrpc_uri event if it's not mentioned in the ini. --- .../Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs index 32659c8..dcac4a9 100644 --- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs @@ -42,7 +42,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule public class XmlRpcRouter : IRegionModule, IXmlRpcRouter { //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + private bool m_enabled = false; public void Initialise(Scene scene, IConfigSource config) { IConfig startupConfig = config.Configs["Startup"]; @@ -53,6 +53,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule "XmlRpcRouterModule") == "XmlRpcRouterModule") { scene.RegisterModuleInterface(this); + m_enabled = true; + } + else + { + m_enabled = false; } } @@ -76,7 +81,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) { - scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] {uri}); + if (m_enabled) + { + scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] { uri }); + } } public void ScriptRemoved(UUID itemID) -- cgit v1.1 From 8e137e31cd61c21d672cec6507e081ed447e886e Mon Sep 17 00:00:00 2001 From: Tom Grimshaw Date: Sat, 24 Jul 2010 11:34:43 -0700 Subject: Fix the XmlRpcRouterModule so it reads from the correct config section ([XMLRPC] not [Startup]) and disable by default (since it's disabled in the ini by default) --- .../Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs index dcac4a9..11c87f8 100644 --- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs @@ -45,12 +45,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule private bool m_enabled = false; public void Initialise(Scene scene, IConfigSource config) { - IConfig startupConfig = config.Configs["Startup"]; + IConfig startupConfig = config.Configs["XMLRPC"]; if (startupConfig == null) return; if (startupConfig.GetString("XmlRpcRouterModule", - "XmlRpcRouterModule") == "XmlRpcRouterModule") + "") == "XmlRpcRouterModule") { scene.RegisterModuleInterface(this); m_enabled = true; -- cgit v1.1 From 516ec4acd01d70276329d251155775cedf7b8941 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 25 Jul 2010 08:11:39 +0200 Subject: Eat a lockign exception that kills scripts. May bear more investigation in the long run. --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 24d260e..dbf493c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -136,12 +136,21 @@ namespace OpenSim.Region.Framework.Scenes if (m_partsLock.RecursiveReadCount > 0) { m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); - m_partsLock.ExitReadLock(); + try + { + m_partsLock.ExitReadLock(); + } + catch { } // Ignore errors, to allow resync } if (m_partsLock.RecursiveWriteCount > 0) { m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested (write lock exists on this thread). This should not happen and means something needs to be fixed."); - m_partsLock.ExitWriteLock(); + try + { + m_partsLock.ExitWriteLock(); + } + catch { } + } while (!m_partsLock.TryEnterReadLock(60000)) -- cgit v1.1 From 3e97b3ae3345d49b968ebf4ad12842bda4640d43 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 25 Jul 2010 21:55:31 +0200 Subject: Fix the XMREngine not starting scripts on region startup. Turns out it was a dumb merge artefact that caused it. --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 9b16281..eefa6d0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -210,11 +210,6 @@ namespace OpenSim.Region.Framework.Scenes if ((int)InventoryType.LSL == item.InvType) { CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); - if ((int)InventoryType.LSL == item.InvType) - { - CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); - Thread.Sleep(10); // workaround for Mono cpu utilization > 100% bug - } } } } -- cgit v1.1 From 7871dd606eb8c827101ee4ee3c64d00139e1a0b4 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 29 Jul 2010 16:33:20 +0200 Subject: Allow gods and estate managers/owners to be unaffected by parcel bans --- OpenSim/Region/CoreModules/World/Land/LandObject.cs | 6 ++++++ .../CoreModules/World/Permissions/PermissionsModule.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.Permissions.cs | 17 +++++++++++++++++ 3 files changed, 24 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 2a87da2..6864629 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -283,6 +283,9 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsBannedFromLand(UUID avatar) { + if (m_scene.Permissions.IsAdministrator(avatar)) + return false; + if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) { ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); @@ -301,6 +304,9 @@ namespace OpenSim.Region.CoreModules.World.Land public bool IsRestrictedFromLand(UUID avatar) { + if (m_scene.Permissions.IsAdministrator(avatar)) + return false; + if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) { ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 69b247c..1d70546 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -209,6 +209,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene.Permissions.OnDeedParcel += CanDeedParcel; m_scene.Permissions.OnDeedObject += CanDeedObject; m_scene.Permissions.OnIsGod += IsGod; + m_scene.Permissions.OnIsAdministrator += IsAdministrator; m_scene.Permissions.OnDuplicateObject += CanDuplicateObject; m_scene.Permissions.OnDeleteObject += CanDeleteObject; //MAYBE FULLY IMPLEMENTED m_scene.Permissions.OnEditObject += CanEditObject; //MAYBE FULLY IMPLEMENTED diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs index 7dab04f..a523351 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs @@ -64,6 +64,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate bool RunConsoleCommandHandler(UUID user, Scene requestFromScene); public delegate bool IssueEstateCommandHandler(UUID user, Scene requestFromScene, bool ownerCommand); public delegate bool IsGodHandler(UUID user, Scene requestFromScene); + public delegate bool IsAdministratorHandler(UUID user); public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene); public delegate bool SellParcelHandler(UUID user, ILandObject parcel, Scene scene); public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene); @@ -122,6 +123,7 @@ namespace OpenSim.Region.Framework.Scenes public event RunConsoleCommandHandler OnRunConsoleCommand; public event IssueEstateCommandHandler OnIssueEstateCommand; public event IsGodHandler OnIsGod; + public event IsAdministratorHandler OnIsAdministrator; public event EditParcelHandler OnEditParcel; public event SellParcelHandler OnSellParcel; public event AbandonParcelHandler OnAbandonParcel; @@ -652,6 +654,21 @@ namespace OpenSim.Region.Framework.Scenes } return true; } + + public bool IsAdministrator(UUID user) + { + IsAdministratorHandler handler = OnIsAdministrator; + if (handler != null) + { + Delegate[] list = handler.GetInvocationList(); + foreach (IsAdministratorHandler h in list) + { + if (h(user) == false) + return false; + } + } + return true; + } #endregion #region EDIT PARCEL -- cgit v1.1 From f9280374d2e44f66145718c880119383c2dc2a71 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 30 Jul 2010 15:03:03 +0200 Subject: Bannination fixes. Objects in nonpublic parcels were muted by default. Gods were muted, too. --- OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | 6 +++++- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 9c8cbc6..50d2f9d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -244,7 +244,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat ILandObject Presencecheck = s.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); if (Presencecheck != null) { - if (Presencecheck.IsEitherBannedOrRestricted(c.SenderUUID) != true) + // This will pass all chat from objects. Not + // perfect, but it will do. For now. Better + // than the prior behavior of muting all + // objects on a parcel with access restrictions + if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) { TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix+fromName, c.Type, message, sourceType); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 8dc83c3..15af8b1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6075,7 +6075,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return m_host.ParentGroup.RootPart.AttachmentPoint; } - public LSL_Integer llGetFreeMemory() + public virtual LSL_Integer llGetFreeMemory() { m_host.AddScriptLPS(1); // Make scripts designed for LSO happy -- cgit v1.1 From d5f497478a371107c568844321a4663bccfbf527 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 1 Aug 2010 10:21:56 -0700 Subject: Add config option securePermissionsLoading which will stop the region from loading if the specified permissions modules fail to load. --- OpenSim/Region/Application/OpenSimBase.cs | 21 +++++++++++++++++++++ bin/OpenSim.ini.example | 3 +++ 2 files changed, 24 insertions(+) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 27cb137..9267721 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -88,6 +88,10 @@ namespace OpenSim protected List m_plugins = new List(); + private List m_permsModules; + + private bool m_securePermissionsLoading = true; + /// /// The config information passed into the OpenSimulator region server. /// @@ -185,6 +189,11 @@ namespace OpenSim CreatePIDFile(pidFile); userStatsURI = startupConfig.GetString("Stats_URI", String.Empty); + + m_securePermissionsLoading = startupConfig.GetBoolean("SecurePermissionsLoading", true); + + string permissionModules = startupConfig.GetString("permissionmodules", "DefaultPermissionsModule"); + m_permsModules = new List(permissionModules.Split(',')); } base.StartupSpecific(); @@ -342,6 +351,18 @@ namespace OpenSim } else m_log.Error("[MODULES]: The new RegionModulesController is missing..."); + if (m_securePermissionsLoading) + { + foreach (string s in m_permsModules) + { + if (!scene.RegionModules.ContainsKey(s)) + { + m_log.Fatal("[MODULES]: Required module " + s + " not found."); + Environment.Exit(0); + } + } + } + scene.SetModuleInterfaces(); // First Step of bootreport sequence if (scene.SnmpService != null) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 1527334..2c105bd 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -178,6 +178,9 @@ ;permissionmodules = "DefaultPermissionsModule" + ;If any of the specified permissions modules fail to load, quit? + SecurePermissionsLoading = true + ; If set to false, then, in theory, the server never carries out permission checks (allowing anybody to copy ; any item, etc. This may not yet be implemented uniformally. ; If set to true, then all permissions checks are carried out -- cgit v1.1 From b860c8021e2fcc2522c931d7e503299079924743 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 1 Aug 2010 10:23:48 -0700 Subject: First, change DefaultPermissionsModule so it returns the correct name... ... Then, make sure we also check the old-style module stack before we throw a tantrum --- OpenSim/Region/Application/OpenSimBase.cs | 15 +++++++++++++-- .../CoreModules/World/Permissions/PermissionsModule.cs | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 9267721..fc67f94 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -357,8 +357,19 @@ namespace OpenSim { if (!scene.RegionModules.ContainsKey(s)) { - m_log.Fatal("[MODULES]: Required module " + s + " not found."); - Environment.Exit(0); + bool found = false; + foreach (IRegionModule m in modules) + { + if (m.Name == s) + { + found = true; + } + } + if (!found) + { + m_log.Fatal("[MODULES]: Required module " + s + " not found."); + Environment.Exit(0); + } } } } diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 1d70546..8223f12 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -402,7 +402,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions public string Name { - get { return "PermissionsModule"; } + get { return "DefaultPermissionsModule"; } } public bool IsSharedModule -- cgit v1.1 From 763dc8bb76396aeea515b2c7c745cc2eb3a510a9 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 1 Aug 2010 10:24:17 -0700 Subject: Add an m_enabled flag to XmlRpcRouterModule so it won't try to bind the xmlrpc_uri event if it's not mentioned in the ini. --- .../Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs index 32659c8..dcac4a9 100644 --- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs @@ -42,7 +42,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule public class XmlRpcRouter : IRegionModule, IXmlRpcRouter { //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + private bool m_enabled = false; public void Initialise(Scene scene, IConfigSource config) { IConfig startupConfig = config.Configs["Startup"]; @@ -53,6 +53,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule "XmlRpcRouterModule") == "XmlRpcRouterModule") { scene.RegisterModuleInterface(this); + m_enabled = true; + } + else + { + m_enabled = false; } } @@ -76,7 +81,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule public void RegisterNewReceiver(IScriptModule scriptEngine, UUID channel, UUID objectID, UUID itemID, string uri) { - scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] {uri}); + if (m_enabled) + { + scriptEngine.PostScriptEvent(itemID, "xmlrpc_uri", new Object[] { uri }); + } } public void ScriptRemoved(UUID itemID) -- cgit v1.1 From d2d56494b221be4aa202ac0a965c5b697ac38163 Mon Sep 17 00:00:00 2001 From: Tom Date: Sun, 1 Aug 2010 10:24:43 -0700 Subject: Fix the XmlRpcRouterModule so it reads from the correct config section ([XMLRPC] not [Startup]) and disable by default (since it's disabled in the ini by default) --- .../Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs index dcac4a9..11c87f8 100644 --- a/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/XmlRpcRouterModule/XmlRpcRouterModule.cs @@ -45,12 +45,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.XmlRpcRouterModule private bool m_enabled = false; public void Initialise(Scene scene, IConfigSource config) { - IConfig startupConfig = config.Configs["Startup"]; + IConfig startupConfig = config.Configs["XMLRPC"]; if (startupConfig == null) return; if (startupConfig.GetString("XmlRpcRouterModule", - "XmlRpcRouterModule") == "XmlRpcRouterModule") + "") == "XmlRpcRouterModule") { scene.RegisterModuleInterface(this); m_enabled = true; -- cgit v1.1 From 16e90809a92095f1d0f3a54ca3a7def6dd5ae3b1 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 2 Aug 2010 00:54:58 +0200 Subject: Remove the (wrong) implementation if llPointAt. It never worked on the LL grid and is officially deprecated. There is no way to rotate an avatar programmatically. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index c08c246..52d3285 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3517,17 +3517,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llPointAt(LSL_Vector pos) { m_host.AddScriptLPS(1); - ScenePresence Owner = World.GetScenePresence(m_host.UUID); - LSL_Rotation rot = llEuler2Rot(pos); - Owner.PreviousRotation = Owner.Rotation; - Owner.Rotation = (new Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s)); } public void llStopPointAt() { m_host.AddScriptLPS(1); - ScenePresence Owner = m_host.ParentGroup.Scene.GetScenePresence(m_host.OwnerID); - Owner.Rotation = Owner.PreviousRotation; } public void llTargetOmega(LSL_Vector axis, double spinrate, double gain) -- cgit v1.1 From 8f2986bc6a438ea9f5de912a5b76a196e7933175 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 2 Aug 2010 21:54:47 -0700 Subject: Catch meshing error in Meshmerizer --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index fded95e..fb2b462 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -336,16 +336,24 @@ namespace OpenSim.Region.Physics.Meshing bool mirror = ((primShape.SculptType & 128) != 0); bool invert = ((primShape.SculptType & 64) != 0); - sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); - - idata.Dispose(); + try + { + sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); + + idata.Dispose(); - sculptMesh.DumpRaw(baseDir, primName, "primMesh"); + sculptMesh.DumpRaw(baseDir, primName, "primMesh"); - sculptMesh.Scale(size.X, size.Y, size.Z); + sculptMesh.Scale(size.X, size.Y, size.Z); - coords = sculptMesh.coords; - faces = sculptMesh.faces; + coords = sculptMesh.coords; + faces = sculptMesh.faces; + } + catch(Exception ex) + { + m_log.Error("[Meshing]: Unable to generate a Sculpty mesh. " + ex.Message); + return null; + } } else { -- cgit v1.1 From d2d1c63b17a55ed1f324fafff89cfbcbd6618d11 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 3 Aug 2010 05:25:01 +0200 Subject: Revert "Catch meshing error in Meshmerizer" This reverts commit 8f2986bc6a438ea9f5de912a5b76a196e7933175. In favor of a fix that tells us where the issue is instead of eating the error --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index fb2b462..fded95e 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -336,24 +336,16 @@ namespace OpenSim.Region.Physics.Meshing bool mirror = ((primShape.SculptType & 128) != 0); bool invert = ((primShape.SculptType & 64) != 0); - try - { - sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); - - idata.Dispose(); + sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); + + idata.Dispose(); - sculptMesh.DumpRaw(baseDir, primName, "primMesh"); + sculptMesh.DumpRaw(baseDir, primName, "primMesh"); - sculptMesh.Scale(size.X, size.Y, size.Z); + sculptMesh.Scale(size.X, size.Y, size.Z); - coords = sculptMesh.coords; - faces = sculptMesh.faces; - } - catch(Exception ex) - { - m_log.Error("[Meshing]: Unable to generate a Sculpty mesh. " + ex.Message); - return null; - } + coords = sculptMesh.coords; + faces = sculptMesh.faces; } else { -- cgit v1.1 From e3184753a6956078a2e34c449d5e30843b5d7f94 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 3 Aug 2010 05:25:23 +0200 Subject: Log the UUID of a prim that fails meshing and set the prim to phantom during region startup --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b19c443..032fbe8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1497,14 +1497,21 @@ namespace OpenSim.Region.Framework.Scenes // or flexible if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) { - PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( - Name, - Shape, - AbsolutePosition, - Scale, - RotationOffset, - RigidBody); - + try + { + PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( + Name, + Shape, + AbsolutePosition, + Scale, + RotationOffset, + RigidBody); + } + catch + { + m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); + PhysActor = null; + } // Basic Physics returns null.. joy joy joy. if (PhysActor != null) { -- cgit v1.1 From f04d51378f864d2eb522678b3fb1e239f746bd35 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Aug 2010 11:06:41 -0700 Subject: Drop the RestClient timeout from 15 minutes to 30 seconds. This does not address the problem, but it will allow the regions to recover in the event that the remote server goes away. --- OpenSim/Framework/Communications/RestClient.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Framework/Communications/RestClient.cs b/OpenSim/Framework/Communications/RestClient.cs index 97b3b60..42c0b18 100644 --- a/OpenSim/Framework/Communications/RestClient.cs +++ b/OpenSim/Framework/Communications/RestClient.cs @@ -363,7 +363,7 @@ namespace OpenSim.Framework.Communications _request = (HttpWebRequest) WebRequest.Create(buildUri()); _request.KeepAlive = false; _request.ContentType = "application/xml"; - _request.Timeout = 900000; + _request.Timeout = 30000; _request.Method = RequestMethod; _asyncException = null; _request.ContentLength = src.Length; -- cgit v1.1 From 6e3c79f31e4a552ef81e73156d3f84cbcfbdb2cf Mon Sep 17 00:00:00 2001 From: Mike Rieker Date: Tue, 3 Aug 2010 20:09:00 +0000 Subject: don't mask current time reads (since we don't mask the corresponding subtract) if you mask the reads you have to mask the subtract as well. simplest is just don't mask any of it. --- OpenSim/Framework/Watchdog.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Watchdog.cs index 5d46905..bc19dd1 100644 --- a/OpenSim/Framework/Watchdog.cs +++ b/OpenSim/Framework/Watchdog.cs @@ -51,7 +51,7 @@ namespace OpenSim.Framework public ThreadWatchdogInfo(Thread thread) { Thread = thread; - LastTick = Environment.TickCount & Int32.MaxValue; + LastTick = Environment.TickCount; } } @@ -143,7 +143,7 @@ namespace OpenSim.Framework try { if (m_threads.TryGetValue(threadID, out threadInfo)) - threadInfo.LastTick = Environment.TickCount & Int32.MaxValue; + threadInfo.LastTick = Environment.TickCount; else AddThread(new ThreadWatchdogInfo(Thread.CurrentThread)); } @@ -160,7 +160,7 @@ namespace OpenSim.Framework lock (m_threads) { - int now = Environment.TickCount & Int32.MaxValue; + int now = Environment.TickCount; foreach (ThreadWatchdogInfo threadInfo in m_threads.Values) { -- cgit v1.1 From 1d1da5069ca91282228f453476bee2444138b230 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Aug 2010 14:11:11 -0700 Subject: Catch a meshing exception caused by corrupt or missing sculpt maps, and mark the prim as "mesh failed" so it doesn't try meshing continuously --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 7e70db9..60eda41 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -131,6 +131,7 @@ namespace OpenSim.Region.Physics.OdePlugin //public GCHandle gc; private CollisionLocker ode; + private bool m_meshfailed = false; private bool m_taintforce = false; private bool m_taintaddangularforce = false; private Vector3 m_force; @@ -1882,12 +1883,20 @@ namespace OpenSim.Region.Physics.OdePlugin m_targetSpace = targetspace; - if (_mesh == null) + if (_mesh == null && m_meshfailed == false) { if (_parent_scene.needsMeshing(_pbs)) { // Don't need to re-enable body.. it's done in SetMesh - _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); + try + { + _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); + } + catch + { + //Don't continuously try to mesh prims when meshing has failed + m_meshfailed = true; + } // createmesh returns null when it's a shape that isn't a cube. // m_log.Debug(m_localID); } -- cgit v1.1 From ae99c1393d4555d4cd26249b149078e4cd3d439f Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Aug 2010 15:31:04 -0700 Subject: Fix scripted sit offset in child prims --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index efe3365..1fc4a81 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1935,8 +1935,14 @@ namespace OpenSim.Region.Framework.Scenes //Console.WriteLine("Scripted, unoccupied"); part.SetAvatarOnSitTarget(UUID); // set that Av will be on it offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one - sitOrientation = avSitOrientation; // Change rotatione to the scripted one - OffsetRotation = avSitOrientation; + + Quaternion nrot = avSitOrientation; + if (!part.IsRoot) + { + nrot = nrot * part.RotationOffset; + } + sitOrientation = nrot; // Change rotatione to the scripted one + OffsetRotation = nrot; autopilot = false; // Jump direct to scripted llSitPos() } else @@ -2010,7 +2016,7 @@ namespace OpenSim.Region.Framework.Scenes // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot); // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error. // { // Single, or Root prim of linkset, target is ClickOffset * RootRot - offsetr = offset * partIRot; + //offsetr = offset * partIRot; // // else // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot) @@ -2029,7 +2035,7 @@ namespace OpenSim.Region.Framework.Scenes //Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child - ControllingClient.SendSitResponse(part.ParentGroup.UUID, offsetr + part.OffsetPosition, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); + ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target // This calls HandleAgentSit twice, once from here, and the client calls @@ -2343,6 +2349,10 @@ namespace OpenSim.Region.Framework.Scenes Quaternion sitTargetOrient = part.SitTargetOrientation; m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); m_pos += SIT_TARGET_ADJUSTMENT; + if (!part.IsRoot) + { + m_pos *= part.RotationOffset; + } m_bodyRot = sitTargetOrient; m_parentPosition = part.AbsolutePosition; part.IsOccupied = true; -- cgit v1.1 From e3cea888fba0afbb97e55b1a2aa8335f78a4ac26 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Aug 2010 16:07:18 -0700 Subject: Fix some more issues causing regions with corrupt sculpts to freeze. --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 60eda41..1604c4b 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -2136,7 +2136,7 @@ Console.WriteLine(" JointCreateFixed"); // we don't need to do space calculation because the client sends a position update also. // Construction of new prim - if (_parent_scene.needsMeshing(_pbs)) + if (_parent_scene.needsMeshing(_pbs) && m_meshfailed == false) { float meshlod = _parent_scene.meshSculptLOD; @@ -2146,8 +2146,15 @@ Console.WriteLine(" JointCreateFixed"); IMesh mesh = null; - if (_parent_scene.needsMeshing(_pbs)) - mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); + try + { + if (_parent_scene.needsMeshing(_pbs)) + mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); + } + catch + { + m_meshfailed = true; + } //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); //Console.WriteLine("changesize 1"); @@ -2242,17 +2249,23 @@ Console.WriteLine(" JointCreateFixed"); if (_size.Z <= 0) _size.Z = 0.01f; // Construction of new prim - if (_parent_scene.needsMeshing(_pbs)) + if (_parent_scene.needsMeshing(_pbs) && m_meshfailed == false) { // Don't need to re-enable body.. it's done in SetMesh float meshlod = _parent_scene.meshSculptLOD; if (IsPhysical) meshlod = _parent_scene.MeshSculptphysicalLOD; - - IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); + try + { + IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); + CreateGeom(m_targetSpace, mesh); + } + catch + { + m_meshfailed = true; + } // createmesh returns null when it doesn't mesh. - CreateGeom(m_targetSpace, mesh); } else { -- cgit v1.1 From d9ae8370632810ae10bc1ca4e7a2c51431200d0d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 4 Aug 2010 00:45:15 +0200 Subject: Allow specifying default region flags. Correct a typo. --- OpenSim/Services/GridService/GridService.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index f49d86d..ebaed42 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -124,7 +124,7 @@ namespace OpenSim.Services.GridService { // Regions reserved for the null key cannot be taken. if ((string)region.Data["PrincipalID"] == UUID.Zero.ToString()) - return "Region location us reserved"; + return "Region location is reserved"; // Treat it as an auth request // @@ -210,6 +210,7 @@ namespace OpenSim.Services.GridService { int newFlags = 0; string regionName = rdata.RegionName.Trim().Replace(' ', '_'); + newFlags = ParseFlags(newFlags, gridConfig.GetString("DefaultRegionFlags", String.Empty)); newFlags = ParseFlags(newFlags, gridConfig.GetString("Region_" + regionName, String.Empty)); newFlags = ParseFlags(newFlags, gridConfig.GetString("Region_" + rdata.RegionID.ToString(), String.Empty)); rdata.Data["flags"] = newFlags.ToString(); -- cgit v1.1 From d57bfec702fd6eb067ab5d46cb791690ae81e10d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 4 Aug 2010 02:16:46 +0200 Subject: A god is a god is a god is a god. Right? Right. You're a god from 200, let's show it! --- OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 50d2f9d..06b1b00 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -218,7 +218,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat fromPos = avatar.AbsolutePosition; fromName = avatar.Name; fromID = c.Sender.AgentId; - if (avatar.GodLevel > 200) + if (avatar.GodLevel >= 200) { fromNamePrefix = m_adminPrefix; } -- cgit v1.1 From 5ff9db7388b5b05e49092d8ee59b3d1b5c963e78 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 4 Aug 2010 02:51:41 +0200 Subject: Clean up some messiness in IM sending. Having offline IM enabled now no longer suppresses "Inventory Saved" messages. --- .../Avatar/InstantMessage/InstantMessageModule.cs | 3 ++- .../Avatar/InstantMessage/MessageTransferModule.cs | 13 ++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs index ffdac58..cbea54c 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs @@ -187,7 +187,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage delegate(bool success) { if (dialog == (uint)InstantMessageDialog.StartTyping || - dialog == (uint)InstantMessageDialog.StopTyping) + dialog == (uint)InstantMessageDialog.StopTyping || + dialog == (uint)InstantMessageDialog.MessageFromObject) { return; } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 83209fc..d025f0c 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -185,13 +185,16 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { UndeliveredMessage handlerUndeliveredMessage = OnUndeliveredMessage; - // If this event has handlers, then the IM will be considered - // delivered. This will suppress the error message. + // If this event has handlers, then an IM from an agent will be + // considered delivered. This will suppress the error message. // if (handlerUndeliveredMessage != null) { handlerUndeliveredMessage(im); - result(true); + if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) + result(true); + else + result(false); return; } @@ -504,14 +507,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // if (upd.RegionID == prevRegionID) { - m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } } else { - m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); HandleUndeliveredMessage(im, result); return; } -- cgit v1.1 From 0020dbee23bf0bab979225dbcdcc9cbcbe72f27b Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 4 Aug 2010 03:23:19 +0200 Subject: Remove StandAlone from default hardcoded config --- OpenSim/Region/Application/ConfigurationLoader.cs | 15 --------------- OpenSim/Tools/Configger/ConfigurationLoader.cs | 15 --------------- 2 files changed, 30 deletions(-) diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index cac5fa9..09f7bea 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -308,21 +308,6 @@ namespace OpenSim } { - IConfig config = defaultConfig.Configs["StandAlone"]; - - if (null == config) - config = defaultConfig.AddConfig("StandAlone"); - - config.Set("accounts_authenticate", true); - config.Set("welcome_message", "Welcome to OpenSimulator"); - config.Set("inventory_plugin", "OpenSim.Data.SQLite.dll"); - config.Set("inventory_source", ""); - config.Set("userDatabase_plugin", "OpenSim.Data.SQLite.dll"); - config.Set("user_source", ""); - config.Set("LibrariesXMLFile", string.Format(".{0}inventory{0}Libraries.xml", Path.DirectorySeparatorChar)); - } - - { IConfig config = defaultConfig.Configs["Network"]; if (null == config) diff --git a/OpenSim/Tools/Configger/ConfigurationLoader.cs b/OpenSim/Tools/Configger/ConfigurationLoader.cs index 1619a22..3d1b668 100644 --- a/OpenSim/Tools/Configger/ConfigurationLoader.cs +++ b/OpenSim/Tools/Configger/ConfigurationLoader.cs @@ -242,21 +242,6 @@ namespace OpenSim.Tools.Configger } { - IConfig config = defaultConfig.Configs["StandAlone"]; - - if (null == config) - config = defaultConfig.AddConfig("StandAlone"); - - config.Set("accounts_authenticate", true); - config.Set("welcome_message", "Welcome to OpenSimulator"); - config.Set("inventory_plugin", "OpenSim.Data.SQLite.dll"); - config.Set("inventory_source", ""); - config.Set("userDatabase_plugin", "OpenSim.Data.SQLite.dll"); - config.Set("user_source", ""); - config.Set("LibrariesXMLFile", string.Format(".{0}inventory{0}Libraries.xml", Path.DirectorySeparatorChar)); - } - - { IConfig config = defaultConfig.Configs["Network"]; if (null == config) -- cgit v1.1 From f1c51c8bb4c634cedf9eb57a1bb339d3e8052b10 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Aug 2010 19:51:32 -0700 Subject: Scripted sit target fixes --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 1fc4a81..d857a1c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1939,7 +1939,7 @@ namespace OpenSim.Region.Framework.Scenes Quaternion nrot = avSitOrientation; if (!part.IsRoot) { - nrot = nrot * part.RotationOffset; + nrot = part.RotationOffset * avSitOrientation; } sitOrientation = nrot; // Change rotatione to the scripted one OffsetRotation = nrot; -- cgit v1.1 From cd9506e8428da7b984bdd833e6855534a90f3b5e Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Aug 2010 22:41:02 -0700 Subject: Don't know HOW we missed this, llSetPos was broken in child prims (and in the llSetPrimitveParams family), it was using the global coordinate as a start location. This resolves mantis #204 --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 52d3285..0a1a10c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2116,7 +2116,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - LSL_Vector rel_vec = SetPosAdjust(currentPos, targetPos); + LSL_Vector rel_vec = SetPosAdjust(new LSL_Vector(part.OffsetPosition.X, part.OffsetPosition.Y, part.OffsetPosition.Z), targetPos); part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z); SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; -- cgit v1.1 From 463fbb4990226661238f1cc30587a5d1e270d44f Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 4 Aug 2010 00:17:02 -0700 Subject: If a user has no home position set, tell them so instead of leaving the request dangling --- .../Framework/EntityTransfer/EntityTransferModule.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 927eeab..1d1a0a1 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -549,6 +549,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (uinfo != null) { + if (uinfo.HomeRegionID == UUID.Zero) + { + // can't find the Home region: Tell viewer and abort + client.SendTeleportFailed("You don't have a home position set."); + return; + } GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID); if (regionInfo == null) { @@ -556,7 +562,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer client.SendTeleportFailed("Your home region could not be found."); return; } - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})", + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})", regionInfo.RegionName, regionInfo.RegionID, regionInfo.RegionLocX / Constants.RegionSize, regionInfo.RegionLocY / Constants.RegionSize); // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point... @@ -564,6 +570,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome)); } + else + { + // can't find the Home region: Tell viewer and abort + client.SendTeleportFailed("Your home region could not be found."); + return; + } } #endregion -- cgit v1.1 From a48c4932108c68156ee62e9e39da618e55d85902 Mon Sep 17 00:00:00 2001 From: sacha Date: Wed, 4 Aug 2010 08:16:55 +0000 Subject: Cost Reduction : Removing verbose message.... --- .../CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 0d04491..98545f9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -153,7 +153,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer private void OnInstantMessage(IClientAPI client, GridInstantMessage im) { - m_log.InfoFormat("[INVENTORY TRANSFER]: OnInstantMessage {0}", im.dialog); + //m_log.InfoFormat("[INVENTORY TRANSFER]: OnInstantMessage {0}", im.dialog); Scene scene = FindClientScene(client.AgentId); -- cgit v1.1 From 4a3321077163f4e93ac67609428c0e6fa4d31b9e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 4 Aug 2010 18:12:31 +0200 Subject: Send attachment updates only to the owner if it's a HUD --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index a9f9d60..4ab719d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3485,6 +3485,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) { + if (entity is SceneObjectPart) + { + SceneObjectPart e = (SceneObjectPart)entity; + SceneObjectGroup g = e.ParentGroup; + if (g.RootPart.Shape.State > 30) // HUD + if (g.OwnerID != AgentId) + return; // Don't send updates for other people's HUDs + } + double priority = m_prioritizer.GetUpdatePriority(this, entity); lock (m_entityUpdates.SyncRoot) -- cgit v1.1 From cb3b124df9213bf12383a5625ac4e545fcc91b87 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Wed, 4 Aug 2010 21:08:00 +0000 Subject: Fixes fresh hollowed prim collision shape. --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 6 +++--- .../storage/SQLiteLegacyStandalone.ini | 16 -------------- bin/config-include/storage/SQLiteStandalone.ini | 25 ---------------------- 3 files changed, 3 insertions(+), 44 deletions(-) delete mode 100644 bin/config-include/storage/SQLiteLegacyStandalone.ini delete mode 100644 bin/config-include/storage/SQLiteStandalone.ini diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 7e70db9..6aa28e0 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -1331,10 +1331,10 @@ namespace OpenSim.Region.Physics.OdePlugin _parent_scene.waitForSpaceUnlock(m_targetSpace); try { - if (prim_geom == IntPtr.Zero) - { + // if (prim_geom == IntPtr.Zero) // setGeom takes care of phys engine recreate and prim_geom pointer + // { SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); - } + // } } catch (AccessViolationException) { diff --git a/bin/config-include/storage/SQLiteLegacyStandalone.ini b/bin/config-include/storage/SQLiteLegacyStandalone.ini deleted file mode 100644 index 1d4dd29..0000000 --- a/bin/config-include/storage/SQLiteLegacyStandalone.ini +++ /dev/null @@ -1,16 +0,0 @@ -; These are the initialization settings for running OpenSim Standalone with an SQLite database - -[DatabaseService] - StorageProvider = "OpenSim.Data.SQLiteLegacy.dll" - -[AvatarService] - ConnectionString = "URI=file:avatars.db,version=3" - -[AuthenticationService] - ConnectionString = "URI=file:auth.db,version=3" - -[UserAccountService] - ConnectionString = "URI=file:userprofiles.db,version=3" - -[FriendsService] - ConnectionString = "URI=file:friends.db,version=3" diff --git a/bin/config-include/storage/SQLiteStandalone.ini b/bin/config-include/storage/SQLiteStandalone.ini deleted file mode 100644 index fe814d7..0000000 --- a/bin/config-include/storage/SQLiteStandalone.ini +++ /dev/null @@ -1,25 +0,0 @@ -; These are the initialization settings for running OpenSim Standalone with an SQLite database - -[DatabaseService] - StorageProvider = "OpenSim.Data.SQLite.dll" - -[InventoryService] - ;ConnectionString = "URI=file:inventory.db,version=3" - ; if you have a legacy inventory store use the connection string below - ConnectionString = "URI=file:inventory.db,version=3,UseUTF16Encoding=True" - -[AvatarService] - ConnectionString = "URI=file:avatars.db,version=3" - -[AuthenticationService] - ConnectionString = "URI=file:auth.db,version=3" - -[UserAccountService] - ConnectionString = "URI=file:userprofiles.db,version=3" - -[GridUserService] - ConnectionString = "URI=file:griduser.db,version=3" - -[FriendsService] - ConnectionString = "URI=file:friends.db,version=3" - -- cgit v1.1 From 663e25fd3a67654ea60f91850302f2f17496ba59 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 4 Aug 2010 19:46:41 -0700 Subject: Pacify osGetAvatarList to provide LSL types instead of omv types --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index db43902..80b021f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2222,9 +2222,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (avatar.IsChildAgent == false) { - result.Add(avatar.UUID); - result.Add(avatar.AbsolutePosition); - result.Add(avatar.Name); + result.Add(new LSL_Key(avatar.UUID.ToString())); + result.Add(new LSL_Vector(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z)); + result.Add(new LSL_String(avatar.Name)); } } }); -- cgit v1.1 From 85fd2def9ce04d68d838439e7931b8358db84ebd Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 5 Aug 2010 08:15:05 -0700 Subject: Enforce a 0.2 second sleep on llDie() before the command is executed - this should get rid of ghost prims (which are much rarer, but still occuring) --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0a1a10c..411c811 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1173,7 +1173,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public virtual void llDie() { m_host.AddScriptLPS(1); - if (!m_host.IsAttachment) throw new SelfDeleteException(); + if (!m_host.IsAttachment) + { + //Enforce a sleep here to avoid ghost prims + llSleep(0.2d); + throw new SelfDeleteException(); + } } public LSL_Float llGround(LSL_Vector offset) -- cgit v1.1 From 0eda6714f332b2883e109312b134b102b732bcea Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 5 Aug 2010 08:41:08 -0700 Subject: llRequestSimulatorData DATA_SIM_POS : Divide by RegionSize, don't multiply. This resolves mantis #215 --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 411c811..d61715e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8881,8 +8881,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return UUID.Zero.ToString(); } reply = new LSL_Vector( - info.RegionLocX * Constants.RegionSize, - info.RegionLocY * Constants.RegionSize, + info.RegionLocX / Constants.RegionSize, + info.RegionLocY / Constants.RegionSize, 0).ToString(); break; case 6: // DATA_SIM_STATUS -- cgit v1.1 From 05520d676ccee950c94d1f8c079afaaaabdb6a49 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 5 Aug 2010 18:45:17 +0200 Subject: Revert "Enforce a 0.2 second sleep on llDie() before the command is executed - this should get rid of ghost prims (which are much rarer, but still occuring)" This reverts commit 85fd2def9ce04d68d838439e7931b8358db84ebd. The sleep helps in only one case: static prims rezzed by script. In other cases (physical prims, bullets) it's harmful. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d61715e..bc47fa1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1173,12 +1173,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public virtual void llDie() { m_host.AddScriptLPS(1); - if (!m_host.IsAttachment) - { - //Enforce a sleep here to avoid ghost prims - llSleep(0.2d); - throw new SelfDeleteException(); - } + if (!m_host.IsAttachment) throw new SelfDeleteException(); } public LSL_Float llGround(LSL_Vector offset) -- cgit v1.1 From 8bdbcda2b70ede033c38a604af573554dd2776ad Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 5 Aug 2010 18:50:17 +0200 Subject: We already have a record of killed prims. It just wasn't used by the new JHurlicane code anymore. Use it to prevent sending updates after kills. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 9 +++++++++ OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 4ab719d..0b8b95b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3514,6 +3514,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP EntityUpdate update; while (updatesThisCall < maxUpdates && m_entityUpdates.TryDequeue(out update)) { + // If we have sent a kill packet for this object + // drop any updates on the floor + if (update.Entity is SceneObjectPart) + { + SceneObjectPart part = (SceneObjectPart)update.Entity; + if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId)) + continue; + } + ++updatesThisCall; #region UpdateFlags to packet type conversion diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 032fbe8..67cb7cc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -3043,6 +3043,15 @@ namespace OpenSim.Region.Framework.Scenes UUID ownerID = _ownerID; UUID objectID = UUID; UUID parentID = GetRootPartUUID(); + + if (ParentGroup.IsAttachment && ParentGroup.RootPart.Shape.State > 30) + { + // Use the avatar as the parent for HUDs, since the prims + // are not sent to other avatars + objectID = _ownerID; + parentID = _ownerID; + } + UUID soundID = UUID.Zero; Vector3 position = AbsolutePosition; // region local ulong regionHandle = m_parentGroup.Scene.RegionInfo.RegionHandle; -- cgit v1.1 From d8f9b98c4ab700efcf4016b605461053c3b50fba Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 5 Aug 2010 22:50:09 +0200 Subject: Prevent hammering the grid services with llRequestAgentData requests. Cache the user information permanently, and the online status for 20 seconds. Also cache negatives. --- .../Shared/Api/Implementation/LSL_Api.cs | 55 +++++++++++++++++++--- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index bc47fa1..ad7d650 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -69,6 +69,14 @@ using System.Reflection; namespace OpenSim.Region.ScriptEngine.Shared.Api { + // MUST be a ref type + public class UserInfoCacheEntry + { + public int time; + public UserAccount account; + public PresenceInfo pinfo; + } + /// /// Contains all LSL ll-functions. This class will be in Default AppDomain. /// @@ -93,6 +101,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected int m_scriptConsoleChannel = 0; protected bool m_scriptConsoleChannelEnabled = false; protected IUrlModule m_UrlModule = null; + protected Dictionary m_userInfoCache = + new Dictionary(); public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) { @@ -4244,16 +4254,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); UUID uuid = (UUID)id; + PresenceInfo pinfo = null; + UserAccount account; - UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); - if (account == null) - return UUID.Zero.ToString(); + UserInfoCacheEntry ce; + if (!m_userInfoCache.TryGetValue(uuid, out ce)) + { + account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); + if (account == null) + { + m_userInfoCache[uuid] = null; // Cache negative + return UUID.Zero.ToString(); + } - PresenceInfo pinfo = null; - PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); - if (pinfos != null && pinfos.Length > 0) - pinfo = pinfos[0]; + PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); + if (pinfos != null && pinfos.Length > 0) + pinfo = pinfos[0]; + + ce = new UserInfoCacheEntry(); + ce.time = Util.EnvironmentTickCount(); + ce.account = account; + ce.pinfo = pinfo; + } + else + { + if (ce == null) + return UUID.Zero.ToString(); + + account = ce.account; + pinfo = ce.pinfo; + } + + if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) + { + PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); + if (pinfos != null && pinfos.Length > 0) + pinfo = pinfos[0]; + + ce.time = Util.EnvironmentTickCount(); + ce.pinfo = pinfo; + } string reply = String.Empty; -- cgit v1.1 From 7368992ee9bbf1aeb5034715e693c82d8ddd4b97 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 5 Aug 2010 23:48:55 +0200 Subject: Actually cache positives --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ad7d650..0f38261 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4276,6 +4276,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ce.time = Util.EnvironmentTickCount(); ce.account = account; ce.pinfo = pinfo; + m_userInfoCache[uuid] = ce; } else { -- cgit v1.1 From d7fe9f7b44311df517a8755dd6cf5603b380c3b8 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 6 Aug 2010 00:02:38 +0200 Subject: Prevent users from becoming stuck online. This affects only 0.7 --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0f38261..236458c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4292,6 +4292,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); if (pinfos != null && pinfos.Length > 0) pinfo = pinfos[0]; + else + pinfo = null; ce.time = Util.EnvironmentTickCount(); ce.pinfo = pinfo; -- cgit v1.1 From c5c6627adb79644b93c5871243a9eeeff553829c Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 6 Aug 2010 02:39:42 -0700 Subject: Implement CHANGED_REGION_(RE)START and also fix various CHANGED_* constants which had the wrong values (checked using LSL in SL). This addresses mantis #217 and mantis #53. --- .../Framework/Scenes/Animation/ScenePresenceAnimator.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 7 ++++--- .../Region/Framework/Scenes/SceneObjectPartInventory.cs | 16 ++++++++++++++++ OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- .../ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | 8 ++++---- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 4 ++-- 6 files changed, 28 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 702a1e2..b847d87 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -130,7 +130,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) { // 16384 is CHANGED_ANIMATION - m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { 16384 }); + m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); SendAnimPack(); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 032fbe8..a0fabff 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -56,9 +56,10 @@ namespace OpenSim.Region.Framework.Scenes LINK = 32, ALLOWED_DROP = 64, OWNER = 128, - REGION_RESTART = 256, - REGION = 512, - TELEPORT = 1024 + REGION = 256, + TELEPORT = 512, + REGION_RESTART = 1024, + ANIMATION = 16384 } // I don't really know where to put this except here. diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 8b4f0ed..4f80a7e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -321,6 +321,22 @@ namespace OpenSim.Region.Framework.Scenes StoreScriptErrors(item.ItemID, null); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); + + //This should play nice with XEngine since XEngine loads scripts /after/ the region starts + if (stateSource == 0 && m_part.ParentGroup.Scene.LoginsDisabled == true) + { + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); + if (engines != null) + { + foreach (IScriptModule xengine in engines) + { + if (xengine != null) + { + xengine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.REGION_RESTART }); + } + } + } + } } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index d857a1c..5fcd1c2 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3939,7 +3939,7 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); if (m == null) // No script engine loaded continue; - m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { 16384 }); + m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION }); } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 96f6486..69f48c9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -273,10 +273,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int CHANGED_LINK = 32; public const int CHANGED_ALLOWED_DROP = 64; public const int CHANGED_OWNER = 128; - public const int CHANGED_REGION_RESTART = 256; - public const int CHANGED_REGION_START = 256; //LL Changed the constant from CHANGED_REGION_RESTART - public const int CHANGED_REGION = 512; - public const int CHANGED_TELEPORT = 1024; + public const int CHANGED_REGION = 256; + public const int CHANGED_TELEPORT = 512; + public const int CHANGED_REGION_RESTART = 1024; + public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART public const int CHANGED_ANIMATION = 16384; public const int TYPE_INVALID = 0; public const int TYPE_INTEGER = 1; diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index b348403..dcbe0c4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -392,13 +392,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { // m_log.Debug("[Script] Posted changed(CHANGED_REGION_RESTART) to script"); PostEvent(new EventParams("changed", - new Object[] {new LSL_Types.LSLInteger(256)}, new DetectParams[0])); + new Object[] { (int)Changed.REGION_RESTART }, new DetectParams[0])); } else if (m_stateSource == StateSource.PrimCrossing) { // CHANGED_REGION PostEvent(new EventParams("changed", - new Object[] {new LSL_Types.LSLInteger(512)}, new DetectParams[0])); + new Object[] { (int)Changed.REGION }, new DetectParams[0])); } } else -- cgit v1.1 From a390541e1c114db419d9a2eb1ac576a582c35e67 Mon Sep 17 00:00:00 2001 From: sacha Date: Fri, 6 Aug 2010 14:38:11 +0000 Subject: Allowing the expected purge trash folder... Please validate !!! --- OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs | 1 + OpenSim/Services/InventoryService/XInventoryService.cs | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index ac6a3ab..e3d30e5 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -408,6 +408,7 @@ namespace OpenSim.Server.Handlers.Asset byte[] HandlePurgeFolder(Dictionary request) { + Dictionary result = new Dictionary(); UUID folderID = UUID.Zero; UUID.TryParse(request["ID"].ToString(), out folderID); diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index f581f76..fc5020d 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -329,8 +329,8 @@ namespace OpenSim.Services.InventoryService if (!m_AllowDelete) return false; - if (!ParentIsTrash(folder.ID)) - return false; +// if (!ParentIsTrash(folder.ID)) +// return false; XInventoryFolder[] subFolders = m_Database.GetFolders( new string[] { "parentFolderID" }, @@ -342,6 +342,7 @@ namespace OpenSim.Services.InventoryService m_Database.DeleteFolders("folderID", x.folderID.ToString()); } + if (!ParentIsTrash(folder.ID)) m_Database.DeleteItems("parentFolderID", folder.ID.ToString()); return true; -- cgit v1.1 From 5da272d0425cc6a971b60a1e5fad556d4d66eb52 Mon Sep 17 00:00:00 2001 From: sacha Date: Fri, 6 Aug 2010 14:45:54 +0000 Subject: reverese my last commit --- OpenSim/Services/InventoryService/XInventoryService.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index fc5020d..541489f 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -329,8 +329,8 @@ namespace OpenSim.Services.InventoryService if (!m_AllowDelete) return false; -// if (!ParentIsTrash(folder.ID)) -// return false; + if (!ParentIsTrash(folder.ID)) + return false; XInventoryFolder[] subFolders = m_Database.GetFolders( new string[] { "parentFolderID" }, @@ -342,8 +342,6 @@ namespace OpenSim.Services.InventoryService m_Database.DeleteFolders("folderID", x.folderID.ToString()); } - if (!ParentIsTrash(folder.ID)) - m_Database.DeleteItems("parentFolderID", folder.ID.ToString()); return true; } -- cgit v1.1 From 42613ec53602093335ebe3ce5127d797318bdf23 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 6 Aug 2010 15:18:48 +0200 Subject: Allow the trash folder itself to be passed to PurgeFolder --- OpenSim/Services/InventoryService/XInventoryService.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 541489f..26c5b33 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -541,6 +541,9 @@ namespace OpenSim.Services.InventoryService if (folder.Length < 1) return false; + if (folder[0].type == (int)AssetType.TrashFolder) + return true; + UUID parentFolder = folder[0].parentFolderID; while (parentFolder != UUID.Zero) -- cgit v1.1 From 696c2c429b3240d775053444943dcfc69c1b814a Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 6 Aug 2010 15:33:22 +0200 Subject: Change XEngine to use the new constant --- OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index dcbe0c4..b4da246 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -388,7 +388,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance PostEvent(new EventParams("attach", new object[] { new LSL_Types.LSLString(m_AttachedAvatar.ToString()) }, new DetectParams[0])); } - else if (m_stateSource == StateSource.NewRez) + else if (m_stateSource == StateSource.RegionStart) { // m_log.Debug("[Script] Posted changed(CHANGED_REGION_RESTART) to script"); PostEvent(new EventParams("changed", -- cgit v1.1 From a636af13e77aae588f425b7bc9504854a7ed1261 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 6 Aug 2010 06:37:40 -0700 Subject: Make sure the avatar position gets moved along with a prim it is sitting on. This fixes mantis #208 and (maybe) issues with chat and sound coming from the wrong place when sat on a vehicle. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 13 +++++++++++-- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 22 ++++++++-------------- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 13 +++++++++++++ 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index dbf493c..5a3dc20 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -469,13 +469,22 @@ namespace OpenSim.Region.Framework.Scenes return; } } - foreach (SceneObjectPart part in m_parts.Values) + List parts = new List(m_parts.Values); + lockPartsForRead(false); + foreach (SceneObjectPart part in parts) { part.IgnoreUndoUpdate = false; part.StoreUndoState(UndoType.STATE_GROUP_POSITION); part.GroupPosition = val; } - lockPartsForRead(false); + + foreach (ScenePresence av in m_linkedAvatars) + { + Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; + av.AbsolutePosition += offset; + av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition + av.SendFullUpdateToAllClients(); + } //if (m_rootPart.PhysActor != null) //{ diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index ba84b88..badd357 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -682,25 +682,13 @@ namespace OpenSim.Region.Framework.Scenes // Tell the physics engines that this prim changed. m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); + } catch (Exception e) { m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); } } - - // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too - if (m_sitTargetAvatar != UUID.Zero) - { - if (m_parentGroup != null) // TODO can there be a SOP without a SOG? - { - ScenePresence avatar; - if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar)) - { - avatar.ParentPosition = GetWorldPosition(); - } - } - } } } @@ -709,6 +697,7 @@ namespace OpenSim.Region.Framework.Scenes get { return m_offsetPosition; } set { + Vector3 oldpos = m_offsetPosition; StoreUndoState(UndoType.STATE_PRIM_POSITION); m_offsetPosition = value; @@ -727,7 +716,12 @@ namespace OpenSim.Region.Framework.Scenes List avs = ParentGroup.GetLinkedAvatars(); foreach (ScenePresence av in avs) { - av.SendFullUpdateToAllClients(); + if (av.LinkedPrim == m_uuid) + { + Vector3 offset = (m_offsetPosition - oldpos); + av.OffsetPosition += offset; + av.SendFullUpdateToAllClients(); + } } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 5fcd1c2..44c3d12 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -595,11 +595,21 @@ namespace OpenSim.Region.Framework.Scenes private uint m_parentID; + + private UUID m_linkedPrim; + public uint ParentID { get { return m_parentID; } set { m_parentID = value; } } + + public UUID LinkedPrim + { + get { return m_linkedPrim; } + set { m_linkedPrim = value; } + } + public float Health { get { return m_health; } @@ -1835,6 +1845,7 @@ namespace OpenSim.Region.Framework.Scenes m_parentPosition = Vector3.Zero; m_parentID = 0; + m_linkedPrim = UUID.Zero; m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); SendFullUpdateToAllClients(); m_requestedSitTargetID = 0; @@ -2422,6 +2433,8 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); m_parentID = m_requestedSitTargetID; } + m_linkedPrim = part.UUID; + Velocity = Vector3.Zero; RemoveFromPhysicalScene(); -- cgit v1.1 From 3ce335c6f865e1b42fbefd44f38f9a2da09ef853 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 6 Aug 2010 06:41:25 -0700 Subject: Fix StateSource constants, provide RegionStart --- OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs index 9f6ea35..0c99d8c 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs @@ -38,10 +38,11 @@ namespace OpenSim.Region.ScriptEngine.Interfaces { public enum StateSource { - NewRez = 0, - PrimCrossing = 1, - ScriptedRez = 2, - AttachedRez = 3 + RegionStart = 0, + NewRez = 1, + PrimCrossing = 2, + ScriptedRez = 3, + AttachedRez = 4 } public interface IScriptWorkItem -- cgit v1.1 From c48be64d9ab82676a2c1894193db42f0a849ae4d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 6 Aug 2010 16:08:50 +0200 Subject: Remove posting region restart event from SOP, as it's now in XMRe --- .../Region/Framework/Scenes/SceneObjectPartInventory.cs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 4f80a7e..8b4f0ed 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -321,22 +321,6 @@ namespace OpenSim.Region.Framework.Scenes StoreScriptErrors(item.ItemID, null); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); - - //This should play nice with XEngine since XEngine loads scripts /after/ the region starts - if (stateSource == 0 && m_part.ParentGroup.Scene.LoginsDisabled == true) - { - IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); - if (engines != null) - { - foreach (IScriptModule xengine in engines) - { - if (xengine != null) - { - xengine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.REGION_RESTART }); - } - } - } - } } } } -- cgit v1.1 From 52e2360e9178394664d6925e14da8468cbf90cd5 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 6 Aug 2010 08:08:43 -0700 Subject: Since i've narrowed the fault down to one function, add some spammy debug to try and fix ghost prims on HUDs in future. Note, the console only gets messages if there is a problem, so it's harmless. --- .../InventoryAccess/InventoryAccessModule.cs | 57 ++++++++++++++++++---- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index c300250..2517a23 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -496,6 +496,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (item != null) { + if (item.ID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 1"); + } + AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); if (rezAsset != null) @@ -518,11 +523,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess itemId = item.ID; } + if (item.ID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 2"); + } + string xmlData = Utils.BytesToString(rezAsset.Data); SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); Vector3 storedPosition = group.AbsolutePosition; - + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 3"); + } group.RootPart.FromFolderID = item.Folder; // If it's rezzed in world, select it. Much easier to @@ -548,9 +561,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess remoteClient.SendBulkUpdateInventory(item); return null; } - + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 4"); + } group.ResetIDs(); - + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 5"); + } if (attachment) { group.RootPart.ObjectFlags |= (uint)PrimFlags.Phantom; @@ -582,7 +601,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { group.SetFromItemID(itemID); } - + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 6"); + } SceneObjectPart rootPart = null; try { @@ -597,7 +619,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); } - + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 7"); + } // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the // object itself before we rez. @@ -625,7 +650,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess group.ApplyNextOwnerPermissions(); } } - + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 8"); + } foreach (SceneObjectPart part in partList) { if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) @@ -638,9 +666,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess part.EveryoneMask = item.EveryOnePermissions; part.NextOwnerMask = item.NextPermissions; } - + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 9"); + } rootPart.TrimPermissions(); - + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 10"); + } if (!attachment) { if (group.RootPart.Shape.PCode == (byte)PCode.Prim) @@ -674,8 +708,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } } - - return rootPart.ParentGroup; + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 11"); + } + return group; } } -- cgit v1.1 From 03da22378e23ae5c74d320d09878e7e2fa7756c8 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 6 Aug 2010 09:53:40 -0700 Subject: Estate managers should be allowed to add and remove new users, groups and bans to/from the estate settings. --- OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 940b535..ee151da 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -250,7 +250,7 @@ namespace OpenSim.Region.CoreModules.World.Estate if ((estateAccessType & 4) != 0) // User add { - if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions()) + if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions()) { m_scene.RegionInfo.EstateSettings.AddEstateUser(user); m_scene.RegionInfo.EstateSettings.Save(); @@ -265,7 +265,7 @@ namespace OpenSim.Region.CoreModules.World.Estate } if ((estateAccessType & 8) != 0) // User remove { - if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions()) + if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions()) { m_scene.RegionInfo.EstateSettings.RemoveEstateUser(user); m_scene.RegionInfo.EstateSettings.Save(); @@ -280,7 +280,7 @@ namespace OpenSim.Region.CoreModules.World.Estate } if ((estateAccessType & 16) != 0) // Group add { - if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions()) + if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions()) { m_scene.RegionInfo.EstateSettings.AddEstateGroup(user); m_scene.RegionInfo.EstateSettings.Save(); @@ -294,7 +294,7 @@ namespace OpenSim.Region.CoreModules.World.Estate } if ((estateAccessType & 32) != 0) // Group remove { - if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || m_scene.Permissions.BypassPermissions()) + if (m_scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || m_scene.Permissions.BypassPermissions()) { m_scene.RegionInfo.EstateSettings.RemoveEstateGroup(user); m_scene.RegionInfo.EstateSettings.Save(); -- cgit v1.1 From 330343505ca2d6d109e89b4767f4351ab9bec91d Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 6 Aug 2010 11:39:10 -0700 Subject: Implement CreateNewOutfitAttachments. This addresses mantis #199. --- OpenSim/Client/MXP/ClientStack/MXPClientView.cs | 1 + .../Sirikata/ClientStack/SirikataClientView.cs | 1 + .../Client/VWoHTTP/ClientStack/VWHClientView.cs | 1 + OpenSim/Framework/IClientAPI.cs | 4 +++ .../Region/ClientStack/LindenUDP/LLClientView.cs | 33 ++++++++++++++++++++++ .../Region/Examples/SimpleModule/MyNpcCharacter.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 20 +++++++++++++ OpenSim/Region/Framework/Scenes/Scene.cs | 1 + .../Server/IRCClientView.cs | 1 + .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 2 +- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 11 files changed, 65 insertions(+), 3 deletions(-) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index ce2e9a1..84c6916 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -593,6 +593,7 @@ namespace OpenSim.Client.MXP.ClientStack public event DisconnectUser OnDisconnectUser; public event RequestAvatarProperties OnRequestAvatarProperties; public event SetAlwaysRun OnSetAlwaysRun; + public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy; public event TeleportLandmarkRequest OnTeleportLandmarkRequest; public event DeRezObject OnDeRezObject; public event Action OnRegionHandShakeReply; diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index 2063616..6ad5f5a 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -253,6 +253,7 @@ namespace OpenSim.Client.Sirikata.ClientStack public event AddNewPrim OnAddPrim; public event FetchInventory OnAgentDataUpdateRequest; public event TeleportLocationRequest OnSetStartLocationRequest; + public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy; public event RequestGodlikePowers OnRequestGodlikePowers; public event GodKickUser OnGodKickUser; public event ObjectDuplicate OnObjectDuplicate; diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 841f9a4..8ef411b 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -290,6 +290,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack public event GenericCall2 OnStopMovement = delegate { }; public event Action OnRemoveAvatar = delegate { }; public event ObjectPermissions OnObjectPermissions = delegate { }; + public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy = delegate { }; public event CreateNewInventoryItem OnCreateNewInventoryItem = delegate { }; public event LinkInventoryItem OnLinkInventoryItem = delegate { }; public event CreateInventoryFolder OnCreateNewInventoryFolder = delegate { }; diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 95aec94..07bded6 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -264,6 +264,9 @@ namespace OpenSim.Framework public delegate void MoveInventoryItem( IClientAPI remoteClient, List items); + public delegate void MoveItemsAndLeaveCopy( + IClientAPI remoteClient, List items, UUID destFolder); + public delegate void RemoveInventoryItem( IClientAPI remoteClient, List itemIDs); @@ -772,6 +775,7 @@ namespace OpenSim.Framework event RequestTaskInventory OnRequestTaskInventory; event UpdateInventoryItem OnUpdateInventoryItem; event CopyInventoryItem OnCopyInventoryItem; + event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy; event MoveInventoryItem OnMoveInventoryItem; event RemoveInventoryFolder OnRemoveInventoryFolder; event RemoveInventoryItem OnRemoveInventoryItem; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 0b8b95b..cd7c11b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -154,6 +154,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event RequestTaskInventory OnRequestTaskInventory; public event UpdateInventoryItem OnUpdateInventoryItem; public event CopyInventoryItem OnCopyInventoryItem; + public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy; public event MoveInventoryItem OnMoveInventoryItem; public event RemoveInventoryItem OnRemoveInventoryItem; public event RemoveInventoryFolder OnRemoveInventoryFolder; @@ -4840,6 +4841,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); + AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments); AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); @@ -9349,6 +9351,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP { return true; } + + private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack) + { + CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack; + + #region Packet Session and User Check + if (m_checkPackets) + { + if (packet.AgentData.SessionID != SessionId || + packet.AgentData.AgentID != AgentId) + return true; + } + #endregion + MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null; + List items = new List(); + foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData) + { + InventoryItemBase b = new InventoryItemBase(); + b.ID = n.OldItemID; + b.Folder = n.OldFolderID; + items.Add(b); + } + + handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy; + if (handlerMoveItemsAndLeaveCopy != null) + { + handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID); + } + + return true; + } private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) { diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 4db8f9e..cdc56a2 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -79,7 +79,7 @@ namespace OpenSim.Region.Examples.SimpleModule public event DisconnectUser OnDisconnectUser; public event RequestAvatarProperties OnRequestAvatarProperties; public event SetAlwaysRun OnSetAlwaysRun; - + public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy; public event DeRezObject OnDeRezObject; public event Action OnRegionHandShakeReply; public event GenericCall2 OnRequestWearables; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 59731f7..17159b4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -648,6 +648,8 @@ namespace OpenSim.Region.Framework.Scenes return; } + if (newName == null) newName = item.Name; + AssetBase asset = AssetService.Get(item.AssetID.ToString()); if (asset != null) @@ -695,6 +697,24 @@ namespace OpenSim.Region.Framework.Scenes } /// + /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit) + /// + public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List items, UUID destfolder) + { + List moveitems = new List(); + foreach (InventoryItemBase b in items) + { + CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null); + InventoryItemBase n = InventoryService.GetItem(b); + n.Folder = destfolder; + moveitems.Add(n); + remoteClient.SendInventoryItemCreateUpdate(n, 0); + } + + MoveInventoryItem(remoteClient, moveitems); + } + + /// /// Move an item within the agent's inventory. /// /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 644fbb0..ea52ffb 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2922,6 +2922,7 @@ namespace OpenSim.Region.Framework.Scenes client.OnFetchInventory += HandleFetchInventory; client.OnUpdateInventoryItem += UpdateInventoryItemAsset; client.OnCopyInventoryItem += CopyInventoryItem; + client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy; client.OnMoveInventoryItem += MoveInventoryItem; client.OnRemoveInventoryItem += RemoveInventoryItem; client.OnRemoveInventoryFolder += RemoveInventoryFolder; diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index c7a9484..91cbee9 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -815,6 +815,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event ObjectOwner OnObjectOwner; public event DirPlacesQuery OnDirPlacesQuery; public event DirFindQuery OnDirFindQuery; + public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy; public event DirLandQuery OnDirLandQuery; public event DirPopularQuery OnDirPopularQuery; public event DirClassifiedQuery OnDirClassifiedQuery; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 23255fb..d6f4d53 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -156,7 +156,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC #pragma warning disable 67 public event Action OnLogout; public event ObjectPermissions OnObjectPermissions; - + public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy; public event MoneyTransferRequest OnMoneyTransferRequest; public event ParcelBuy OnParcelBuy; public event Action OnConnectionClosed; diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 2993b46..1e4bc2a 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -65,7 +65,7 @@ namespace OpenSim.Tests.Common.Mock public event MoneyTransferRequest OnMoneyTransferRequest; public event ParcelBuy OnParcelBuy; public event Action OnConnectionClosed; - + public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy; public event ImprovedInstantMessage OnInstantMessage; public event ChatMessage OnChatFromClient; public event TextureRequest OnRequestTexture; -- cgit v1.1 From a783f048a37e759e522cf73d482d6478ddc348d6 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 7 Aug 2010 03:38:35 +0200 Subject: Make the landmark properties and search places work again --- .../CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs index b0ace39..153c2a5 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs @@ -90,7 +90,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land if (!m_Enabled) return; - m_GridService = scene.GridService; m_LocalService.AddRegion(scene); scene.RegisterModuleInterface(this); } @@ -103,6 +102,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land public void RegionLoaded(Scene scene) { + m_GridService = scene.GridService; } -- cgit v1.1 From fa11ac8c851d4471640dfb0381ca285d0e5299d7 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 7 Aug 2010 05:42:30 +0200 Subject: Change the (hackish) constant to match the changed enum for attachs --- OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index e557d2c..c802490 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -293,8 +293,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } // Fire after attach, so we don't get messy perms dialogs - // 3 == AttachedRez - objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 3); + // 4 == AttachedRez + objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); objatt.ResumeScripts(); // Do this last so that event listeners have access to all the effects of the attachment -- cgit v1.1 From c554de75010a442753cce29ee06d2b60d7b4701a Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 7 Aug 2010 05:45:52 +0200 Subject: Correct display of landmark about info. Also correct region maturity rating in LM info. Maturity is NOT the parcel's setting, that is only for the image and text. Parcel maturity is governed by region maturity. --- OpenSim/Framework/Util.cs | 12 +++++++++++- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 6 +++--- .../ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs | 4 +++- .../ServiceConnectorsOut/Land/LocalLandServiceConnector.cs | 4 +++- .../ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs | 6 +++--- .../Region/CoreModules/World/Land/LandManagementModule.cs | 6 +++++- OpenSim/Server/Handlers/Land/LandHandlers.cs | 4 +++- OpenSim/Services/Connectors/Land/LandServiceConnector.cs | 5 ++++- OpenSim/Services/Interfaces/ILandService.cs | 2 +- 9 files changed, 36 insertions(+), 13 deletions(-) diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index c39fb6f..af5a0ce 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -1171,6 +1171,16 @@ namespace OpenSim.Framework } + public static uint ConvertAccessLevelToMaturity(byte maturity) + { + if (maturity <= 13) + return 0; + else if (maturity <= 21) + return 1; + else + return 2; + } + /// /// Produces an OSDMap from its string representation on a stream /// @@ -1486,4 +1496,4 @@ namespace OpenSim.Framework } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index d2d1e8f..af2dd85 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -2675,7 +2675,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Bit 0: Mature, bit 7: on sale, other bits: no idea reply.Data.Flags = (byte)( - ((land.Flags & (uint)ParcelFlags.MaturePublish) != 0 ? (1 << 0) : 0) + + (info.AccessLevel > 13 ? (1 << 0) : 0) + ((land.Flags & (uint)ParcelFlags.ForSale) != 0 ? (1 << 7) : 0)); Vector3 pos = land.UserLocation; @@ -2683,8 +2683,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP { pos = (land.AABBMax + land.AABBMin) * 0.5f; } - reply.Data.GlobalX = info.RegionLocX * Constants.RegionSize + x; - reply.Data.GlobalY = info.RegionLocY * Constants.RegionSize + y; + reply.Data.GlobalX = info.RegionLocX + x; + reply.Data.GlobalY = info.RegionLocY + y; reply.Data.GlobalZ = pos.Z; reply.Data.SimName = Utils.StringToBytes(info.RegionName); reply.Data.SnapshotID = land.SnapshotID; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs index bce160a..23251c9 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs @@ -121,7 +121,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land #region ILandService - public LandData GetLandData(ulong regionHandle, uint x, uint y) + public LandData GetLandData(ulong regionHandle, uint x, uint y, out byte regionAccess) { m_log.DebugFormat("[LAND IN CONNECTOR]: GetLandData for {0}. Count = {1}", regionHandle, m_Scenes.Count); @@ -130,10 +130,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land if (s.RegionInfo.RegionHandle == regionHandle) { m_log.Debug("[LAND IN CONNECTOR]: Found region to GetLandData from"); + regionAccess = s.RegionInfo.AccessLevel; return s.GetLandData(x, y); } } m_log.DebugFormat("[LAND IN CONNECTOR]: region handle {0} not found", regionHandle); + regionAccess = 42; return null; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs index cb87f6f..e15f624 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs @@ -116,8 +116,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land #region ILandService - public LandData GetLandData(ulong regionHandle, uint x, uint y) + public LandData GetLandData(ulong regionHandle, uint x, uint y, out byte regionAccess) { + regionAccess = 2; m_log.DebugFormat("[LAND CONNECTOR]: request for land data in {0} at {1}, {2}", regionHandle, x, y); @@ -126,6 +127,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land if (s.RegionInfo.RegionHandle == regionHandle) { LandData land = s.GetLandData(x, y); + regionAccess = s.RegionInfo.AccessLevel; return land; } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs index 153c2a5..2386060 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs @@ -108,13 +108,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land #region ILandService - public override LandData GetLandData(ulong regionHandle, uint x, uint y) + public override LandData GetLandData(ulong regionHandle, uint x, uint y, out byte regionAccess) { - LandData land = m_LocalService.GetLandData(regionHandle, x, y); + LandData land = m_LocalService.GetLandData(regionHandle, x, y, out regionAccess); if (land != null) return land; - return base.GetLandData(regionHandle, x, y); + return base.GetLandData(regionHandle, x, y, out regionAccess); } #endregion ILandService diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index cfee1b0..7e29a56 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -51,6 +51,7 @@ namespace OpenSim.Region.CoreModules.World.Land public LandData LandData; public ulong RegionHandle; public uint X, Y; + public byte RegionAccess; } public class LandManagementModule : INonSharedRegionModule @@ -1484,13 +1485,15 @@ namespace OpenSim.Region.CoreModules.World.Land if (extLandData.RegionHandle == m_scene.RegionInfo.RegionHandle) { extLandData.LandData = this.GetLandObject(extLandData.X, extLandData.Y).LandData; + extLandData.RegionAccess = m_scene.RegionInfo.AccessLevel; } else { ILandService landService = m_scene.RequestModuleInterface(); extLandData.LandData = landService.GetLandData(extLandData.RegionHandle, extLandData.X, - extLandData.Y); + extLandData.Y, + out extLandData.RegionAccess); if (extLandData.LandData == null) { // we didn't find the region/land => don't cache @@ -1522,6 +1525,7 @@ namespace OpenSim.Region.CoreModules.World.Land r.RegionName = info.RegionName; r.RegionLocX = (uint)info.RegionLocX; r.RegionLocY = (uint)info.RegionLocY; + r.RegionSettings.Maturity = (int)Util.ConvertAccessLevelToMaturity(data.RegionAccess); remoteClient.SendParcelInfo(r, data.LandData, parcelID, data.X, data.Y); } else diff --git a/OpenSim/Server/Handlers/Land/LandHandlers.cs b/OpenSim/Server/Handlers/Land/LandHandlers.cs index a21f9de..561f285 100644 --- a/OpenSim/Server/Handlers/Land/LandHandlers.cs +++ b/OpenSim/Server/Handlers/Land/LandHandlers.cs @@ -66,7 +66,8 @@ namespace OpenSim.Server.Handlers.Land uint y = Convert.ToUInt32(requestData["y"]); m_log.DebugFormat("[LAND HANDLER]: Got request for land data at {0}, {1} for region {2}", x, y, regionHandle); - LandData landData = m_LocalService.GetLandData(regionHandle, x, y); + byte regionAccess; + LandData landData = m_LocalService.GetLandData(regionHandle, x, y, out regionAccess); Hashtable hash = new Hashtable(); if (landData != null) { @@ -83,6 +84,7 @@ namespace OpenSim.Server.Handlers.Land hash["SalePrice"] = landData.SalePrice.ToString(); hash["SnapshotID"] = landData.SnapshotID.ToString(); hash["UserLocation"] = landData.UserLocation.ToString(); + hash["RegionAccess"] = regionAccess.ToString(); } XmlRpcResponse response = new XmlRpcResponse(); diff --git a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs index 0223a77..c439dc5 100644 --- a/OpenSim/Services/Connectors/Land/LandServiceConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServiceConnector.cs @@ -64,7 +64,7 @@ namespace OpenSim.Services.Connectors m_GridService = gridServices; } - public virtual LandData GetLandData(ulong regionHandle, uint x, uint y) + public virtual LandData GetLandData(ulong regionHandle, uint x, uint y, out byte regionAccess) { LandData landData = null; Hashtable hash = new Hashtable(); @@ -74,6 +74,7 @@ namespace OpenSim.Services.Connectors IList paramList = new ArrayList(); paramList.Add(hash); + regionAccess = 42; // Default to adult. Better safe... try { @@ -109,6 +110,8 @@ namespace OpenSim.Services.Connectors landData.SalePrice = Convert.ToInt32(hash["SalePrice"]); landData.SnapshotID = new UUID((string)hash["SnapshotID"]); landData.UserLocation = Vector3.Parse((string)hash["UserLocation"]); + if (hash["RegionAccess"] != null) + regionAccess = (byte)Convert.ToInt32((string)hash["RegionAccess"]); m_log.DebugFormat("[OGS1 GRID SERVICES] Got land data for parcel {0}", landData.Name); } catch (Exception e) diff --git a/OpenSim/Services/Interfaces/ILandService.cs b/OpenSim/Services/Interfaces/ILandService.cs index e2f1d1d..7a12aff 100644 --- a/OpenSim/Services/Interfaces/ILandService.cs +++ b/OpenSim/Services/Interfaces/ILandService.cs @@ -33,6 +33,6 @@ namespace OpenSim.Services.Interfaces { public interface ILandService { - LandData GetLandData(ulong regionHandle, uint x, uint y); + LandData GetLandData(ulong regionHandle, uint x, uint y, out byte regionAccess); } } -- cgit v1.1 From e69efdd4ce7e989d04adf685d6fa7a704c609377 Mon Sep 17 00:00:00 2001 From: sacha Date: Sat, 7 Aug 2010 13:13:27 +0000 Subject: Clean the loo after use please !!!!! No need to keep useless debug message ! Never heard of wasted cpucycle you darn kid ! --- .../CoreModules/Avatar/InstantMessage/MessageTransferModule.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index d025f0c..e1ee0b1 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -132,7 +132,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { UUID toAgentID = new UUID(im.toAgentID); - m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM from {0} to {1}", im.fromAgentName, toAgentID.ToString()); + //m_log.DebugFormat("[INSTANT MESSAGE]: Attempting delivery of IM from {0} to {1}", im.fromAgentName, toAgentID.ToString()); // Try root avatar only first foreach (Scene scene in m_Scenes) @@ -140,12 +140,12 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if (scene.Entities.ContainsKey(toAgentID) && scene.Entities[toAgentID] is ScenePresence) { - m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); + // m_log.DebugFormat("[INSTANT MESSAGE]: Looking for {0} in {1}", toAgentID.ToString(), scene.RegionInfo.RegionName); // Local message ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; if (!user.IsChildAgent) { - m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); + // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent @@ -167,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage // Local message ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; - m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); + // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering to client"); user.ControllingClient.SendInstantMessage(im); // Message sent -- cgit v1.1 From 047a4764f22340667ea8c3b11a56ed54011aded9 Mon Sep 17 00:00:00 2001 From: sacha Date: Sat, 7 Aug 2010 13:19:53 +0000 Subject: and another one... --- .../Avatar/InstantMessage/InstantMessageModule.cs | 2 +- bin/ICSharpCode.SharpZipLib.xml | 9055 ++++++++++++++++++++ bin/hdfsdll.dll.config | 3 + bin/hdfsdll.so | Bin 0 -> 6557 bytes bin/xmrhelpers.so | Bin 0 -> 18357 bytes 5 files changed, 9059 insertions(+), 1 deletion(-) create mode 100644 bin/ICSharpCode.SharpZipLib.xml create mode 100644 bin/hdfsdll.dll.config create mode 100755 bin/hdfsdll.so create mode 100755 bin/xmrhelpers.so diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs index cbea54c..1603c07 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/InstantMessageModule.cs @@ -169,7 +169,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } catch { - m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp."); + //m_log.Info("[OFFLINE MESSAGING]: No PST timezone found on this machine. Saving with local timestamp."); } // And make it look local again to fool the unix time util diff --git a/bin/ICSharpCode.SharpZipLib.xml b/bin/ICSharpCode.SharpZipLib.xml new file mode 100644 index 0000000..98cb51e --- /dev/null +++ b/bin/ICSharpCode.SharpZipLib.xml @@ -0,0 +1,9055 @@ + + + + ICSharpCode.SharpZipLib + + + + + FastZipEvents supports all events applicable to FastZip operations. + + + + + Delegate to invoke when processing directories. + + + + + Delegate to invoke when processing files. + + + + + Delegate to invoke during processing of files. + + + + + Delegate to invoke when processing for a file has been completed. + + + + + Delegate to invoke when processing directory failures. + + + + + Delegate to invoke when processing file failures. + + + + + Raise the directory failure event. + + The directory causing the failure. + The exception for this event. + A boolean indicating if execution should continue or not. + + + + Raises the file failure delegate. + + The file causing the failure. + The exception for this failure. + A boolean indicating if execution should continue or not. + + + + Fires the Process File delegate. + + The file being processed. + A boolean indicating if execution should continue or not. + + + + Fires the CompletedFile delegate + + The file whose processing has been completed. + A boolean indicating if execution should continue or not. + + + + Fires the process directory delegate. + + The directory being processed. + Flag indicating if the directory has matching files as determined by the current filter. + A of true if the operation should continue; false otherwise. + + + + The minimum timespan between events. + + The minimum period of time between events. + + + + + FastZip provides facilities for creating and extracting zip files. + + + + + Initialise a default instance of . + + + + + Initialise a new instance of + + The events to use during operations. + + + + Create a zip file. + + The name of the zip file to create. + The directory to source files from. + True to recurse directories, false for no recursion. + The file filter to apply. + The directory filter to apply. + + + + Create a zip file/archive. + + The name of the zip file to create. + The directory to obtain files and directories from. + True to recurse directories, false for no recursion. + The file filter to apply. + + + + Create a zip archive sending output to the passed. + + The stream to write archive data to. + The directory to source files from. + True to recurse directories, false for no recursion. + The file filter to apply. + The directory filter to apply. + + + + Extract the contents of a zip file. + + The zip file to extract from. + The directory to save extracted information in. + A filter to apply to files. + + + + Extract the contents of a zip file. + + The zip file to extract from. + The directory to save extracted information in. + The style of overwriting to apply. + A delegate to invoke when confirming overwriting. + A filter to apply to files. + A filter to apply to directories. + Flag indicating wether to restore the date and time for extracted files. + + + + Get/set a value indicating wether empty directories should be created. + + + + + Get / set the password value. + + + + + Get or set the active when creating Zip files. + + + + + + Get or set the active when creating Zip files. + + + + + Get/set a value indicating wether file dates and times should + be restored when extracting files from an archive. + + The default value is false. + + + + Get/set a value indicating wether file attributes should + be restored during extract operations + + + + + Defines the desired handling when overwriting files during extraction. + + + + + Prompt the user to confirm overwriting + + + + + Never overwrite files. + + + + + Always overwrite files. + + + + + Delegate called when confirming overwriting of files. + + + + + NameFilter is a string matching class which allows for both positive and negative + matching. + A filter is a sequence of independant regular expressions separated by semi-colons ';' + Each expression can be prefixed by a plus '+' sign or a minus '-' sign to denote the expression + is intended to include or exclude names. If neither a plus or minus sign is found include is the default + A given name is tested for inclusion before checking exclusions. Only names matching an include spec + and not matching an exclude spec are deemed to match the filter. + An empty filter matches any name. + + The following expression includes all name ending in '.dat' with the exception of 'dummy.dat' + "+\.dat$;-^dummy\.dat$" + + + + + Scanning filters support filtering of names. + + + + + Test a name to see if it 'matches' the filter. + + The name to test. + Returns true if the name matches the filter, false if it does not match. + + + + Construct an instance based on the filter expression passed + + The filter expression. + + + + Test a string to see if it is a valid regular expression. + + The expression to test. + True if expression is a valid false otherwise. + + + + Test an expression to see if it is valid as a filter. + + The filter expression to test. + True if the expression is valid, false otherwise. + + + + Convert this filter to its string equivalent. + + The string equivalent for this filter. + + + + Test a value to see if it is included by the filter. + + The value to test. + True if the value is included, false otherwise. + + + + Test a value to see if it is excluded by the filter. + + The value to test. + True if the value is excluded, false otherwise. + + + + Test a value to see if it matches the filter. + + The value to test. + True if the value matches, false otherwise. + + + + Compile this filter. + + + + + Huffman tree used for inflation + + + + + Literal length tree + + + + + Distance tree + + + + + Constructs a Huffman tree from the array of code lengths. + + + the array of code lengths + + + + + Reads the next symbol from input. The symbol is encoded using the + huffman tree. + + + input the input source. + + + the next symbol, or -1 if not enough input is available. + + + + + This class is general purpose class for writing data to a buffer. + + It allows you to write bits as well as bytes + Based on DeflaterPending.java + + author of the original java version : Jochen Hoenicke + + + + + Internal work buffer + + + + + construct instance using default buffer size of 4096 + + + + + construct instance using specified buffer size + + + size to use for internal buffer + + + + + Clear internal state/buffers + + + + + Write a byte to buffer + + + The value to write + + + + + Write a short value to buffer LSB first + + + The value to write. + + + + + write an integer LSB first + + The value to write. + + + + Write a block of data to buffer + + data to write + offset of first byte to write + number of bytes to write + + + + Align internal buffer on a byte boundary + + + + + Write bits to internal buffer + + source of bits + number of bits to write + + + + Write a short value to internal buffer most significant byte first + + value to write + + + + Flushes the pending buffer into the given output array. If the + output array is to small, only a partial flush is done. + + The output array. + The offset into output array. + The maximum number of bytes to store. + The number of bytes flushed. + + + + Convert internal buffer to byte array. + Buffer is empty on completion + + + The internal buffer contents converted to a byte array. + + + + + The number of bits written to the buffer + + + + + Indicates if buffer has been flushed + + + + + Used to advise clients of 'events' while processing archives + + + + + The TarArchive class implements the concept of a + 'Tape Archive'. A tar archive is a series of entries, each of + which represents a file system object. Each entry in + the archive consists of a header block followed by 0 or more data blocks. + Directory entries consist only of the header block, and are followed by entries + for the directory's contents. File entries consist of a + header followed by the number of blocks needed to + contain the file's contents. All entries are written on + block boundaries. Blocks are 512 bytes long. + + TarArchives are instantiated in either read or write mode, + based upon whether they are instantiated with an InputStream + or an OutputStream. Once instantiated TarArchives read/write + mode can not be changed. + + There is currently no support for random access to tar archives. + However, it seems that subclassing TarArchive, and using the + TarBuffer.CurrentRecord and TarBuffer.CurrentBlock + properties, this would be rather trivial. + + + + + Raises the ProgressMessage event + + The TarEntry for this event + message for this event. Null is no message + + + + Constructor for a default . + + + + + Initalise a TarArchive for input. + + The to use for input. + + + + Initialise a TarArchive for output. + + The to use for output. + + + + The InputStream based constructors create a TarArchive for the + purposes of extracting or listing a tar archive. Thus, use + these constructors when you wish to extract files from or list + the contents of an existing tar archive. + + The stream to retrieve archive data from. + Returns a new suitable for reading from. + + + + Create TarArchive for reading setting block factor + + Stream for tar archive contents + The blocking factor to apply + Returns a suitable for reading. + + + + Create a TarArchive for writing to, using the default blocking factor + + The to write to + Returns a suitable for writing. + + + + Create a TarArchive for writing to + + The stream to write to + The blocking factor to use for buffering. + Returns a suitable for writing. + + + + Set the flag that determines whether existing files are + kept, or overwritten during extraction. + + + If true, do not overwrite existing files. + + + + + Set the ascii file translation flag. + + + If true, translate ascii text files. + + + + + Set user and group information that will be used to fill in the + tar archive's entry headers. This information based on that available + for the linux operating system, which is not always available on other + operating systems. TarArchive allows the programmer to specify values + to be used in their place. + is set to true by this call. + + + The user id to use in the headers. + + + The user name to use in the headers. + + + The group id to use in the headers. + + + The group name to use in the headers. + + + + + Close the archive. + + + + + Perform the "list" command for the archive contents. + + NOTE That this method uses the progress event to actually list + the contents. If the progress display event is not set, nothing will be listed! + + + + + Perform the "extract" command and extract the contents of the archive. + + + The destination directory into which to extract. + + + + + Extract an entry from the archive. This method assumes that the + tarIn stream has been properly set with a call to GetNextEntry(). + + + The destination directory into which to extract. + + + The TarEntry returned by tarIn.GetNextEntry(). + + + + + Write an entry to the archive. This method will call the putNextEntry + and then write the contents of the entry, and finally call closeEntry() + for entries that are files. For directories, it will call putNextEntry(), + and then, if the recurse flag is true, process each entry that is a + child of the directory. + + + The TarEntry representing the entry to write to the archive. + + + If true, process the children of directory entries. + + + + + Write an entry to the archive. This method will call the putNextEntry + and then write the contents of the entry, and finally call closeEntry() + for entries that are files. For directories, it will call putNextEntry(), + and then, if the recurse flag is true, process each entry that is a + child of the directory. + + + The TarEntry representing the entry to write to the archive. + + + If true, process the children of directory entries. + + + + + Releases the unmanaged resources used by the FileStream and optionally releases the managed resources. + + true to release both managed and unmanaged resources; + false to release only unmanaged resources. + + + + Closes the archive and releases any associated resources. + + + + + Ensures that resources are freed and other cleanup operations are performed + when the garbage collector reclaims the . + + + + + Client hook allowing detailed information to be reported during processing + + + + + Get/set the ascii file translation flag. If ascii file translation + is true, then the file is checked to see if it a binary file or not. + If the flag is true and the test indicates it is ascii text + file, it will be translated. The translation converts the local + operating system's concept of line ends into the UNIX line end, + '\n', which is the defacto standard for a TAR archive. This makes + text files compatible with UNIX. + + + + + PathPrefix is added to entry names as they are written if the value is not null. + A slash character is appended after PathPrefix + + + + + RootPath is removed from entry names if it is found at the + beginning of the name. + + + + + Get or set a value indicating if overrides defined by SetUserInfo should be applied. + + If overrides are not applied then the values as set in each header will be used. + + + + Get the archive user id. + See ApplyUserInfoOverrides for detail + on how to allow setting values on a per entry basis. + + + The current user id. + + + + + Get the archive user name. + See ApplyUserInfoOverrides for detail + on how to allow setting values on a per entry basis. + + + The current user name. + + + + + Get the archive group id. + See ApplyUserInfoOverrides for detail + on how to allow setting values on a per entry basis. + + + The current group id. + + + + + Get the archive group name. + See ApplyUserInfoOverrides for detail + on how to allow setting values on a per entry basis. + + + The current group name. + + + + + Get the archive's record size. Tar archives are composed of + a series of RECORDS each containing a number of BLOCKS. + This allowed tar archives to match the IO characteristics of + the physical device being used. Archives are expected + to be properly "blocked". + + + The record size this archive is using. + + + + + An output stream that compresses into the BZip2 format + including file header chars into another stream. + + + + + Construct a default output stream with maximum block size + + The stream to write BZip data onto. + + + + Initialise a new instance of the + for the specified stream, using the given blocksize. + + The stream to write compressed data to. + The block size to use. + + Valid block sizes are in the range 1..9, with 1 giving + the lowest compression and 9 the highest. + + + + + Ensures that resources are freed and other cleanup operations + are performed when the garbage collector reclaims the BZip2OutputStream. + + + + + Sets the current position of this stream to the given value. + + The point relative to the offset from which to being seeking. + The reference point from which to begin seeking. + The new position in the stream. + + + + Sets the length of this stream to the given value. + + The new stream length. + + + + Read a byte from the stream advancing the position. + + The byte read cast to an int; -1 if end of stream. + + + + Read a block of bytes + + The buffer to read into. + The offset in the buffer to start storing data at. + The maximum number of bytes to read. + The total number of bytes read. This might be less than the number of bytes + requested if that number of bytes are not currently available, or zero + if the end of the stream is reached. + + + + Write a block of bytes to the stream + + The buffer containing data to write. + The offset of the first byte to write. + The number of bytes to write. + + + + Write a byte to the stream. + + The byte to write to the stream. + + + + End the current block and end compression. + Close the stream and free any resources + + + + + Get the number of bytes written to output. + + + + + Releases the unmanaged resources used by the and optionally releases the managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Flush output buffers + + + + + Get/set flag indicating ownership of underlying stream. + When the flag is true will close the underlying stream also. + + + + + Gets a value indicating whether the current stream supports reading + + + + + Gets a value indicating whether the current stream supports seeking + + + + + Gets a value indicating whether the current stream supports writing + + + + + Gets the length in bytes of the stream + + + + + Gets or sets the current position of this stream. + + + + + Get the number of bytes written to the output. + + + + + Represents exception conditions specific to Zip archive handling + + + + + SharpZipBaseException is the base exception class for the SharpZipLibrary. + All library exceptions are derived from this. + + NOTE: Not all exceptions thrown will be derived from this class. + A variety of other exceptions are possible for example + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initializes a new instance of the SharpZipBaseException class. + + + + + Initializes a new instance of the SharpZipBaseException class with a specified error message. + + A message describing the exception. + + + + Initializes a new instance of the SharpZipBaseException class with a specified + error message and a reference to the inner exception that is the cause of this exception. + + A message describing the exception. + The inner exception + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initializes a new instance of the ZipException class. + + + + + Initializes a new instance of the ZipException class with a specified error message. + + The error message that explains the reason for the exception. + + + + Initialise a new instance of ZipException. + + A message describing the error. + The exception that is the cause of the current exception. + + + + A helper class to simplify compressing and decompressing streams. + + + + + Decompress input writing + decompressed data to the output stream + + The stream containing data to decompress. + The stream to write decompressed data to. + Both streams are closed on completion + + + + Compress input stream sending + result to output stream + + The stream to compress. + The stream to write compressed data to. + The block size to use. + Both streams are closed on completion + + + + Initialise a default instance of this class. + + + + + Determines how entries are tested to see if they should use Zip64 extensions or not. + + + + + Zip64 will not be forced on entries during processing. + + An entry can have this overridden if required + + + + Zip64 should always be used. + + + + + #ZipLib will determine use based on entry values when added to archive. + + + + + The kind of compression used for an entry in an archive + + + + + A direct copy of the file contents is held in the archive + + + + + Common Zip compression method using a sliding dictionary + of up to 32KB and secondary compression from Huffman/Shannon-Fano trees + + + + + An extension to deflate with a 64KB window. Not supported by #Zip currently + + + + + Not supported by #Zip currently + + + + + WinZip special for AES encryption, Not supported by #Zip + + + + + Identifies the encryption algorithm used for an entry + + + + + No encryption has been used. + + + + + Encrypted using PKZIP 2.0 or 'classic' encryption. + + + + + DES encryption has been used. + + + + + RCS encryption has been used for encryption. + + + + + Triple DES encryption with 168 bit keys has been used for this entry. + + + + + Triple DES with 112 bit keys has been used for this entry. + + + + + AES 128 has been used for encryption. + + + + + AES 192 has been used for encryption. + + + + + AES 256 has been used for encryption. + + + + + RC2 corrected has been used for encryption. + + + + + Blowfish has been used for encryption. + + + + + Twofish has been used for encryption. + + + + + RCS has been used for encryption. + + + + + An unknown algorithm has been used for encryption. + + + + + Defines the contents of the general bit flags field for an archive entry. + + + + + Bit 0 if set indicates that the file is encrypted + + + + + Bits 1 and 2 - Two bits defining the compression method (only for Method 6 Imploding and 8,9 Deflating) + + + + + Bit 3 if set indicates a trailing data desciptor is appended to the entry data + + + + + Bit 4 is reserved for use with method 8 for enhanced deflation + + + + + Bit 5 if set indicates the file contains Pkzip compressed patched data. + Requires version 2.7 or greater. + + + + + Bit 6 if set strong encryption has been used for this entry. + + + + + Bit 7 is currently unused + + + + + Bit 8 is currently unused + + + + + Bit 9 is currently unused + + + + + Bit 10 is currently unused + + + + + Bit 11 if set indicates the filename and + comment fields for this file must be encoded using UTF-8. + + + + + Bit 12 is documented as being reserved by PKware for enhanced compression. + + + + + Bit 13 if set indicates that values in the local header are masked to hide + their actual values, and the central directory is encrypted. + + + Used when encrypting the central directory contents. + + + + + Bit 14 is documented as being reserved for use by PKware + + + + + Bit 15 is documented as being reserved for use by PKware + + + + + This class contains constants used for Zip format files + + + + + The version made by field for entries in the central header when created by this library + + + This is also the Zip version for the library when comparing against the version required to extract + for an entry. See . + + + + + The version made by field for entries in the central header when created by this library + + + This is also the Zip version for the library when comparing against the version required to extract + for an entry. See ZipInputStream.CanDecompressEntry. + + + + + The minimum version required to support strong encryption + + + + + The minimum version required to support strong encryption + + + + + The version required for Zip64 extensions + + + + + Size of local entry header (excluding variable length fields at end) + + + + + Size of local entry header (excluding variable length fields at end) + + + + + Size of Zip64 data descriptor + + + + + Size of data descriptor + + + + + Size of data descriptor + + + + + Size of central header entry (excluding variable fields) + + + + + Size of central header entry + + + + + Size of end of central record (excluding variable fields) + + + + + Size of end of central record (excluding variable fields) + + + + + Size of 'classic' cryptographic header stored before any entry data + + + + + Size of cryptographic header stored before entry data + + + + + Signature for local entry header + + + + + Signature for local entry header + + + + + Signature for spanning entry + + + + + Signature for spanning entry + + + + + Signature for temporary spanning entry + + + + + Signature for temporary spanning entry + + + + + Signature for data descriptor + + + This is only used where the length, Crc, or compressed size isnt known when the + entry is created and the output stream doesnt support seeking. + The local entry cannot be 'patched' with the correct values in this case + so the values are recorded after the data prefixed by this header, as well as in the central directory. + + + + + Signature for data descriptor + + + This is only used where the length, Crc, or compressed size isnt known when the + entry is created and the output stream doesnt support seeking. + The local entry cannot be 'patched' with the correct values in this case + so the values are recorded after the data prefixed by this header, as well as in the central directory. + + + + + Signature for central header + + + + + Signature for central header + + + + + Signature for Zip64 central file header + + + + + Signature for Zip64 central file header + + + + + Signature for Zip64 central directory locator + + + + + Signature for archive extra data signature (were headers are encrypted). + + + + + Central header digitial signature + + + + + Central header digitial signature + + + + + End of central directory record signature + + + + + End of central directory record signature + + + + + Convert a portion of a byte array to a string. + + + Data to convert to string + + + Number of bytes to convert starting from index 0 + + + data[0]..data[length - 1] converted to a string + + + + + Convert a byte array to string + + + Byte array to convert + + + dataconverted to a string + + + + + Convert a byte array to string + + The applicable general purpose bits flags + + Byte array to convert + + The number of bytes to convert. + + dataconverted to a string + + + + + Convert a byte array to string + + + Byte array to convert + + The applicable general purpose bits flags + + dataconverted to a string + + + + + Convert a string to a byte array + + + String to convert to an array + + Converted array + + + + Convert a string to a byte array + + The applicable general purpose bits flags + + String to convert to an array + + Converted array + + + + Initialise default instance of ZipConstants + + + Private to prevent instances being created. + + + + + Default encoding used for string conversion. 0 gives the default system OEM code page. + Dont use unicode encodings if you want to be Zip compatible! + Using the default code page isnt the full solution neccessarily + there are many variable factors, codepage 850 is often a good choice for + European users, however be careful about compatability. + + + + + This is a DeflaterOutputStream that writes the files into a zip + archive one after another. It has a special method to start a new + zip entry. The zip entries contains information about the file name + size, compressed size, CRC, etc. + + It includes support for Stored and Deflated entries. + This class is not thread safe. +
+
Author of the original java version : Jochen Hoenicke +
+ This sample shows how to create a zip file + + using System; + using System.IO; + + using ICSharpCode.SharpZipLib.Core; + using ICSharpCode.SharpZipLib.Zip; + + class MainClass + { + public static void Main(string[] args) + { + string[] filenames = Directory.GetFiles(args[0]); + byte[] buffer = new byte[4096]; + + using ( ZipOutputStream s = new ZipOutputStream(File.Create(args[1])) ) { + + s.SetLevel(9); // 0 - store only to 9 - means best compression + + foreach (string file in filenames) { + ZipEntry entry = new ZipEntry(file); + s.PutNextEntry(entry); + + using (FileStream fs = File.OpenRead(file)) { + StreamUtils.Copy(fs, s, buffer); + } + } + } + } + } + + +
+ + + A special stream deflating or compressing the bytes that are + written to it. It uses a Deflater to perform actual deflating.
+ Authors of the original java version : Tom Tromey, Jochen Hoenicke +
+
+ + + Creates a new DeflaterOutputStream with a default Deflater and default buffer size. + + + the output stream where deflated output should be written. + + + + + Creates a new DeflaterOutputStream with the given Deflater and + default buffer size. + + + the output stream where deflated output should be written. + + + the underlying deflater. + + + + + Creates a new DeflaterOutputStream with the given Deflater and + buffer size. + + + The output stream where deflated output is written. + + + The underlying deflater to use + + + The buffer size to use when deflating + + + bufsize is less than or equal to zero. + + + baseOutputStream does not support writing + + + deflater instance is null + + + + + Finishes the stream by calling finish() on the deflater. + + + Not all input is deflated + + + + + Encrypt a block of data + + + Data to encrypt. NOTE the original contents of the buffer are lost + + + Offset of first byte in buffer to encrypt + + + Number of bytes in buffer to encrypt + + + + + Initializes encryption keys based on given password + + The password. + + + + Deflates everything in the input buffers. This will call + def.deflate() until all bytes from the input buffers + are processed. + + + + + Sets the current position of this stream to the given value. Not supported by this class! + + The offset relative to the to seek. + The to seek from. + The new position in the stream. + Any access + + + + Sets the length of this stream to the given value. Not supported by this class! + + The new stream length. + Any access + + + + Read a byte from stream advancing position by one + + The byte read cast to an int. THe value is -1 if at the end of the stream. + Any access + + + + Read a block of bytes from stream + + The buffer to store read data in. + The offset to start storing at. + The maximum number of bytes to read. + The actual number of bytes read. Zero if end of stream is detected. + Any access + + + + Asynchronous reads are not supported a NotSupportedException is always thrown + + The buffer to read into. + The offset to start storing data at. + The number of bytes to read + The async callback to use. + The state to use. + Returns an + Any access + + + + Asynchronous writes arent supported, a NotSupportedException is always thrown + + The buffer to write. + The offset to begin writing at. + The number of bytes to write. + The to use. + The state object. + Returns an IAsyncResult. + Any access + + + + Flushes the stream by calling Flush on the deflater and then + on the underlying stream. This ensures that all bytes are flushed. + + + + + Calls and closes the underlying + stream when is true. + + + + + Writes a single byte to the compressed output stream. + + + The byte value. + + + + + Writes bytes from an array to the compressed stream. + + + The byte array + + + The offset into the byte array where to start. + + + The number of bytes to write. + + + + + This buffer is used temporarily to retrieve the bytes from the + deflater and write them to the underlying output stream. + + + + + The deflater which is used to deflate the stream. + + + + + Base stream the deflater depends on. + + + + + Get/set flag indicating ownership of the underlying stream. + When the flag is true will close the underlying stream also. + + + + + Allows client to determine if an entry can be patched after its added + + + + + Get/set the password used for encryption. + + When set to null or if the password is empty no encryption is performed + + + + Gets value indicating stream can be read from + + + + + Gets a value indicating if seeking is supported for this stream + This property always returns false + + + + + Get value indicating if this stream supports writing + + + + + Get current length of stream + + + + + Gets the current position within the stream. + + Any attempt to set position + + + + Creates a new Zip output stream, writing a zip archive. + + + The output stream to which the archive contents are written. + + + + + Set the zip file comment. + + + The comment text for the entire archive. + + + The converted comment is longer than 0xffff bytes. + + + + + Sets the compression level. The new level will be activated + immediately. + + The new compression level (1 to 9). + + Level specified is not supported. + + + + + + Get the current deflater compression level + + The current compression level + + + + Write an unsigned short in little endian byte order. + + + + + Write an int in little endian byte order. + + + + + Write an int in little endian byte order. + + + + + Starts a new Zip entry. It automatically closes the previous + entry if present. + All entry elements bar name are optional, but must be correct if present. + If the compression method is stored and the output is not patchable + the compression for that entry is automatically changed to deflate level 0 + + + the entry. + + + if entry passed is null. + + + if an I/O error occured. + + + if stream was finished + + + Too many entries in the Zip file
+ Entry name is too long
+ Finish has already been called
+
+
+ + + Closes the current entry, updating header and footer information as required + + + An I/O error occurs. + + + No entry is active. + + + + + Writes the given buffer to the current entry. + + The buffer containing data to write. + The offset of the first byte to write. + The number of bytes to write. + Archive size is invalid + No entry is active. + + + + Finishes the stream. This will write the central directory at the + end of the zip file and flush the stream. + + + This is automatically called when the stream is closed. + + + An I/O error occurs. + + + Comment exceeds the maximum length
+ Entry name exceeds the maximum length +
+
+ + + The entries for the archive. + + + + + Used to track the crc of data added to entries. + + + + + The current entry being added. + + + + + Used to track the size of data for an entry during writing. + + + + + Offset to be recorded for each entry in the central header. + + + + + Comment for the entire archive recorded in central header. + + + + + Flag indicating that header patching is required for the current entry. + + + + + Position to patch crc + + + + + Position to patch size. + + + + + Gets a flag value of true if the central header has been added for this archive; false if it has not been added. + + No further entries can be added once this has been done. + + + + Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + + Older archivers may not understand Zip64 extensions. + If backwards compatability is an issue be careful when adding entries to an archive. + Setting this property to off is workable but less desirable as in those circumstances adding a file + larger then 4GB will fail. + + + + INameTransform defines how file system names are transformed for use with archives. + + + + + Given a file name determine the transformed value. + + The name to transform. + The transformed file name. + + + + Given a directory name determine the transformed value. + + The name to transform. + The transformed directory name + + + + This class contains constants used for deflation. + + + + + Set to true to enable debugging + + + + + Written to Zip file to identify a stored block + + + + + Identifies static tree in Zip file + + + + + Identifies dynamic tree in Zip file + + + + + Header flag indicating a preset dictionary for deflation + + + + + Sets internal buffer sizes for Huffman encoding + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + Internal compression engine constant + + + + + This class stores the pending output of the Deflater. + + author of the original java version : Jochen Hoenicke + + + + + Construct instance with default buffer size + + + + + PathFilter filters directories and files using a form of regular expressions + by full path name. + See NameFilter for more detail on filtering. + + + + + Initialise a new instance of . + + The filter expression to apply. + + + + Test a name to see if it matches the filter. + + The name to test. + True if the name matches, false otherwise. + + + + ExtendedPathFilter filters based on name, file size, and the last write time of the file. + + Provides an example of how to customise filtering. + + + + Initialise a new instance of ExtendedPathFilter. + + The filter to apply. + The minimum file size to include. + The maximum file size to include. + + + + Initialise a new instance of ExtendedPathFilter. + + The filter to apply. + The minimum to include. + The maximum to include. + + + + Initialise a new instance of ExtendedPathFilter. + + The filter to apply. + The minimum file size to include. + The maximum file size to include. + The minimum to include. + The maximum to include. + + + + Test a filename to see if it matches the filter. + + The filename to test. + True if the filter matches, false otherwise. + + + + Get/set the minimum size for a file that will match this filter. + + + + + Get/set the maximum size for a file that will match this filter. + + + + + Get/set the minimum value that will match for this filter. + + Files with a LastWrite time less than this value are excluded by the filter. + + + + Get/set the maximum value that will match for this filter. + + Files with a LastWrite time greater than this value are excluded by the filter. + + + + NameAndSizeFilter filters based on name and file size. + + A sample showing how filters might be extended. + + + + Initialise a new instance of NameAndSizeFilter. + + The filter to apply. + The minimum file size to include. + The maximum file size to include. + + + + Test a filename to see if it matches the filter. + + The filename to test. + True if the filter matches, false otherwise. + + + + Get/set the minimum size for a file that will match this filter. + + + + + Get/set the maximum size for a file that will match this filter. + + + + + BZip2Exception represents exceptions specific to Bzip2 algorithm + + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initialise a new instance of BZip2Exception. + + + + + Initialise a new instance of BZip2Exception with its message set to message. + + The message describing the error. + + + + Initialise an instance of BZip2Exception + + A message describing the error. + The exception that is the cause of the current exception. + + + + GZipException represents a Gzip specific exception + + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initialise a new instance of GZipException + + + + + Initialise a new instance of GZipException with its message string. + + A that describes the error. + + + + Initialise a new instance of . + + A that describes the error. + The that caused this exception. + + + + Contains the output from the Inflation process. + We need to have a window so that we can refer backwards into the output stream + to repeat stuff.
+ Author of the original java version : John Leuner +
+
+ + + Write a byte to this output window + + value to write + + if window is full + + + + + Append a byte pattern already in the window itself + + length of pattern to copy + distance from end of window pattern occurs + + If the repeated data overflows the window + + + + + Copy from input manipulator to internal window + + source of data + length of data to copy + the number of bytes copied + + + + Copy dictionary to window + + source dictionary + offset of start in source dictionary + length of dictionary + + If window isnt empty + + + + + Get remaining unfilled space in window + + Number of bytes left in window + + + + Get bytes available for output in window + + Number of bytes filled + + + + Copy contents of window to output + + buffer to copy to + offset to start at + number of bytes to count + The number of bytes copied + + If a window underflow occurs + + + + + Reset by clearing window so GetAvailable returns 0 + + + + + Defines internal values for both compression and decompression + + + + + When multiplied by compression parameter (1-9) gives the block size for compression + 9 gives the best compresssion but uses the most memory. + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Backend constant + + + + + Random numbers used to randomise repetitive blocks + + + + + This filter stream is used to compress a stream into a "GZIP" stream. + The "GZIP" format is described in RFC 1952. + + author of the original java version : John Leuner + + This sample shows how to gzip a file + + using System; + using System.IO; + + using ICSharpCode.SharpZipLib.GZip; + using ICSharpCode.SharpZipLib.Core; + + class MainClass + { + public static void Main(string[] args) + { + using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz"))) + using (FileStream fs = File.OpenRead(args[0])) { + byte[] writeData = new byte[4096]; + Streamutils.Copy(s, fs, writeData); + } + } + } + } + + + + + + CRC-32 value for uncompressed data + + + + + Creates a GzipOutputStream with the default buffer size + + + The stream to read data (to be compressed) from + + + + + Creates a GZipOutputStream with the specified buffer size + + + The stream to read data (to be compressed) from + + + Size of the buffer to use + + + + + Sets the active compression level (1-9). The new level will be activated + immediately. + + The compression level to set. + + Level specified is not supported. + + + + + + Get the current compression level. + + The current compression level. + + + + Write given buffer to output updating crc + + Buffer to write + Offset of first byte in buf to write + Number of bytes to write + + + + Writes remaining compressed output data to the output stream + and closes it. + + + + + Finish compression and write any footer information required to stream + + + + + Arguments used with KeysRequiredEvent + + + + + Initialise a new instance of + + The name of the file for which keys are required. + + + + Initialise a new instance of + + The name of the file for which keys are required. + The current key value. + + + + Get the name of the file for which keys are required. + + + + + Get/set the key value + + + + + The strategy to apply to testing. + + + + + Find the first error only. + + + + + Find all possible errors. + + + + + The operation in progress reported by a during testing. + + TestArchive + + + + Setting up testing. + + + + + Testing an individual entries header + + + + + Testing an individual entries data + + + + + Testing an individual entry has completed. + + + + + Running miscellaneous tests + + + + + Testing is complete + + + + + Status returned returned by during testing. + + TestArchive + + + + Initialise a new instance of + + The this status applies to. + + + + Get the current in progress. + + + + + Get the this status is applicable to. + + + + + Get the current/last entry tested. + + + + + Get the number of errors detected so far. + + + + + Get the number of bytes tested so far for the current entry. + + + + + Get a value indicating wether the last entry test was valid. + + + + + Delegate invoked during testing if supplied indicating current progress and status. + + If the message is non-null an error has occured. If the message is null + the operation as found in status has started. + + + + The possible ways of applying updates to an archive. + + + + + Perform all updates on temporary files ensuring that the original file is saved. + + + + + Update the archive directly, which is faster but less safe. + + + + + This class represents a Zip archive. You can ask for the contained + entries, or get an input stream for a file entry. The entry is + automatically decompressed. + + You can also update the archive adding or deleting entries. + + This class is thread safe for input: You can open input streams for arbitrary + entries in different threads. +
+
Author of the original java version : Jochen Hoenicke +
+ + + using System; + using System.Text; + using System.Collections; + using System.IO; + + using ICSharpCode.SharpZipLib.Zip; + + class MainClass + { + static public void Main(string[] args) + { + using (ZipFile zFile = new ZipFile(args[0])) { + Console.WriteLine("Listing of : " + zFile.Name); + Console.WriteLine(""); + Console.WriteLine("Raw Size Size Date Time Name"); + Console.WriteLine("-------- -------- -------- ------ ---------"); + foreach (ZipEntry e in zFile) { + if ( e.IsFile ) { + DateTime d = e.DateTime; + Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize, + d.ToString("dd-MM-yy"), d.ToString("HH:mm"), + e.Name); + } + } + } + } + } + + +
+ + + Event handler for handling encryption keys. + + + + + Handles getting of encryption keys when required. + + The file for which encryption keys are required. + + + + Opens a Zip file with the given name for reading. + + The name of the file to open. + + An i/o error occurs + + + The file doesn't contain a valid zip archive. + + + + + Opens a Zip file reading the given . + + The to read archive data from. + + An i/o error occurs. + + + The file doesn't contain a valid zip archive. + + + + + Opens a Zip file reading the given . + + The to read archive data from. + + An i/o error occurs + + + The file doesn't contain a valid zip archive.
+ The stream provided cannot seek +
+
+ + + Initialises a default instance with no entries and no file storage. + + + + + Finalize this instance. + + + + + Closes the ZipFile. If the stream is owned then this also closes the underlying input stream. + Once closed, no further instance methods should be called. + + + An i/o error occurs. + + + + + Create a new whose data will be stored in a file. + + The name of the archive to create. + Returns the newly created + + + + Create a new whose data will be stored on a stream. + + The stream providing data storage. + Returns the newly created + + + + Gets an enumerator for the Zip entries in this Zip file. + + Returns an for this archive. + + The Zip file has been closed. + + + + + Return the index of the entry with a matching name + + Entry name to find + If true the comparison is case insensitive + The index position of the matching entry or -1 if not found + + The Zip file has been closed. + + + + + Searches for a zip entry in this archive with the given name. + String comparisons are case insensitive + + + The name to find. May contain directory components separated by slashes ('/'). + + + A clone of the zip entry, or null if no entry with that name exists. + + + The Zip file has been closed. + + + + + Gets an input stream for reading the given zip entry data in an uncompressed form. + Normally the should be an entry returned by GetEntry(). + + The to obtain a data for + An input containing data for this + + The ZipFile has already been closed + + + The compression method for the entry is unknown + + + The entry is not found in the ZipFile + + + + + Creates an input stream reading a zip entry + + The index of the entry to obtain an input stream for. + + An input containing data for this + + + The ZipFile has already been closed + + + The compression method for the entry is unknown + + + The entry is not found in the ZipFile + + + + + Test an archive for integrity/validity + + Perform low level data Crc check + true if all tests pass, false otherwise + Testing will terminate on the first error found. + + + + Test an archive for integrity/validity + + Perform low level data Crc check + The to apply. + The handler to call during testing. + true if all tests pass, false otherwise + + + + Test a local header against that provided from the central directory + + + The entry to test against + + The type of tests to carry out. + The offset of the entries data in the file + + + + Begin updating this archive. + + The archive storage for use during the update. + The data source to utilise during updating. + + + + Begin updating to this archive. + + The storage to use during the update. + + + + Begin updating this archive. + + + + + + + + Commit current updates, updating this archive. + + + + + + + Abort updating leaving the archive unchanged. + + + + + + + Set the file comment to be recorded when the current update is commited. + + The comment to record. + + + + Add a new entry to the archive. + + The name of the file to add. + The compression method to use. + Ensure Unicode text is used for name and comment for this entry. + + + + Add a new entry to the archive. + + The name of the file to add. + The compression method to use. + + + + Add a file to the archive. + + The name of the file to add. + + + + Add a file entry with data. + + The source of the data for this entry. + The name to give to the entry. + + + + Add a file entry with data. + + The source of the data for this entry. + The name to give to the entry. + The compression method to use. + + + + Add a file entry with data. + + The source of the data for this entry. + The name to give to the entry. + The compression method to use. + Ensure Unicode text is used for name and comments for this entry. + + + + Add a that contains no data. + + The entry to add. + This can be used to add directories, volume labels, or empty file entries. + + + + Add a directory entry to the archive. + + The directory to add. + + + + Delete an entry by name + + The filename to delete + True if the entry was found and deleted; false otherwise. + + + + Delete a from the archive. + + The entry to delete. + + + + Write an unsigned short in little endian byte order. + + + + + Write an int in little endian byte order. + + + + + Write an unsigned int in little endian byte order. + + + + + Write a long in little endian byte order. + + + + + Get a raw memory buffer. + + Returns a raw memory buffer. + + + + Get the size of the source descriptor for a . + + The update to get the size for. + The descriptor size, zero if there isnt one. + + + + Get an output stream for the specified + + The entry to get an output stream for. + The output stream obtained for the entry. + + + + Releases the unmanaged resources used by the this instance and optionally releases the managed resources. + + true to release both managed and unmanaged resources; + false to release only unmanaged resources. + + + + Read an unsigned short in little endian byte order. + + Returns the value read. + + The stream ends prematurely + + + + + Read a uint in little endian byte order. + + Returns the value read. + + An i/o error occurs. + + + The file ends prematurely + + + + + Search for and read the central directory of a zip file filling the entries array. + + + An i/o error occurs. + + + The central directory is malformed or cannot be found + + + + + Locate the data for a given entry. + + + The start offset of the data. + + + The stream ends prematurely + + + The local header signature is invalid, the entry and central header file name lengths are different + or the local and entry compression methods dont match + + + + + Get/set the encryption key value. + + + + + Password to be used for encrypting/decrypting files. + + Set to null if no password is required. + + + + Get a value indicating wether encryption keys are currently available. + + + + + Get/set a flag indicating if the underlying stream is owned by the ZipFile instance. + If the flag is true then the stream will be closed when Close is called. + + + The default value is true in all cases. + + + + + Get a value indicating wether + this archive is embedded in another file or not. + + + + + Get a value indicating that this archive is a new one. + + + + + Gets the comment for the zip file. + + + + + Gets the name of this zip file. + + + + + Gets the number of entries in this zip file. + + + The Zip file has been closed. + + + + + Get the number of entries contained in this . + + + + + Indexer property for ZipEntries + + + + + Get / set the to apply to names when updating. + + + + + Get/set the used to generate values + during updates. + + + + + Get /set the buffer size to be used when updating this zip file. + + + + + Get a value indicating an update has been started. + + + + + Get / set a value indicating how Zip64 Extension usage is determined when adding entries. + + + + + Delegate for handling keys/password setting during compresion/decompression. + + + + + The kind of update to apply. + + + + + Class used to sort updates. + + + + + Compares two objects and returns a value indicating whether one is + less than, equal to or greater than the other. + + First object to compare + Second object to compare. + Compare result. + + + + Represents a pending update to a Zip file. + + + + + Copy an existing entry. + + The existing entry to copy. + + + + Get the for this update. + + This is the source or original entry. + + + + Get the that will be written to the updated/new file. + + + + + Get the command for this update. + + + + + Get the filename if any for this update. Null if none exists. + + + + + Get/set the location of the size patch for this update. + + + + + Get /set the location of the crc patch for this update. + + + + + Represents a string from a which is stored as an array of bytes. + + + + + Initialise a with a string. + + The textual string form. + + + + Initialise a using a string in its binary 'raw' form. + + + + + + Reset the comment to its initial state. + + + + + Implicit conversion of comment to a string. + + The to convert to a string. + The textual equivalent for the input value. + + + + Get a value indicating the original source of data for this instance. + True if the source was a string; false if the source was binary data. + + + + + Get the length of the comment when represented as raw bytes. + + + + + Get the comment in its 'raw' form as plain bytes. + + + + + An enumerator for Zip entries + + + + + An is a stream that you can write uncompressed data + to and flush, but cannot read, seek or do anything else to. + + + + + Close this stream instance. + + + + + Write any buffered data to underlying storage. + + + + + Gets a value indicating whether the current stream supports reading. + + + + + Gets a value indicating whether the current stream supports writing. + + + + + Gets a value indicating whether the current stream supports seeking. + + + + + Get the length in bytes of the stream. + + + + + Gets or sets the position within the current stream. + + + + + A is an + whose data is only a part or subsection of a file. + + + + + This filter stream is used to decompress data compressed using the "deflate" + format. The "deflate" format is described in RFC 1951. + + This stream may form the basis for other decompression filters, such + as the GZipInputStream. + + Author of the original java version : John Leuner. + + + + + Create an InflaterInputStream with the default decompressor + and a default buffer size of 4KB. + + + The InputStream to read bytes from + + + + + Create an InflaterInputStream with the specified decompressor + and a default buffer size of 4KB. + + + The source of input data + + + The decompressor used to decompress data read from baseInputStream + + + + + Create an InflaterInputStream with the specified decompressor + and the specified buffer size. + + + The InputStream to read bytes from + + + The decompressor to use + + + Size of the buffer to use + + + + + Skip specified number of bytes of uncompressed data + + + Number of bytes to skip + + + The number of bytes skipped, zero if the end of + stream has been reached + + + Number of bytes to skip is less than zero + + + + + Clear any cryptographic state. + + + + + Fills the buffer with more data to decompress. + + + Stream ends early + + + + + Flushes the baseInputStream + + + + + Sets the position within the current stream + Always throws a NotSupportedException + + The relative offset to seek to. + The defining where to seek from. + The new position in the stream. + Any access + + + + Set the length of the current stream + Always throws a NotSupportedException + + The new length value for the stream. + Any access + + + + Writes a sequence of bytes to stream and advances the current position + This method always throws a NotSupportedException + + Thew buffer containing data to write. + The offset of the first byte to write. + The number of bytes to write. + Any access + + + + Writes one byte to the current stream and advances the current position + Always throws a NotSupportedException + + The byte to write. + Any access + + + + Entry point to begin an asynchronous write. Always throws a NotSupportedException. + + The buffer to write data from + Offset of first byte to write + The maximum number of bytes to write + The method to be called when the asynchronous write operation is completed + A user-provided object that distinguishes this particular asynchronous write request from other requests + An IAsyncResult that references the asynchronous write + Any access + + + + Closes the input stream. When + is true the underlying stream is also closed. + + + + + Reads decompressed data into the provided buffer byte array + + + The array to read and decompress data into + + + The offset indicating where the data should be placed + + + The number of bytes to decompress + + The number of bytes read. Zero signals the end of stream + + Inflater needs a dictionary + + + + + Decompressor for this stream + + + + + Input buffer for this stream. + + + + + Base stream the inflater reads from. + + + + + The compressed size + + + + + Flag indicating wether this instance has been closed or not. + + + + + Flag indicating wether this instance is designated the stream owner. + When closing if this flag is true the underlying stream is closed. + + + + + Get/set flag indicating ownership of underlying stream. + When the flag is true will close the underlying stream also. + + + The default value is true. + + + + + Returns 0 once the end of the stream (EOF) has been reached. + Otherwise returns 1. + + + + + Gets a value indicating whether the current stream supports reading + + + + + Gets a value of false indicating seeking is not supported for this stream. + + + + + Gets a value of false indicating that this stream is not writeable. + + + + + A value representing the length of the stream in bytes. + + + + + The current position within the stream. + Throws a NotSupportedException when attempting to set the position + + Attempting to set the position + + + + Initialise a new instance of the class. + + The underlying stream to use for IO. + The start of the partial data. + The length of the partial data. + + + + Skip the specified number of input bytes. + + The maximum number of input bytes to skip. + The actuial number of input bytes skipped. + + + + Read a byte from this stream. + + Returns the byte read or -1 on end of stream. + + + + Close this partial input stream. + + + The underlying stream is not closed. Close the parent ZipFile class to do that. + + + + + Provides a static way to obtain a source of data for an entry. + + + + + Get a source of data by creating a new stream. + + Returns a to use for compression input. + Ideally a new stream is created and opened to achieve this, to avoid locking problems. + + + + Represents a source of data that can dynamically provide + multiple data sources based on the parameters passed. + + + + + Get a data source. + + The to get a source for. + The name for data if known. + Returns a to use for compression input. + Ideally a new stream is created and opened to achieve this, to avoid locking problems. + + + + Default implementation of a for use with files stored on disk. + + + + + Initialise a new instnace of + + The name of the file to obtain data from. + + + + Get a providing data. + + Returns a provising data. + + + + Default implementation of for files stored on disk. + + + + + Initialise a default instance of . + + + + + Get a providing data for an entry. + + The entry to provide data for. + The file name for data if known. + Returns a stream providing data; or null if not available + + + + Defines facilities for data storage when updating Zip Archives. + + + + + Get an empty that can be used for temporary output. + + Returns a temporary output + + + + + Convert a temporary output stream to a final stream. + + The resulting final + + + + + Make a temporary copy of the original stream. + + The to copy. + Returns a temporary output that is a copy of the input. + + + + Return a stream suitable for performing direct updates on the original source. + + The current stream. + Returns a stream suitable for direct updating. + This may be the current stream passed. + + + + Dispose of this instance. + + + + + Get the to apply during updates. + + + + + An abstract suitable for extension by inheritance. + + + + + Initializes a new instance of the class. + + The update mode. + + + + Gets a temporary output + + Returns the temporary output stream. + + + + + Converts the temporary to its final form. + + Returns a that can be used to read + the final storage for the archive. + + + + + Make a temporary copy of a . + + The to make a copy of. + Returns a temporary output that is a copy of the input. + + + + Return a stream suitable for performing direct updates on the original source. + + The to open for direct update. + Returns a stream suitable for direct updating. + + + + Disposes this instance. + + + + + Gets the update mode applicable. + + The update mode. + + + + An implementation suitable for hard disks. + + + + + Initializes a new instance of the class. + + The file. + The update mode. + + + + Initializes a new instance of the class. + + The file. + + + + Gets a temporary output for performing updates on. + + Returns the temporary output stream. + + + + Converts a temporary to its final form. + + Returns a that can be used to read + the final storage for the archive. + + + + Make a temporary copy of a stream. + + The to copy. + Returns a temporary output that is a copy of the input. + + + + Return a stream suitable for performing direct updates on the original source. + + The current stream. + Returns a stream suitable for direct updating. + If the stream is not null this is used as is. + + + + Disposes this instance. + + + + + An implementation suitable for in memory streams. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The to use + This constructor is for testing as memory streams dont really require safe mode. + + + + Gets the temporary output + + Returns the temporary output stream. + + + + Converts the temporary to its final form. + + Returns a that can be used to read + the final storage for the archive. + + + + Make a temporary copy of the original stream. + + The to copy. + Returns a temporary output that is a copy of the input. + + + + Return a stream suitable for performing direct updates on the original source. + + The original source stream + Returns a stream suitable for direct updating. + If the passed is not null this is used; + otherwise a new is returned. + + + + Disposes this instance. + + + + + Get the stream returned by if this was in fact called. + + + + + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. + + + + + Interface to compute a data checksum used by checked input/output streams. + A data checksum can be updated by one byte or with a byte array. After each + update the value of the current checksum can be returned by calling + getValue. The complete checksum object can also be reset + so it can be used again with new data. + + + + + Resets the data checksum as if no update was ever called. + + + + + Adds one byte to the data checksum. + + + the data value to add. The high byte of the int is ignored. + + + + + Updates the data checksum with the bytes taken from the array. + + + buffer an array of bytes + + + + + Adds the byte array to the data checksum. + + + The buffer which contains the data + + + The offset in the buffer where the data starts + + + the number of data bytes to add. + + + + + Returns the data checksum computed so far. + + + + + The crc data checksum so far. + + + + + Resets the CRC32 data checksum as if no update was ever called. + + + + + Updates the checksum with the int bval. + + + the byte is taken as the lower 8 bits of value + + + + + Updates the checksum with the bytes taken from the array. + + + buffer an array of bytes + + + + + Adds the byte array to the data checksum. + + + The buffer which contains the data + + + The offset in the buffer where the data starts + + + The number of data bytes to update the CRC with. + + + + + Returns the CRC32 data checksum computed so far. + + + + + Basic implementation of + + + + + Defines factory methods for creating new values. + + + + + Create a for a file given its name + + The name of the file to create an entry for. + Returns a file entry based on the passed. + + + + Create a for a file given its name + + The name of the file to create an entry for. + If true get details from the file system if the file exists. + Returns a file entry based on the passed. + + + + Create a for a directory given its name + + The name of the directory to create an entry for. + Returns a directory entry based on the passed. + + + + Create a for a directory given its name + + The name of the directory to create an entry for. + If true get details from the file system for this directory if it exists. + Returns a directory entry based on the passed. + + + + Get/set the applicable. + + + + + Initialise a new instance of the class. + + A default , and the LastWriteTime for files is used. + + + + Initialise a new instance of using the specified + + The time setting to use when creating Zip entries. + + + + Initialise a new instance of using the specified + + The time to set all values to. + + + + Make a new for a file. + + The name of the file to create a new entry for. + Returns a new based on the . + + + + Make a new from a name. + + The name of the file to create a new entry for. + If true entry detail is retrieved from the file system if the file exists. + Returns a new based on the . + + + + Make a new for a directory. + + The raw untransformed name for the new directory + Returns a new representing a directory. + + + + Make a new for a directory. + + The raw untransformed name for the new directory + If true entry detail is retrieved from the file system if the file exists. + Returns a new representing a directory. + + + + Get / set the to be used when creating new values. + + + Setting this property to null will cause a default name transform to be used. + + + + + Get / set the in use. + + + + + Get / set the value to use when is set to + + + + + A bitmask defining the attributes to be retrieved from the actual file. + + The default is to get all possible attributes from the actual file. + + + + A bitmask defining which attributes are to be set on. + + By default no attributes are set on. + + + + Get set a value indicating wether unidoce text should be set on. + + + + + Defines the possible values to be used for the . + + + + + Use the recorded LastWriteTime value for the file. + + + + + Use the recorded LastWriteTimeUtc value for the file + + + + + Use the recorded CreateTime value for the file. + + + + + Use the recorded CreateTimeUtc value for the file. + + + + + Use the recorded LastAccessTime value for the file. + + + + + Use the recorded LastAccessTimeUtc value for the file. + + + + + Use a fixed value. + + The actual value used can be + specified via the constructor or + using the with the setting set + to which will use the when this class was constructed. + The property can also be used to set this value. + + + + PkzipClassic embodies the classic or original encryption facilities used in Pkzip archives. + While it has been superceded by more recent and more powerful algorithms, its still in use and + is viable for preventing casual snooping + + + + + Generates new encryption keys based on given seed + + The seed value to initialise keys with. + A new key value. + + + + PkzipClassicCryptoBase provides the low level facilities for encryption + and decryption using the PkzipClassic algorithm. + + + + + Transform a single byte + + + The transformed value + + + + + Set the key schedule for encryption/decryption. + + The data use to set the keys from. + + + + Update encryption keys + + + + + Reset the internal state. + + + + + PkzipClassic CryptoTransform for encryption. + + + + + Initialise a new instance of + + The key block to use. + + + + Transforms the specified region of the specified byte array. + + The input for which to compute the transform. + The offset into the byte array from which to begin using data. + The number of bytes in the byte array to use as data. + The computed transform. + + + + Transforms the specified region of the input byte array and copies + the resulting transform to the specified region of the output byte array. + + The input for which to compute the transform. + The offset into the input byte array from which to begin using data. + The number of bytes in the input byte array to use as data. + The output to which to write the transform. + The offset into the output byte array from which to begin writing data. + The number of bytes written. + + + + Cleanup internal state. + + + + + Gets a value indicating whether the current transform can be reused. + + + + + Gets the size of the input data blocks in bytes. + + + + + Gets the size of the output data blocks in bytes. + + + + + Gets a value indicating whether multiple blocks can be transformed. + + + + + PkzipClassic CryptoTransform for decryption. + + + + + Initialise a new instance of . + + The key block to decrypt with. + + + + Transforms the specified region of the specified byte array. + + The input for which to compute the transform. + The offset into the byte array from which to begin using data. + The number of bytes in the byte array to use as data. + The computed transform. + + + + Transforms the specified region of the input byte array and copies + the resulting transform to the specified region of the output byte array. + + The input for which to compute the transform. + The offset into the input byte array from which to begin using data. + The number of bytes in the input byte array to use as data. + The output to which to write the transform. + The offset into the output byte array from which to begin writing data. + The number of bytes written. + + + + Cleanup internal state. + + + + + Gets a value indicating whether the current transform can be reused. + + + + + Gets the size of the input data blocks in bytes. + + + + + Gets the size of the output data blocks in bytes. + + + + + Gets a value indicating whether multiple blocks can be transformed. + + + + + Defines a wrapper object to access the Pkzip algorithm. + This class cannot be inherited. + + + + + Generate an initial vector. + + + + + Generate a new random key. + + + + + Create an encryptor. + + The key to use for this encryptor. + Initialisation vector for the new encryptor. + Returns a new PkzipClassic encryptor + + + + Create a decryptor. + + Keys to use for this new decryptor. + Initialisation vector for the new decryptor. + Returns a new decryptor. + + + + Get / set the applicable block size in bits. + + The only valid block size is 8. + + + + Get an array of legal key sizes. + + + + + Get an array of legal block sizes. + + + + + Get / set the key value applicable. + + + + + This class represents an entry in a Tar archive. It consists + of the entry's header, as well as the entry's File. Entries + can be instantiated in one of three ways, depending on how + they are to be used. +

+ TarEntries that are created from the header bytes read from + an archive are instantiated with the TarEntry( byte[] ) + constructor. These entries will be used when extracting from + or listing the contents of an archive. These entries have their + header filled in using the header bytes. They also set the File + to null, since they reference an archive entry not a file.

+

+ TarEntries that are created from files that are to be written + into an archive are instantiated with the CreateEntryFromFile(string) + pseudo constructor. These entries have their header filled in using + the File's information. They also keep a reference to the File + for convenience when writing entries.

+

+ Finally, TarEntries can be constructed from nothing but a name. + This allows the programmer to construct the entry by hand, for + instance when only an InputStream is available for writing to + the archive, and the header information is constructed from + other information. In this case the header fields are set to + defaults and the File is set to null.

+ +
+
+ + + Initialise a default instance of . + + + + + Construct an entry from an archive's header bytes. File is set + to null. + + + The header bytes from a tar archive entry. + + + + + Construct a TarEntry using the header provided + + Header details for entry + + + + Clone this tar entry. + + Returns a clone of this entry. + + + + Construct an entry with only a name. + This allows the programmer to construct the entry's header "by hand". + + The name to use for the entry + Returns the newly created + + + + Construct an entry for a file. File is set to file, and the + header is constructed from information from the file. + + The file name that the entry represents. + Returns the newly created + + + + Determine if the two entries are equal. Equality is determined + by the header names being equal. + + The to compare with the current Object. + + True if the entries are equal; false if not. + + + + + Derive a Hash value for the current + + A Hash code for the current + + + + Determine if the given entry is a descendant of this entry. + Descendancy is determined by the name of the descendant + starting with this entry's name. + + + Entry to be checked as a descendent of this. + + + True if entry is a descendant of this. + + + + + Convenience method to set this entry's group and user ids. + + + This entry's new user id. + + + This entry's new group id. + + + + + Convenience method to set this entry's group and user names. + + + This entry's new user name. + + + This entry's new group name. + + + + + Fill in a TarHeader with information from a File. + + + The TarHeader to fill in. + + + The file from which to get the header information. + + + + + Get entries for all files present in this entries directory. + If this entry doesnt represent a directory zero entries are returned. + + + An array of TarEntry's for this entry's children. + + + + + Write an entry's header information to a header buffer. + + + The tar entry header buffer to fill in. + + + + + Convenience method that will modify an entry's name directly + in place in an entry header buffer byte array. + + + The buffer containing the entry header to modify. + + + The new name to place into the header buffer. + + + + + Fill in a TarHeader given only the entry's name. + + + The TarHeader to fill in. + + + The tar entry name. + + + + + The name of the file this entry represents or null if the entry is not based on a file. + + + + + The entry's header information. + + + + + Get this entry's header. + + + This entry's TarHeader. + + + + + Get/Set this entry's name. + + + + + Get/set this entry's user id. + + + + + Get/set this entry's group id. + + + + + Get/set this entry's user name. + + + + + Get/set this entry's group name. + + + + + Get/Set the modification time for this entry + + + + + Get this entry's file. + + + This entry's file. + + + + + Get/set this entry's recorded file size. + + + + + Return true if this entry represents a directory, false otherwise + + + True if this entry is a directory. + + + + + This filter stream is used to decompress a "GZIP" format stream. + The "GZIP" format is described baseInputStream RFC 1952. + + author of the original java version : John Leuner + + This sample shows how to unzip a gzipped file + + using System; + using System.IO; + + using ICSharpCode.SharpZipLib.Core; + using ICSharpCode.SharpZipLib.GZip; + + class MainClass + { + public static void Main(string[] args) + { + using (Stream inStream = new GZipInputStream(File.OpenRead(args[0]))) + using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { + byte[] buffer = new byte[4096]; + StreamUtils.Copy(inStream, outStream, buffer); + } + } + } + + + + + + CRC-32 value for uncompressed data + + + + + Indicates end of stream + + + + + Creates a GZipInputStream with the default buffer size + + + The stream to read compressed data from (baseInputStream GZIP format) + + + + + Creates a GZIPInputStream with the specified buffer size + + + The stream to read compressed data from (baseInputStream GZIP format) + + + Size of the buffer to use + + + + + Reads uncompressed data into an array of bytes + + + The buffer to read uncompressed data into + + + The offset indicating where the data should be placed + + + The number of uncompressed bytes to be read + + Returns the number of bytes actually read. + + + + Provides simple " utilities. + + + + + Read from a ensuring all the required data is read. + + The stream to read. + The buffer to fill. + + + + Read from a " ensuring all the required data is read. + + The stream to read data from. + The buffer to store data in. + The offset at which to begin storing data. + The number of bytes of data to store. + + + + Copy the contents of one to another. + + The stream to source data from. + The stream to write data to. + The buffer to use during copying. + The progress handler delegate to use. + The minimum between progress updates. + The source for this event. + The name to use with the event. + + + + Copy the contents of one to another. + + The stream to source data from. + The stream to write data to. + The buffer to use during copying. + + + + Initialise an instance of + + + + + This is the DeflaterHuffman class. + + This class is not thread safe. This is inherent in the API, due + to the split of Deflate and SetInput. + + author of the original java version : Jochen Hoenicke + + + + + Pending buffer to use + + + + + Construct instance with pending buffer + + Pending buffer to use + + + + Reset internal state + + + + + Write all trees to pending buffer + + The number/rank of treecodes to send. + + + + Compress current buffer writing data to pending buffer + + + + + Flush block to output with no compression + + Data to write + Index of first byte to write + Count of bytes to write + True if this is the last block + + + + Flush block to output with compression + + Data to flush + Index of first byte to flush + Count of bytes to flush + True if this is the last block + + + + Get value indicating if internal buffer is full + + true if buffer is full + + + + Add literal to buffer + + Literal value to add to buffer. + Value indicating internal buffer is full + + + + Add distance code and length to literal and distance trees + + Distance code + Length + Value indicating if internal buffer is full + + + + Reverse the bits of a 16 bit value. + + Value to reverse bits + Value with bits reversed + + + + Resets the internal state of the tree + + + + + Check that all frequencies are zero + + + At least one frequency is non-zero + + + + + Set static codes and length + + new codes + length for new codes + + + + Build dynamic codes and lengths + + + + + Get encoded length + + Encoded length, the sum of frequencies * lengths + + + + Scan a literal or distance tree to determine the frequencies of the codes + in the bit length tree. + + + + + Write tree values + + Tree to write + + + + This class contains constants used for gzip. + + + + + Magic number found at start of GZIP header + + + + + Flag bit mask for text + + + + + Flag bitmask for Crc + + + + + Flag bit mask for extra + + + + + flag bitmask for name + + + + + flag bit mask indicating comment is present + + + + + Initialise default instance. + + Constructor is private to prevent instances being created. + + + + TarExceptions are used for exceptions specific to tar classes and code. + + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initialises a new instance of the TarException class. + + + + + Initialises a new instance of the TarException class with a specified message. + + The message that describes the error. + + + + + + A message describing the error. + The exception that is the cause of the current exception. + + + + Bzip2 checksum algorithm + + + + + Initialise a default instance of + + + + + Reset the state of Crc. + + + + + Update the Crc value. + + data update is based on + + + + Update Crc based on a block of data + + The buffer containing data to update the crc with. + + + + Update Crc based on a portion of a block of data + + block of data + index of first byte to use + number of bytes to use + + + + Get the current Crc value. + + + + + This is an InflaterInputStream that reads the files baseInputStream an zip archive + one after another. It has a special method to get the zip entry of + the next file. The zip entry contains information about the file name + size, compressed size, Crc, etc. + It includes support for Stored and Deflated entries. +
+
Author of the original java version : Jochen Hoenicke +
+ + This sample shows how to read a zip file + + using System; + using System.Text; + using System.IO; + + using ICSharpCode.SharpZipLib.Zip; + + class MainClass + { + public static void Main(string[] args) + { + using ( ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]))) { + + ZipEntry theEntry; + while ((theEntry = s.GetNextEntry()) != null) { + int size = 2048; + byte[] data = new byte[2048]; + + Console.Write("Show contents (y/n) ?"); + if (Console.ReadLine() == "y") { + while (true) { + size = s.Read(data, 0, data.Length); + if (size > 0) { + Console.Write(new ASCIIEncoding().GetString(data, 0, size)); + } else { + break; + } + } + } + } + } + } + } + + +
+ + + The current reader this instance. + + + + + Creates a new Zip input stream, for reading a zip archive. + + The underlying providing data. + + + + Advances to the next entry in the archive + + + The next entry in the archive or null if there are no more entries. + + + If the previous entry is still open CloseEntry is called. + + + Input stream is closed + + + Password is not set, password is invalid, compression method is invalid, + version required to extract is not supported + + + + + Read data descriptor at the end of compressed data. + + + + + Complete cleanup as the final part of closing. + + True if the crc value should be tested + + + + Closes the current zip entry and moves to the next one. + + + The stream is closed + + + The Zip stream ends early + + + + + Reads a byte from the current zip entry. + + + The byte or -1 if end of stream is reached. + + + + + Handle attempts to read by throwing an . + + The destination array to store data in. + The offset at which data read should be stored. + The maximum number of bytes to read. + Returns the number of bytes actually read. + + + + Handle attempts to read from this entry by throwing an exception + + + + + Perform the initial read on an entry which may include + reading encryption headers and setting up inflation. + + The destination to fill with data read. + The offset to start reading at. + The maximum number of bytes to read. + The actual number of bytes read. + + + + Read a block of bytes from the stream. + + The destination for the bytes. + The index to start storing data. + The number of bytes to attempt to read. + Returns the number of bytes read. + Zero bytes read means end of stream. + + + + Reads a block of bytes from the current zip entry. + + + The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream. + + + An i/o error occured. + + + The deflated stream is corrupted. + + + The stream is not open. + + + + + Closes the zip input stream + + + + + Optional password used for encryption when non-null + + A password for all encrypted entries in this + + + + Gets a value indicating if there is a current entry and it can be decompressed + + + The entry can only be decompressed if the library supports the zip features required to extract it. + See the ZipEntry Version property for more details. + + + + + Returns 1 if there is an entry available + Otherwise returns 0. + + + + + Returns the current size that can be read from the current entry if available + + Thrown if the entry size is not known. + Thrown if no entry is currently available. + + + + ZipNameTransform transforms names as per the Zip file naming convention. + + The use of absolute names is supported although its use is not valid + according to Zip naming conventions, and should not be used if maximum compatability is desired. + + + + Initialize a new instance of + + + + + Initialize a new instance of + + The string to trim from front of paths if found. + + + + Static constructor. + + + + + Transform a directory name according to the Zip file naming conventions. + + The directory name to transform. + The transformed name. + + + + Transform a windows file name according to the Zip file naming conventions. + + The file name to transform. + The transformed name. + + + + Force a name to be valid by replacing invalid characters with a fixed value + + The name to force valid + The replacement character to use. + Returns a valid name + + + + Test a name to see if it is a valid name for a zip entry. + + The name to test. + If true checking is relaxed about windows file names and absolute paths. + Returns true if the name is a valid zip name; false otherwise. + Zip path names are actually in Unix format, and should only contain relative paths. + This means that any path stored should not contain a drive or + device letter, or a leading slash. All slashes should forward slashes '/'. + An empty name is valid for a file where the input comes from standard input. + A null name is not considered valid. + + + + + Test a name to see if it is a valid name for a zip entry. + + The name to test. + Returns true if the name is a valid zip name; false otherwise. + Zip path names are actually in unix format, + and should only contain relative paths if a path is present. + This means that the path stored should not contain a drive or + device letter, or a leading slash. All slashes should forward slashes '/'. + An empty name is valid where the input comes from standard input. + A null name is not considered valid. + + + + + Get/set the path prefix to be trimmed from paths if present. + + The prefix is trimmed before any conversion from + a windows path is done. + + + + This exception is used to indicate that there is a problem + with a TAR archive header. + + + + + Deserialization constructor + + for this constructor + for this constructor + + + + Initialise a new instance of the InvalidHeaderException class. + + + + + Initialises a new instance of the InvalidHeaderException class with a specified message. + + Message describing the exception cause. + + + + Initialise a new instance of InvalidHeaderException + + Message describing the problem. + The exception that is the cause of the current exception. + + + + This class allows us to retrieve a specified number of bits from + the input buffer, as well as copy big byte blocks. + + It uses an int buffer to store up to 31 bits for direct + manipulation. This guarantees that we can get at least 16 bits, + but we only need at most 15, so this is all safe. + + There are some optimizations in this class, for example, you must + never peek more than 8 bits more than needed, and you must first + peek bits before you may drop them. This is not a general purpose + class but optimized for the behaviour of the Inflater. + + authors of the original java version : John Leuner, Jochen Hoenicke + + + + + Constructs a default StreamManipulator with all buffers empty + + + + + Get the next sequence of bits but don't increase input pointer. bitCount must be + less or equal 16 and if this call succeeds, you must drop + at least n - 8 bits in the next call. + + The number of bits to peek. + + the value of the bits, or -1 if not enough bits available. */ + + + + + Drops the next n bits from the input. You should have called PeekBits + with a bigger or equal n before, to make sure that enough bits are in + the bit buffer. + + The number of bits to drop. + + + + Gets the next n bits and increases input pointer. This is equivalent + to followed by , except for correct error handling. + + The number of bits to retrieve. + + the value of the bits, or -1 if not enough bits available. + + + + + Skips to the next byte boundary. + + + + + Copies bytes from input buffer to output buffer starting + at output[offset]. You have to make sure, that the buffer is + byte aligned. If not enough bytes are available, copies fewer + bytes. + + + The buffer to copy bytes to. + + + The offset in the buffer at which copying starts + + + The length to copy, 0 is allowed. + + + The number of bytes copied, 0 if no bytes were available. + + + Length is less than zero + + + Bit buffer isnt byte aligned + + + + + Resets state and empties internal buffers + + + + + Add more input for consumption. + Only call when IsNeedingInput returns true + + data to be input + offset of first byte of input + number of bytes of input to add. + + + + Gets the number of bits available in the bit buffer. This must be + only called when a previous PeekBits() returned -1. + + + the number of bits available. + + + + + Gets the number of bytes available. + + + The number of bytes available. + + + + + Returns true when SetInput can be called + + + + + Strategies for deflater + + + + + The default strategy + + + + + This strategy will only allow longer string repetitions. It is + useful for random data with a small character set. + + + + + This strategy will not look for string repetitions at all. It + only encodes with Huffman trees (which means, that more common + characters get a smaller encoding. + + + + + Low level compression engine for deflate algorithm which uses a 32K sliding window + with secondary compression from Huffman/Shannon-Fano codes. + + + + + Construct instance with pending buffer + + + Pending buffer to use + > + + + + Deflate drives actual compression of data + + True to flush input buffers + Finish deflation with the current input. + Returns true if progress has been made. + + + + Sets input data to be deflated. Should only be called when NeedsInput() + returns true + + The buffer containing input data. + The offset of the first byte of data. + The number of bytes of data to use as input. + + + + Determines if more input is needed. + + Return true if input is needed via SetInput + + + + Set compression dictionary + + The buffer containing the dictionary data + The offset in the buffer for the first byte of data + The length of the dictionary data. + + + + Reset internal state + + + + + Reset Adler checksum + + + + + Set the deflate level (0-9) + + The value to set the level to. + + + + Fill the window + + + + + Inserts the current string in the head hash and returns the previous + value for this hash. + + The previous hash value + + + + Find the best (longest) string in the window matching the + string starting at strstart. + + Preconditions: + + strstart + MAX_MATCH <= window.length. + + + True if a match greater than the minimum length is found + + + + Hashtable, hashing three characters to an index for window, so + that window[index]..window[index+2] have this hash code. + Note that the array should really be unsigned short, so you need + to and the values with 0xffff. + + + + + prev[index & WMASK] points to the previous index that has the + same hash code as the string starting at index. This way + entries with the same hash code are in a linked list. + Note that the array should really be unsigned short, so you need + to and the values with 0xffff. + + + + + Points to the current character in the window. + + + + + lookahead is the number of characters starting at strstart in + window that are valid. + So window[strstart] until window[strstart+lookahead-1] are valid + characters. + + + + + This array contains the part of the uncompressed stream that + is of relevance. The current character is indexed by strstart. + + + + + The current compression function. + + + + + The input data for compression. + + + + + The total bytes of input read. + + + + + The offset into inputBuf, where input data starts. + + + + + The end offset of the input data. + + + + + The adler checksum + + + + + Get current value of Adler checksum + + + + + Total data processed + + + + + Get/set the deflate strategy + + + + + The TarBuffer class implements the tar archive concept + of a buffered input stream. This concept goes back to the + days of blocked tape drives and special io devices. In the + C# universe, the only real function that this class + performs is to ensure that files have the correct "record" + size, or other tars will complain. +

+ You should never have a need to access this class directly. + TarBuffers are created by Tar IO Streams. +

+
+
+ + + The size of a block in a tar archive in bytes. + + This is 512 bytes. + + + + The number of blocks in a default record. + + + The default value is 20 blocks per record. + + + + + The size in bytes of a default record. + + + The default size is 10KB. + + + + + Get the TAR Buffer's record size. + + The record size in bytes. + This is equal to the multiplied by the + + + + Get the TAR Buffer's block factor + + The block factor; the number of blocks per record. + + + + Construct a default TarBuffer + + + + + Create TarBuffer for reading with default BlockFactor + + Stream to buffer + A new suitable for input. + + + + Construct TarBuffer for reading inputStream setting BlockFactor + + Stream to buffer + Blocking factor to apply + A new suitable for input. + + + + Construct TarBuffer for writing with default BlockFactor + + output stream for buffer + A new suitable for output. + + + + Construct TarBuffer for writing Tar output to streams. + + Output stream to write to. + Blocking factor to apply + A new suitable for output. + + + + Initialization common to all constructors. + + + + + Determine if an archive block indicates End of Archive. End of + archive is indicated by a block that consists entirely of null bytes. + All remaining blocks for the record should also be null's + However some older tars only do a couple of null blocks (Old GNU tar for one) + and also partial records + + The data block to check. + Returns true if the block is an EOF block; false otherwise. + + + + Skip over a block on the input stream. + + + + + Read a block from the input stream. + + + The block of data read. + + + + + Read a record from data stream. + + + false if End-Of-File, else true. + + + + + Get the current block number, within the current record, zero based. + + + The current zero based block number. + + + The absolute block number = (record number * block factor) + block number. + + + + + Get the current record number. + + + The current zero based record number. + + + + + Write a block of data to the archive. + + + The data to write to the archive. + + + + + Write an archive record to the archive, where the record may be + inside of a larger array buffer. The buffer must be "offset plus + record size" long. + + + The buffer containing the record data to write. + + + The offset of the record data within buffer. + + + + + Write a TarBuffer record to the archive. + + + + + Flush the current record if it has any data in it. + + + + + Close the TarBuffer. If this is an output buffer, also flush the + current block before closing. + + + + + Get the record size for this buffer + + The record size in bytes. + This is equal to the multiplied by the + + + + Get the Blocking factor for the buffer + + This is the number of block in each record. + + + + Get the current block number, within the current record, zero based. + + + + + Get the current record number. + + + The current zero based record number. + + + + + This class encapsulates the Tar Entry Header used in Tar Archives. + The class also holds a number of tar constants, used mostly in headers. + + + + + The length of the name field in a header buffer. + + + + + The length of the mode field in a header buffer. + + + + + The length of the user id field in a header buffer. + + + + + The length of the group id field in a header buffer. + + + + + The length of the checksum field in a header buffer. + + + + + Offset of checksum in a header buffer. + + + + + The length of the size field in a header buffer. + + + + + The length of the magic field in a header buffer. + + + + + The length of the version field in a header buffer. + + + + + The length of the modification time field in a header buffer. + + + + + The length of the user name field in a header buffer. + + + + + The length of the group name field in a header buffer. + + + + + The length of the devices field in a header buffer. + + + + + The "old way" of indicating a normal file. + + + + + Normal file type. + + + + + Link file type. + + + + + Symbolic link file type. + + + + + Character device file type. + + + + + Block device file type. + + + + + Directory file type. + + + + + FIFO (pipe) file type. + + + + + Contiguous file type. + + + + + Posix.1 2001 global extended header + + + + + Posix.1 2001 extended header + + + + + Solaris access control list file type + + + + + GNU dir dump file type + This is a dir entry that contains the names of files that were in the + dir at the time the dump was made + + + + + Solaris Extended Attribute File + + + + + Inode (metadata only) no file content + + + + + Identifies the next file on the tape as having a long link name + + + + + Identifies the next file on the tape as having a long name + + + + + Continuation of a file that began on another volume + + + + + For storing filenames that dont fit in the main header (old GNU) + + + + + GNU Sparse file + + + + + GNU Tape/volume header ignore on extraction + + + + + The magic tag representing a POSIX tar archive. (includes trailing NULL) + + + + + The magic tag representing an old GNU tar archive where version is included in magic and overwrites it + + + + + Initialise a default TarHeader instance + + + + + Get the name of this entry. + + The entry's name. + + + + Create a new that is a copy of the current instance. + + A new that is a copy of the current instance. + + + + Parse TarHeader information from a header buffer. + + + The tar entry header buffer to get information from. + + + + + 'Write' header information to buffer provided, updating the check sum. + + output buffer for header information + + + + Get a hash code for the current object. + + A hash code for the current object. + + + + Determines if this instance is equal to the specified object. + + The object to compare with. + true if the objects are equal, false otherwise. + + + + Set defaults for values used when constructing a TarHeader instance. + + Value to apply as a default for userId. + Value to apply as a default for userName. + Value to apply as a default for groupId. + Value to apply as a default for groupName. + + + + Parse an octal string from a header buffer. + + The header buffer from which to parse. + The offset into the buffer from which to parse. + The number of header bytes to parse. + The long equivalent of the octal string. + + + + Parse a name from a header buffer. + + + The header buffer from which to parse. + + + The offset into the buffer from which to parse. + + + The number of header bytes to parse. + + + The name parsed. + + + + + Add name to the buffer as a collection of bytes + + The name to add + The offset of the first character + The buffer to add to + The index of the first byte to add + The number of characters/bytes to add + The next free index in the buffer + + + + Add name to the buffer as a collection of bytes + + The name to add + The offset of the first character + The buffer to add to + The index of the first byte to add + The number of characters/bytes to add + The next free index in the buffer + + + + Add an entry name to the buffer + + + The name to add + + + The buffer to add to + + + The offset into the buffer from which to start adding + + + The number of header bytes to add + + + The index of the next free byte in the buffer + + + + + Add an entry name to the buffer + + The name to add + The buffer to add to + The offset into the buffer from which to start adding + The number of header bytes to add + The index of the next free byte in the buffer + + + + Add a string to a buffer as a collection of ascii bytes. + + The string to add + The offset of the first character to add. + The buffer to add to. + The offset to start adding at. + The number of ascii characters to add. + The next free index in the buffer. + + + + Put an octal representation of a value into a buffer + + + the value to be converted to octal + + + buffer to store the octal string + + + The offset into the buffer where the value starts + + + The length of the octal string to create + + + The offset of the character next byte after the octal string + + + + + Put an octal representation of a value into a buffer + + Value to be convert to octal + The buffer to update + The offset into the buffer to store the value + The length of the octal string + Index of next byte + + + + Add the checksum integer to header buffer. + + + The header buffer to set the checksum for + The offset into the buffer for the checksum + The number of header bytes to update. + It's formatted differently from the other fields: it has 6 digits, a + null, then a space -- rather than digits, a space, then a null. + The final space is already there, from checksumming + + The modified buffer offset + + + + Compute the checksum for a tar entry header. + The checksum field must be all spaces prior to this happening + + The tar entry's header buffer. + The computed checksum. + + + + Make a checksum for a tar entry ignoring the checksum contents. + + The tar entry's header buffer. + The checksum for the buffer + + + + Get/set the name for this tar entry. + + Thrown when attempting to set the property to null. + + + + Get/set the entry's Unix style permission mode. + + + + + The entry's user id. + + + This is only directly relevant to unix systems. + The default is zero. + + + + + Get/set the entry's group id. + + + This is only directly relevant to linux/unix systems. + The default value is zero. + + + + + Get/set the entry's size. + + Thrown when setting the size to less than zero. + + + + Get/set the entry's modification time. + + + The modification time is only accurate to within a second. + + Thrown when setting the date time to less than 1/1/1970. + + + + Get the entry's checksum. This is only valid/updated after writing or reading an entry. + + + + + Get value of true if the header checksum is valid, false otherwise. + + + + + Get/set the entry's type flag. + + + + + The entry's link name. + + Thrown when attempting to set LinkName to null. + + + + Get/set the entry's magic tag. + + Thrown when attempting to set Magic to null. + + + + The entry's version. + + Thrown when attempting to set Version to null. + + + + The entry's user name. + + + + + Get/set the entry's group name. + + + This is only directly relevant to unix systems. + + + + + Get/set the entry's major device number. + + + + + Get/set the entry's minor device number. + + + + + Event arguments for scanning. + + + + + Initialise a new instance of + + The file or directory name. + + + + The fie or directory name for this event. + + + + + Get set a value indicating if scanning should continue or not. + + + + + Event arguments during processing of a single file or directory. + + + + + Initialise a new instance of + + The file or directory name if known. + The number of bytes processed so far + The total number of bytes to process, 0 if not known + + + + The name for this event if known. + + + + + Get set a value indicating wether scanning should continue or not. + + + + + Get a percentage representing how much of the has been processed + + 0.0 to 100.0 percent; 0 if target is not known. + + + + The number of bytes processed so far + + + + + The number of bytes to process. + + Target may be 0 or negative if the value isnt known. + + + + Event arguments for directories. + + + + + Initialize an instance of . + + The name for this directory. + Flag value indicating if any matching files are contained in this directory. + + + + Get a value indicating if the directory contains any matching files or not. + + + + + Arguments passed when scan failures are detected. + + + + + Initialise a new instance of + + The name to apply. + The exception to use. + + + + The applicable name. + + + + + The applicable exception. + + + + + Get / set a value indicating wether scanning should continue. + + + + + Delegate invoked before starting to process a directory. + + + + + Delegate invoked before starting to process a file. + + The source of the event + The event arguments. + + + + Delegate invoked during processing of a file or directory + + The source of the event + The event arguments. + + + + Delegate invoked when a file has been completely processed. + + The source of the event + The event arguments. + + + + Delegate invoked when a directory failure is detected. + + The source of the event + The event arguments. + + + + Delegate invoked when a file failure is detected. + + The source of the event + The event arguments. + + + + FileSystemScanner provides facilities scanning of files and directories. + + + + + Initialise a new instance of + + The file filter to apply when scanning. + + + + Initialise a new instance of + + The file filter to apply. + The directory filter to apply. + + + + Initialise a new instance of + + The file filter to apply. + + + + Initialise a new instance of + + The file filter to apply. + The directory filter to apply. + + + + Delegate to invoke when a directory is processed. + + + + + Delegate to invoke when a file is processed. + + + + + Delegate to invoke when processing for a file has finished. + + + + + Delegate to invoke when a directory failure is detected. + + + + + Delegate to invoke when a file failure is detected. + + + + + Raise the DirectoryFailure event. + + The directory name. + The exception detected. + + + + Raise the FileFailure event. + + The file name. + The exception detected. + + + + Raise the ProcessFile event. + + The file name. + + + + Raise the complete file event + + The file name + + + + Raise the ProcessDirectory event. + + The directory name. + Flag indicating if the directory has matching files. + + + + Scan a directory. + + The base directory to scan. + True to recurse subdirectories, false to scan a single directory. + + + + The file filter currently in use. + + + + + The directory filter currently in use. + + + + + Flag indicating if scanning should continue running. + + + + + An input buffer customised for use by + + + The buffer supports decryption of incoming data. + + + + + Initialise a new instance of with a default buffer size + + The stream to buffer. + + + + Initialise a new instance of + + The stream to buffer. + The size to use for the buffer + A minimum buffer size of 1KB is permitted. Lower sizes are treated as 1KB. + + + + Call passing the current clear text buffer contents. + + The inflater to set input for. + + + + Fill the buffer from the underlying input stream. + + + + + Read a buffer directly from the input stream + + The buffer to fill + Returns the number of bytes read. + + + + Read a buffer directly from the input stream + + The buffer to read into + The offset to start reading data into. + The number of bytes to read. + Returns the number of bytes read. + + + + Read clear text data from the input stream. + + The buffer to add data to. + The offset to start adding data at. + The number of bytes to read. + Returns the number of bytes actually read. + + + + Read a from the input stream. + + Returns the byte read. + + + + Read an in little endian byte order. + + The short value read case to an int. + + + + Read an in little endian byte order. + + The int value read. + + + + Read a in little endian byte order. + + The long value read. + + + + Get the length of bytes bytes in the + + + + + Get the contents of the raw data buffer. + + This may contain encrypted data. + + + + Get the number of useable bytes in + + + + + Get the contents of the clear text buffer. + + + + + Get/set the number of bytes available + + + + + Get/set the to apply to any data. + + Set this value to null to have no transform applied. + + + + The TarOutputStream writes a UNIX tar archive as an OutputStream. + Methods are provided to put entries, and then write their contents + by writing to this stream using write(). + + public + + + + Construct TarOutputStream using default block factor + + stream to write to + + + + Construct TarOutputStream with user specified block factor + + stream to write to + blocking factor + + + + set the position within the current stream + + The offset relative to the to seek to + The to seek from. + The new position in the stream. + + + + Set the length of the current stream + + The new stream length. + + + + Read a byte from the stream and advance the position within the stream + by one byte or returns -1 if at the end of the stream. + + The byte value or -1 if at end of stream + + + + read bytes from the current stream and advance the position within the + stream by the number of bytes read. + + The buffer to store read bytes in. + The index into the buffer to being storing bytes at. + The desired number of bytes to read. + The total number of bytes read, or zero if at the end of the stream. + The number of bytes may be less than the count + requested if data is not avialable. + + + + All buffered data is written to destination + + + + + Ends the TAR archive without closing the underlying OutputStream. + The result is that the EOF block of nulls is written. + + + + + Ends the TAR archive and closes the underlying OutputStream. + + This means that Finish() is called followed by calling the + TarBuffer's Close(). + + + + Get the record size being used by this stream's TarBuffer. + + + The TarBuffer record size. + + + + + Put an entry on the output stream. This writes the entry's + header and positions the output stream for writing + the contents of the entry. Once this method is called, the + stream is ready for calls to write() to write the entry's + contents. Once the contents are written, closeEntry() + MUST be called to ensure that all buffered data + is completely written to the output stream. + + + The TarEntry to be written to the archive. + + + + + Close an entry. This method MUST be called for all file + entries that contain data. The reason is that we must + buffer data written to the stream in order to satisfy + the buffer's block based writes. Thus, there may be + data fragments still being assembled that must be written + to the output stream before this entry is closed and the + next entry written. + + + + + Writes a byte to the current tar archive entry. + This method simply calls Write(byte[], int, int). + + + The byte to be written. + + + + + Writes bytes to the current tar archive entry. This method + is aware of the current entry and will throw an exception if + you attempt to write bytes past the length specified for the + current entry. The method is also (painfully) aware of the + record buffering required by TarBuffer, and manages buffers + that are not a multiple of recordsize in length, including + assembling records from small buffers. + + + The buffer to write to the archive. + + + The offset in the buffer from which to get bytes. + + + The number of bytes to write. + + + + + Write an EOF (end of archive) block to the tar archive. + An EOF block consists of all zeros. + + + + + bytes written for this entry so far + + + + + current 'Assembly' buffer length + + + + + Flag indicating wether this instance has been closed or not. + + + + + Size for the current entry + + + + + single block working buffer + + + + + 'Assembly' buffer used to assemble data before writing + + + + + TarBuffer used to provide correct blocking factor + + + + + the destination stream for the archive contents + + + + + true if the stream supports reading; otherwise, false. + + + + + true if the stream supports seeking; otherwise, false. + + + + + true if stream supports writing; otherwise, false. + + + + + length of stream in bytes + + + + + gets or sets the position within the current stream. + + + + + Get the record size being used by this stream's TarBuffer. + + + + + Get a value indicating wether an entry is open, requiring more data to be written. + + + + + This is the Deflater class. The deflater class compresses input + with the deflate algorithm described in RFC 1951. It has several + compression levels and three different strategies described below. + + This class is not thread safe. This is inherent in the API, due + to the split of deflate and setInput. + + author of the original java version : Jochen Hoenicke + + + + + The best and slowest compression level. This tries to find very + long and distant string repetitions. + + + + + The worst but fastest compression level. + + + + + The default compression level. + + + + + This level won't compress at all but output uncompressed blocks. + + + + + The compression method. This is the only method supported so far. + There is no need to use this constant at all. + + + + + Creates a new deflater with default compression level. + + + + + Creates a new deflater with given compression level. + + + the compression level, a value between NO_COMPRESSION + and BEST_COMPRESSION, or DEFAULT_COMPRESSION. + + if lvl is out of range. + + + + Creates a new deflater with given compression level. + + + the compression level, a value between NO_COMPRESSION + and BEST_COMPRESSION. + + + true, if we should suppress the Zlib/RFC1950 header at the + beginning and the adler checksum at the end of the output. This is + useful for the GZIP/PKZIP formats. + + if lvl is out of range. + + + + Resets the deflater. The deflater acts afterwards as if it was + just created with the same compression level and strategy as it + had before. + + + + + Flushes the current input block. Further calls to deflate() will + produce enough output to inflate everything in the current input + block. This is not part of Sun's JDK so I have made it package + private. It is used by DeflaterOutputStream to implement + flush(). + + + + + Finishes the deflater with the current input block. It is an error + to give more input after this method was called. This method must + be called to force all bytes to be flushed. + + + + + Sets the data which should be compressed next. This should be only + called when needsInput indicates that more input is needed. + If you call setInput when needsInput() returns false, the + previous input that is still pending will be thrown away. + The given byte array should not be changed, before needsInput() returns + true again. + This call is equivalent to setInput(input, 0, input.length). + + + the buffer containing the input data. + + + if the buffer was finished() or ended(). + + + + + Sets the data which should be compressed next. This should be + only called when needsInput indicates that more input is needed. + The given byte array should not be changed, before needsInput() returns + true again. + + + the buffer containing the input data. + + + the start of the data. + + + the number of data bytes of input. + + + if the buffer was Finish()ed or if previous input is still pending. + + + + + Sets the compression level. There is no guarantee of the exact + position of the change, but if you call this when needsInput is + true the change of compression level will occur somewhere near + before the end of the so far given input. + + + the new compression level. + + + + + Get current compression level + + Returns the current compression level + + + + Sets the compression strategy. Strategy is one of + DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact + position where the strategy is changed, the same as for + SetLevel() applies. + + + The new compression strategy. + + + + + Deflates the current input block with to the given array. + + + The buffer where compressed data is stored + + + The number of compressed bytes added to the output, or 0 if either + IsNeedingInput() or IsFinished returns true or length is zero. + + + + + Deflates the current input block to the given array. + + + Buffer to store the compressed data. + + + Offset into the output array. + + + The maximum number of bytes that may be stored. + + + The number of compressed bytes added to the output, or 0 if either + needsInput() or finished() returns true or length is zero. + + + If Finish() was previously called. + + + If offset or length don't match the array length. + + + + + Sets the dictionary which should be used in the deflate process. + This call is equivalent to setDictionary(dict, 0, dict.Length). + + + the dictionary. + + + if SetInput () or Deflate () were already called or another dictionary was already set. + + + + + Sets the dictionary which should be used in the deflate process. + The dictionary is a byte array containing strings that are + likely to occur in the data which should be compressed. The + dictionary is not stored in the compressed output, only a + checksum. To decompress the output you need to supply the same + dictionary again. + + + The dictionary data + + + The index where dictionary information commences. + + + The number of bytes in the dictionary. + + + If SetInput () or Deflate() were already called or another dictionary was already set. + + + + + Compression level. + + + + + If true no Zlib/RFC1950 headers or footers are generated + + + + + The current state. + + + + + The total bytes of output written. + + + + + The pending output. + + + + + The deflater engine. + + + + + Gets the current adler checksum of the data that was processed so far. + + + + + Gets the number of input bytes processed so far. + + + + + Gets the number of output bytes so far. + + + + + Returns true if the stream was finished and no more output bytes + are available. + + + + + Returns true, if the input buffer is empty. + You should then call setInput(). + NOTE: This method can also return true when the stream + was finished. + + + + + The TarInputStream reads a UNIX tar archive as an InputStream. + methods are provided to position at each successive entry in + the archive, and the read each entry as a normal input stream + using read(). + + + + + Construct a TarInputStream with default block factor + + stream to source data from + + + + Construct a TarInputStream with user specified block factor + + stream to source data from + block factor to apply to archive + + + + Flushes the baseInputStream + + + + + Set the streams position. This operation is not supported and will throw a NotSupportedException + + The offset relative to the origin to seek to. + The to start seeking from. + The new position in the stream. + Any access + + + + Sets the length of the stream + This operation is not supported and will throw a NotSupportedException + + The new stream length. + Any access + + + + Writes a block of bytes to this stream using data from a buffer. + This operation is not supported and will throw a NotSupportedException + + The buffer containing bytes to write. + The offset in the buffer of the frist byte to write. + The number of bytes to write. + Any access + + + + Writes a byte to the current position in the file stream. + This operation is not supported and will throw a NotSupportedException + + The byte value to write. + Any access + + + + Reads a byte from the current tar archive entry. + + A byte cast to an int; -1 if the at the end of the stream. + + + + Reads bytes from the current tar archive entry. + + This method is aware of the boundaries of the current + entry in the archive and will deal with them appropriately + + + The buffer into which to place bytes read. + + + The offset at which to place bytes read. + + + The number of bytes to read. + + + The number of bytes read, or 0 at end of stream/EOF. + + + + + Closes this stream. Calls the TarBuffer's close() method. + The underlying stream is closed by the TarBuffer. + + + + + Set the entry factory for this instance. + + The factory for creating new entries + + + + Get the record size being used by this stream's TarBuffer. + + + TarBuffer record size. + + + + + Skip bytes in the input buffer. This skips bytes in the + current entry's data, not the entire archive, and will + stop at the end of the current entry's data if the number + to skip extends beyond that point. + + + The number of bytes to skip. + + + + + Since we do not support marking just yet, we do nothing. + + + The limit to mark. + + + + + Since we do not support marking just yet, we do nothing. + + + + + Get the next entry in this tar archive. This will skip + over any remaining data in the current entry, if there + is one, and place the input stream at the header of the + next entry, and read the header and instantiate a new + TarEntry from the header bytes and return that entry. + If there are no more entries in the archive, null will + be returned to indicate that the end of the archive has + been reached. + + + The next TarEntry in the archive, or null. + + + + + Copies the contents of the current tar archive entry directly into + an output stream. + + + The OutputStream into which to write the entry's data. + + + + + Flag set when last block has been read + + + + + Size of this entry as recorded in header + + + + + Number of bytes read for this entry so far + + + + + Buffer used with calls to Read() + + + + + Working buffer + + + + + Current entry being read + + + + + Factory used to create TarEntry or descendant class instance + + + + + Stream used as the source of input data. + + + + + Gets a value indicating whether the current stream supports reading + + + + + Gets a value indicating whether the current stream supports seeking + This property always returns false. + + + + + Gets a value indicating if the stream supports writing. + This property always returns false. + + + + + The length in bytes of the stream + + + + + Gets or sets the position within the stream. + Setting the Position is not supported and throws a NotSupportedExceptionNotSupportedException + + Any attempt to set position + + + + Get the record size being used by this stream's TarBuffer. + + + + + Get the available data that can be read from the current + entry in the archive. This does not indicate how much data + is left in the entire archive, only in the current entry. + This value is determined from the entry's size header field + and the amount of data already read from the current entry. + + + The number of available bytes for the current entry. + + + + + Return a value of true if marking is supported; false otherwise. + + Currently marking is not supported, the return value is always false. + + + + This interface is provided, along with the method , to allow + the programmer to have their own subclass instantiated for the + entries return from . + + + + + Create an entry based on name alone + + + Name of the new EntryPointNotFoundException to create + + created TarEntry or descendant class + + + + Create an instance based on an actual file + + + Name of file to represent in the entry + + + Created TarEntry or descendant class + + + + + Create a tar entry based on the header information passed + + + Buffer containing header information to base entry on + + + Created TarEntry or descendant class + + + + + Standard entry factory class creating instances of the class TarEntry + + + + + Create a based on named + + The name to use for the entry + A new + + + + Create a tar entry with details obtained from file + + The name of the file to retrieve details from. + A new + + + + Create an entry based on details in header + + The buffer containing entry details. + A new + + + + Defines known values for the property. + + + + + Host system = MSDOS + + + + + Host system = Amiga + + + + + Host system = Open VMS + + + + + Host system = Unix + + + + + Host system = VMCms + + + + + Host system = Atari ST + + + + + Host system = OS2 + + + + + Host system = Macintosh + + + + + Host system = ZSystem + + + + + Host system = Cpm + + + + + Host system = Windows NT + + + + + Host system = MVS + + + + + Host system = VSE + + + + + Host system = Acorn RISC + + + + + Host system = VFAT + + + + + Host system = Alternate MVS + + + + + Host system = BEOS + + + + + Host system = Tandem + + + + + Host system = OS400 + + + + + Host system = OSX + + + + + Host system = WinZIP AES + + + + + This class represents an entry in a zip archive. This can be a file + or a directory + ZipFile and ZipInputStream will give you instances of this class as + information about the members in an archive. ZipOutputStream + uses an instance of this class when creating an entry in a Zip file. +
+
Author of the original java version : Jochen Hoenicke +
+
+ + + Creates a zip entry with the given name. + + + The name for this entry. Can include directory components. + The convention for names is 'unix' style paths with relative names only. + There are with no device names and path elements are separated by '/' characters. + + + The name passed is null + + + + + Creates a zip entry with the given name and version required to extract + + + The name for this entry. Can include directory components. + The convention for names is 'unix' style paths with no device names and + path elements separated by '/' characters. This is not enforced see CleanName + on how to ensure names are valid if this is desired. + + + The minimum 'feature version' required this entry + + + The name passed is null + + + + + Initializes an entry with the given name and made by information + + Name for this entry + Version and HostSystem Information + Minimum required zip feature version required to extract this entry + Compression method for this entry. + + The name passed is null + + + versionRequiredToExtract should be 0 (auto-calculate) or > 10 + + + This constructor is used by the ZipFile class when reading from the central header + It is not generally useful, use the constructor specifying the name only. + + + + + Creates a deep copy of the given zip entry. + + + The entry to copy. + + + + + Test the external attributes for this to + see if the external attributes are Dos based (including WINNT and variants) + and match the values + + The attributes to test. + Returns true if the external attributes are known to be DOS/Windows + based and have the same attributes set as the value passed. + + + + Force this entry to be recorded using Zip64 extensions. + + + + + Get a value indicating wether Zip64 extensions were forced. + + A value of true if Zip64 extensions have been forced on; false if not. + + + + Process extra data fields updating the entry based on the contents. + + True if the extra data fields should be handled + for a local header, rather than for a central header. + + + + + Test entry to see if data can be extracted. + + Returns true if data can be extracted for this entry; false otherwise. + + + + Creates a copy of this zip entry. + + An that is a copy of the current instance. + + + + Gets a string representation of this ZipEntry. + + A readable textual representation of this + + + + Test a compression method to see if this library + supports extracting data compressed with that method + + The compression method to test. + Returns true if the compression method is supported; false otherwise + + + + Cleans a name making it conform to Zip file conventions. + Devices names ('c:\') and UNC share names ('\\server\share') are removed + and forward slashes ('\') are converted to back slashes ('/'). + Names are made relative by trimming leading slashes which is compatible + with the ZIP naming convention. + + The name to clean + The 'cleaned' name. + + The Zip name transform class is more flexible. + + + + + Get a value indicating wether the entry has a CRC value available. + + + + + Get/Set flag indicating if entry is encrypted. + A simple helper routine to aid interpretation of flags + + This is an assistant that interprets the flags property. + + + + Get / set a flag indicating wether entry name and comment text are + encoded in unicode UTF8. + + This is an assistant that interprets the flags property. + + + + Value used during password checking for PKZIP 2.0 / 'classic' encryption. + + + + + Get/Set general purpose bit flag for entry + + + General purpose bit flag
+
+ Bit 0: If set, indicates the file is encrypted
+ Bit 1-2 Only used for compression type 6 Imploding, and 8, 9 deflating
+ Imploding:
+ Bit 1 if set indicates an 8K sliding dictionary was used. If clear a 4k dictionary was used
+ Bit 2 if set indicates 3 Shannon-Fanno trees were used to encode the sliding dictionary, 2 otherwise
+
+ Deflating:
+ Bit 2 Bit 1
+ 0 0 Normal compression was used
+ 0 1 Maximum compression was used
+ 1 0 Fast compression was used
+ 1 1 Super fast compression was used
+
+ Bit 3: If set, the fields crc-32, compressed size + and uncompressed size are were not able to be written during zip file creation + The correct values are held in a data descriptor immediately following the compressed data.
+ Bit 4: Reserved for use by PKZIP for enhanced deflating
+ Bit 5: If set indicates the file contains compressed patch data
+ Bit 6: If set indicates strong encryption was used.
+ Bit 7-10: Unused or reserved
+ Bit 11: If set the name and comments for this entry are in unicode.
+ Bit 12-15: Unused or reserved
+
+ + +
+ + + Get/Set index of this entry in Zip file + + This is only valid when the entry is part of a + + + + Get/set offset for use in central header + + + + + Get/Set external file attributes as an integer. + The values of this are operating system dependant see + HostSystem for details + + + + + Get the version made by for this entry or zero if unknown. + The value / 10 indicates the major version number, and + the value mod 10 is the minor version number + + + + + Get a value indicating this entry is for a DOS/Windows system. + + + + + Gets the compatability information for the external file attribute + If the external file attributes are compatible with MS-DOS and can be read + by PKZIP for DOS version 2.04g then this value will be zero. Otherwise the value + will be non-zero and identify the host system on which the attributes are compatible. + + + + The values for this as defined in the Zip File format and by others are shown below. The values are somewhat + misleading in some cases as they are not all used as shown. You should consult the relevant documentation + to obtain up to date and correct information. The modified appnote by the infozip group is + particularly helpful as it documents a lot of peculiarities. The document is however a little dated. + + 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) + 1 - Amiga + 2 - OpenVMS + 3 - Unix + 4 - VM/CMS + 5 - Atari ST + 6 - OS/2 HPFS + 7 - Macintosh + 8 - Z-System + 9 - CP/M + 10 - Windows NTFS + 11 - MVS (OS/390 - Z/OS) + 12 - VSE + 13 - Acorn Risc + 14 - VFAT + 15 - Alternate MVS + 16 - BeOS + 17 - Tandem + 18 - OS/400 + 19 - OS/X (Darwin) + 99 - WinZip AES + remainder - unused + + + + + + Get minimum Zip feature version required to extract this entry + + + Minimum features are defined as:
+ 1.0 - Default value
+ 1.1 - File is a volume label
+ 2.0 - File is a folder/directory
+ 2.0 - File is compressed using Deflate compression
+ 2.0 - File is encrypted using traditional encryption
+ 2.1 - File is compressed using Deflate64
+ 2.5 - File is compressed using PKWARE DCL Implode
+ 2.7 - File is a patch data set
+ 4.5 - File uses Zip64 format extensions
+ 4.6 - File is compressed using BZIP2 compression
+ 5.0 - File is encrypted using DES
+ 5.0 - File is encrypted using 3DES
+ 5.0 - File is encrypted using original RC2 encryption
+ 5.0 - File is encrypted using RC4 encryption
+ 5.1 - File is encrypted using AES encryption
+ 5.1 - File is encrypted using corrected RC2 encryption
+ 5.1 - File is encrypted using corrected RC2-64 encryption
+ 6.1 - File is encrypted using non-OAEP key wrapping
+ 6.2 - Central directory encryption (not confirmed yet)
+ 6.3 - File is compressed using LZMA
+ 6.3 - File is compressed using PPMD+
+ 6.3 - File is encrypted using Blowfish
+ 6.3 - File is encrypted using Twofish
+
+ +
+ + + Get a value indicating wether this entry can be decompressed by the library. + + This is based on the and + wether the compression method is supported. + + + + Gets a value indicating if the entry requires Zip64 extensions + to store the full entry values. + + A value of true if a local header requires Zip64 extensions; false if not. + + + + Get a value indicating wether the central directory entry requires Zip64 extensions to be stored. + + + + + Get/Set DosTime value. + + + The MS-DOS date format can only represent dates between 1/1/1980 and 12/31/2107. + + + + + Gets/Sets the time of last modification of the entry. + + + The property is updated to match this as far as possible. + + + + + Returns the entry name. + + + The unix naming convention is followed. + Path components in the entry should always separated by forward slashes ('/'). + Dos device names like C: should also be removed. + See the class, or + + + + + Gets/Sets the size of the uncompressed data. + + + The size or -1 if unknown. + + Setting the size before adding an entry to an archive can help + avoid compatability problems with some archivers which dont understand Zip64 extensions. + + + + Gets/Sets the size of the compressed data. + + + The compressed entry size or -1 if unknown. + + + + + Gets/Sets the crc of the uncompressed data. + + + Crc is not in the range 0..0xffffffffL + + + The crc value or -1 if unknown. + + + + + Gets/Sets the compression method. Only Deflated and Stored are supported. + + + The compression method for this entry + + + + + + + Gets/Sets the extra data. + + + Extra data is longer than 64KB (0xffff) bytes. + + + Extra data or null if not set. + + + + + Gets/Sets the entry comment. + + + If comment is longer than 0xffff. + + + The comment or null if not set. + + + A comment is only available for entries when read via the class. + The class doesnt have the comment data available. + + + + + Gets a value indicating if the entry is a directory. + however. + + + A directory is determined by an entry name with a trailing slash '/'. + The external file attributes can also indicate an entry is for a directory. + Currently only dos/windows attributes are tested in this manner. + The trailing slash convention should always be followed. + + + + + Get a value of true if the entry appears to be a file; false otherwise + + + This only takes account of DOS/Windows attributes. Other operating systems are ignored. + For linux and others the result may be incorrect. + + + + + ExtraData tagged value interface. + + + + + Set the contents of this instance from the data passed. + + The data to extract contents from. + The offset to begin extracting data from. + The number of bytes to extract. + + + + Get the data representing this instance. + + Returns the data for this instance. + + + + Get the ID for this tagged data value. + + + + + A raw binary tagged value + + + + + Initialise a new instance. + + The tag ID. + + + + Set the data from the raw values provided. + + The raw data to extract values from. + The index to start extracting values from. + The number of bytes available. + + + + Get the binary data representing this instance. + + The raw binary data representing this instance. + + + + The tag ID for this instance. + + + + + Get the ID for this tagged data value. + + + + + Get /set the binary data representing this instance. + + The raw binary data representing this instance. + + + + Class representing extended unix date time values. + + + + + Set the data from the raw values provided. + + The raw data to extract values from. + The index to start extracting values from. + The number of bytes available. + + + + Get the binary data representing this instance. + + The raw binary data representing this instance. + + + + Test a value to see if is valid and can be represented here. + + The value to test. + Returns true if the value is valid and can be represented; false if not. + The standard Unix time is a signed integer data type, directly encoding the Unix time number, + which is the number of seconds since 1970-01-01. + Being 32 bits means the values here cover a range of about 136 years. + The minimum representable time is 1901-12-13 20:45:52, + and the maximum representable time is 2038-01-19 03:14:07. + + + + + Get the ID + + + + + Get /set the Modification Time + + + + + + + Get / set the Access Time + + + + + + + Get / Set the Create Time + + + + + + + Get/set the values to include. + + + + + Flags indicate which values are included in this instance. + + + + + The modification time is included + + + + + The access time is included + + + + + The create time is included. + + + + + Class handling NT date time values. + + + + + Set the data from the raw values provided. + + The raw data to extract values from. + The index to start extracting values from. + The number of bytes available. + + + + Get the binary data representing this instance. + + The raw binary data representing this instance. + + + + Test a valuie to see if is valid and can be represented here. + + The value to test. + Returns true if the value is valid and can be represented; false if not. + + NTFS filetimes are 64-bit unsigned integers, stored in Intel + (least significant byte first) byte order. They determine the + number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", + which is "01-Jan-1601 00:00:00 UTC". 28 May 60056 is the upper limit + + + + + Get the ID for this tagged data value. + + + + + Get/set the last modification time. + + + + + Get /set the create time + + + + + Get /set the last access time. + + + + + A factory that creates tagged data instances. + + + + + Get data for a specific tag value. + + The tag ID to find. + The data to search. + The offset to begin extracting data from. + The number of bytes to extract. + The located value found, or null if not found. + + + + + A class to handle the extra data field for Zip entries + + + Extra data contains 0 or more values each prefixed by a header tag and length. + They contain zero or more bytes of actual data. + The data is held internally using a copy on write strategy. This is more efficient but + means that for extra data created by passing in data can have the values modified by the caller + in some circumstances. + + + + + Initialise a default instance. + + + + + Initialise with known extra data. + + The extra data. + + + + Get the raw extra data value + + Returns the raw byte[] extra data this instance represents. + + + + Clear the stored data. + + + + + Get a read-only for the associated tag. + + The tag to locate data for. + Returns a containing tag data or null if no tag was found. + + + + Get the tagged data for a tag. + + The tag to search for. + Returns a tagged value or null if none found. + + + + Find an extra data value + + The identifier for the value to find. + Returns true if the value was found; false otherwise. + + + + Add a new entry to extra data. + + The value to add. + + + + Add a new entry to extra data + + The ID for this entry. + The data to add. + If the ID already exists its contents are replaced. + + + + Start adding a new entry. + + Add data using , , , or . + The new entry is completed and actually added by calling + + + + + Add entry data added since using the ID passed. + + The identifier to use for this entry. + + + + Add a byte of data to the pending new entry. + + The byte to add. + + + + + Add data to a pending new entry. + + The data to add. + + + + + Add a short value in little endian order to the pending new entry. + + The data to add. + + + + + Add an integer value in little endian order to the pending new entry. + + The data to add. + + + + + Add a long value in little endian order to the pending new entry. + + The data to add. + + + + + Delete an extra data field. + + The identifier of the field to delete. + Returns true if the field was found and deleted. + + + + Read a long in little endian form from the last found data value + + Returns the long value read. + + + + Read an integer in little endian form from the last found data value. + + Returns the integer read. + + + + Read a short value in little endian form from the last found data value. + + Returns the short value read. + + + + Read a byte from an extra data + + The byte value read or -1 if the end of data has been reached. + + + + Skip data during reading. + + The number of bytes to skip. + + + + Internal form of that reads data at any location. + + Returns the short value read. + + + + Dispose of this instance. + + + + + Gets the current extra data length. + + + + + Get the length of the last value found by + + This is only value if has previsouly returned true. + + + + Get the index for the current read value. + + This is only valid if has previously returned true. + Initially it will be the index of the first byte of actual data. The value is updated after calls to + , and . + + + + Get the number of bytes remaining to be read for the current value; + + + + + Holds data pertinent to a data descriptor. + + + + + Get /set the compressed size of data. + + + + + Get / set the uncompressed size of data + + + + + Get /set the crc value. + + + + + This class assists with writing/reading from Zip files. + + + + + Initialise an instance of this class. + + The name of the file to open. + + + + Initialise a new instance of . + + The stream to use. + + + + Close the stream. + + + The underlying stream is closed only if is true. + + + + + Locates a block with the desired . + + The signature to find. + Location, marking the end of block. + Minimum size of the block. + The maximum variable data. + Eeturns the offset of the first byte after the signature; -1 if not found + + + + Write Zip64 end of central directory records (File header and locator). + + The number of entries in the central directory. + The size of entries in the central directory. + The offset of the dentral directory. + + + + Write the required records to end the central directory. + + The number of entries in the directory. + The size of the entries in the directory. + The start of the central directory. + The archive comment. (This can be null). + + + + Read an unsigned short in little endian byte order. + + Returns the value read. + + An i/o error occurs. + + + The file ends prematurely + + + + + Read an int in little endian byte order. + + Returns the value read. + + An i/o error occurs. + + + The file ends prematurely + + + + + Read a long in little endian byte order. + + The value read. + + + + Write an unsigned short in little endian byte order. + + The value to write. + + + + Write a ushort in little endian byte order. + + The value to write. + + + + Write an int in little endian byte order. + + The value to write. + + + + Write a uint in little endian byte order. + + The value to write. + + + + Write a long in little endian byte order. + + The value to write. + + + + Write a ulong in little endian byte order. + + The value to write. + + + + Write a data descriptor. + + The entry to write a descriptor for. + Returns the number of descriptor bytes written. + + + + Read data descriptor at the end of compressed data. + + if set to true [zip64]. + The data to fill in. + Returns the number of bytes read in the descriptor. + + + + Get / set a value indicating wether the the underlying stream is owned or not. + + If the stream is owned it is closed when this instance is closed. + + + + Inflater is used to decompress data that has been compressed according + to the "deflate" standard described in rfc1951. + + By default Zlib (rfc1950) headers and footers are expected in the input. + You can use constructor public Inflater(bool noHeader) passing true + if there is no Zlib header information + + The usage is as following. First you have to set some input with + SetInput(), then Inflate() it. If inflate doesn't + inflate any bytes there may be three reasons: +
    +
  • IsNeedingInput() returns true because the input buffer is empty. + You have to provide more input with SetInput(). + NOTE: IsNeedingInput() also returns true when, the stream is finished. +
  • +
  • IsNeedingDictionary() returns true, you have to provide a preset + dictionary with SetDictionary().
  • +
  • IsFinished returns true, the inflater has finished.
  • +
+ Once the first output byte is produced, a dictionary will not be + needed at a later stage. + + author of the original java version : John Leuner, Jochen Hoenicke +
+
+ + + These are the possible states for an inflater + + + + + Copy lengths for literal codes 257..285 + + + + + Extra bits for literal codes 257..285 + + + + + Copy offsets for distance codes 0..29 + + + + + Extra bits for distance codes + + + + + This variable contains the current state. + + + + + The adler checksum of the dictionary or of the decompressed + stream, as it is written in the header resp. footer of the + compressed stream. + Only valid if mode is DECODE_DICT or DECODE_CHKSUM. + + + + + The number of bits needed to complete the current state. This + is valid, if mode is DECODE_DICT, DECODE_CHKSUM, + DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. + + + + + True, if the last block flag was set in the last block of the + inflated stream. This means that the stream ends after the + current block. + + + + + The total number of inflated bytes. + + + + + The total number of bytes set with setInput(). This is not the + value returned by the TotalIn property, since this also includes the + unprocessed input. + + + + + This variable stores the noHeader flag that was given to the constructor. + True means, that the inflated stream doesn't contain a Zlib header or + footer. + + + + + Creates a new inflater or RFC1951 decompressor + RFC1950/Zlib headers and footers will be expected in the input data + + + + + Creates a new inflater. + + + True if no RFC1950/Zlib header and footer fields are expected in the input data + + This is used for GZIPed/Zipped input. + + For compatibility with + Sun JDK you should provide one byte of input more than needed in + this case. + + + + + Resets the inflater so that a new stream can be decompressed. All + pending input and output will be discarded. + + + + + Decodes a zlib/RFC1950 header. + + + False if more input is needed. + + + The header is invalid. + + + + + Decodes the dictionary checksum after the deflate header. + + + False if more input is needed. + + + + + Decodes the huffman encoded symbols in the input stream. + + + false if more input is needed, true if output window is + full or the current block ends. + + + if deflated stream is invalid. + + + + + Decodes the adler checksum after the deflate stream. + + + false if more input is needed. + + + If checksum doesn't match. + + + + + Decodes the deflated stream. + + + false if more input is needed, or if finished. + + + if deflated stream is invalid. + + + + + Sets the preset dictionary. This should only be called, if + needsDictionary() returns true and it should set the same + dictionary, that was used for deflating. The getAdler() + function returns the checksum of the dictionary needed. + + + The dictionary. + + + + + Sets the preset dictionary. This should only be called, if + needsDictionary() returns true and it should set the same + dictionary, that was used for deflating. The getAdler() + function returns the checksum of the dictionary needed. + + + The dictionary. + + + The index into buffer where the dictionary starts. + + + The number of bytes in the dictionary. + + + No dictionary is needed. + + + The adler checksum for the buffer is invalid + + + + + Sets the input. This should only be called, if needsInput() + returns true. + + + the input. + + + + + Sets the input. This should only be called, if needsInput() + returns true. + + + The source of input data + + + The index into buffer where the input starts. + + + The number of bytes of input to use. + + + No input is needed. + + + The index and/or count are wrong. + + + + + Inflates the compressed stream to the output buffer. If this + returns 0, you should check, whether IsNeedingDictionary(), + IsNeedingInput() or IsFinished() returns true, to determine why no + further output is produced. + + + the output buffer. + + + The number of bytes written to the buffer, 0 if no further + output can be produced. + + + if buffer has length 0. + + + if deflated stream is invalid. + + + + + Inflates the compressed stream to the output buffer. If this + returns 0, you should check, whether needsDictionary(), + needsInput() or finished() returns true, to determine why no + further output is produced. + + + the output buffer. + + + the offset in buffer where storing starts. + + + the maximum number of bytes to output. + + + the number of bytes written to the buffer, 0 if no further output can be produced. + + + if count is less than 0. + + + if the index and / or count are wrong. + + + if deflated stream is invalid. + + + + + Returns true, if the input buffer is empty. + You should then call setInput(). + NOTE: This method also returns true when the stream is finished. + + + + + Returns true, if a preset dictionary is needed to inflate the input. + + + + + Returns true, if the inflater has finished. This means, that no + input is needed and no output can be produced. + + + + + Gets the adler checksum. This is either the checksum of all + uncompressed bytes returned by inflate(), or if needsDictionary() + returns true (and thus no output was yet produced) this is the + adler checksum of the expected dictionary. + + + the adler checksum. + + + + + Gets the total number of output bytes returned by Inflate(). + + + the total number of output bytes. + + + + + Gets the total number of processed compressed input bytes. + + + The total number of bytes of processed input bytes. + + + + + Gets the number of unprocessed input bytes. Useful, if the end of the + stream is reached and you want to further process the bytes after + the deflate stream. + + + The number of bytes of the input which have not been processed. + + + + + An input stream that decompresses files in the BZip2 format + + + + + Construct instance for reading from stream + + Data source + + + + Flushes the stream. + + + + + Set the streams position. This operation is not supported and will throw a NotSupportedException + + A byte offset relative to the parameter. + A value of type indicating the reference point used to obtain the new position. + The new position of the stream. + Any access + + + + Sets the length of this stream to the given value. + This operation is not supported and will throw a NotSupportedExceptionortedException + + The new length for the stream. + Any access + + + + Writes a block of bytes to this stream using data from a buffer. + This operation is not supported and will throw a NotSupportedException + + The buffer to source data from. + The offset to start obtaining data from. + The number of bytes of data to write. + Any access + + + + Writes a byte to the current position in the file stream. + This operation is not supported and will throw a NotSupportedException + + The value to write. + Any access + + + + Read a sequence of bytes and advances the read position by one byte. + + Array of bytes to store values in + Offset in array to begin storing data + The maximum number of bytes to read + The total number of bytes read into the buffer. This might be less + than the number of bytes requested if that number of bytes are not + currently available or zero if the end of the stream is reached. + + + + + Closes the stream, releasing any associated resources. + + + + + Read a byte from stream advancing position + + byte read or -1 on end of stream + + + + Get/set flag indicating ownership of underlying stream. + When the flag is true will close the underlying stream also. + + + + + Gets a value indicating if the stream supports reading + + + + + Gets a value indicating whether the current stream supports seeking. + + + + + Gets a value indicating whether the current stream supports writing. + This property always returns false + + + + + Gets the length in bytes of the stream. + + + + + Gets or sets the streams position. + Setting the position is not supported and will throw a NotSupportException + + Any attempt to set the position + + + + Computes Adler32 checksum for a stream of data. An Adler32 + checksum is not as reliable as a CRC32 checksum, but a lot faster to + compute. + + The specification for Adler32 may be found in RFC 1950. + ZLIB Compressed Data Format Specification version 3.3) + + + From that document: + + "ADLER32 (Adler-32 checksum) + This contains a checksum value of the uncompressed data + (excluding any dictionary data) computed according to Adler-32 + algorithm. This algorithm is a 32-bit extension and improvement + of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 + standard. + + Adler-32 is composed of two sums accumulated per byte: s1 is + the sum of all bytes, s2 is the sum of all s1 values. Both sums + are done modulo 65521. s1 is initialized to 1, s2 to zero. The + Adler-32 checksum is stored as s2*65536 + s1 in most- + significant-byte first (network) order." + + "8.2. The Adler-32 algorithm + + The Adler-32 algorithm is much faster than the CRC32 algorithm yet + still provides an extremely low probability of undetected errors. + + The modulo on unsigned long accumulators can be delayed for 5552 + bytes, so the modulo operation time is negligible. If the bytes + are a, b, c, the second sum is 3a + 2b + c + 3, and so is position + and order sensitive, unlike the first sum, which is just a + checksum. That 65521 is prime is important to avoid a possible + large class of two-byte errors that leave the check unchanged. + (The Fletcher checksum uses 255, which is not prime and which also + makes the Fletcher check insensitive to single byte changes 0 - + 255.) + + The sum s1 is initialized to 1 instead of zero to make the length + of the sequence part of s2, so that the length does not have to be + checked separately. (Any sequence of zeroes has a Fletcher + checksum of zero.)" + + + + + + + largest prime smaller than 65536 + + + + + Creates a new instance of the Adler32 class. + The checksum starts off with a value of 1. + + + + + Resets the Adler32 checksum to the initial value. + + + + + Updates the checksum with a byte value. + + + The data value to add. The high byte of the int is ignored. + + + + + Updates the checksum with an array of bytes. + + + The source of the data to update with. + + + + + Updates the checksum with the bytes taken from the array. + + + an array of bytes + + + the start of the data used for this update + + + the number of bytes to use for this update + + + + + Returns the Adler32 data checksum computed so far. + + +
+
diff --git a/bin/hdfsdll.dll.config b/bin/hdfsdll.dll.config new file mode 100644 index 0000000..f1805fd --- /dev/null +++ b/bin/hdfsdll.dll.config @@ -0,0 +1,3 @@ + + + diff --git a/bin/hdfsdll.so b/bin/hdfsdll.so new file mode 100755 index 0000000..cf79ffc Binary files /dev/null and b/bin/hdfsdll.so differ diff --git a/bin/xmrhelpers.so b/bin/xmrhelpers.so new file mode 100755 index 0000000..6074da2 Binary files /dev/null and b/bin/xmrhelpers.so differ -- cgit v1.1 From 4f80d75bf3fa6de226203c6752e7a8e53fda8108 Mon Sep 17 00:00:00 2001 From: Tom Date: Sat, 7 Aug 2010 06:28:04 -0700 Subject: Add a CHANGED_POSITION event so scripts don't have to run expensive loops to check for position changes --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1 + OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 4 +++- OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 8ce79a2..cac3df6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -476,6 +476,7 @@ namespace OpenSim.Region.Framework.Scenes part.IgnoreUndoUpdate = false; part.StoreUndoState(UndoType.STATE_GROUP_POSITION); part.GroupPosition = val; + part.TriggerScriptChangedEvent(Changed.POSITION); } foreach (ScenePresence av in m_linkedAvatars) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index efdc19c..d544619 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -60,7 +60,8 @@ namespace OpenSim.Region.Framework.Scenes TELEPORT = 512, REGION_RESTART = 1024, MEDIA = 2048, - ANIMATION = 16384 + ANIMATION = 16384, + POSITION = 32768 } // I don't really know where to put this except here. @@ -730,6 +731,7 @@ namespace OpenSim.Region.Framework.Scenes } } } + TriggerScriptChangedEvent(Changed.POSITION); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 5da6bb9..6e8435d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -279,6 +279,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int CHANGED_REGION_START = 1024; //LL Changed the constant from CHANGED_REGION_RESTART public const int CHANGED_MEDIA = 2048; public const int CHANGED_ANIMATION = 16384; + public const int CHANGED_POSITION = 32768; public const int TYPE_INVALID = 0; public const int TYPE_INTEGER = 1; public const int TYPE_FLOAT = 2; -- cgit v1.1 From 00cc42a607c59add54af3c1113162576e6109e41 Mon Sep 17 00:00:00 2001 From: sacha Date: Sat, 7 Aug 2010 13:40:38 +0000 Subject: and another endless debug cleaning --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 8ce79a2..0dc63ef 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1734,9 +1734,9 @@ namespace OpenSim.Region.Framework.Scenes // don't backup while it's selected or you're asking for changes mid stream. if ((isTimeToPersist()) || (forcedBackup)) { - m_log.DebugFormat( - "[SCENE]: Storing {0}, {1} in {2}", - Name, UUID, m_scene.RegionInfo.RegionName); + // m_log.DebugFormat( + // "[SCENE]: Storing {0}, {1} in {2}", + // Name, UUID, m_scene.RegionInfo.RegionName); SceneObjectGroup backup_group = Copy(false); backup_group.RootPart.Velocity = RootPart.Velocity; -- cgit v1.1 From b017d985ab05044bf196f108516e6b0185c172f5 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 08:06:41 -0700 Subject: Add some nullref checks to the UnackedPacketCollection. --- .../LindenUDP/UnackedPacketCollection.cs | 353 +++++++++++---------- 1 file changed, 184 insertions(+), 169 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index e43f7cf..c120a12 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs @@ -1,169 +1,184 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using OpenMetaverse; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - /// - /// Special collection that is optimized for tracking unacknowledged packets - /// - public sealed class UnackedPacketCollection - { - /// - /// Holds information about a pending acknowledgement - /// - private struct PendingAck - { - /// Sequence number of the packet to remove - public uint SequenceNumber; - /// Environment.TickCount value when the remove was queued. - /// This is used to update round-trip times for packets - public int RemoveTime; - /// Whether or not this acknowledgement was attached to a - /// resent packet. If so, round-trip time will not be calculated - public bool FromResend; - - public PendingAck(uint sequenceNumber, int currentTime, bool fromResend) - { - SequenceNumber = sequenceNumber; - RemoveTime = currentTime; - FromResend = fromResend; - } - } - - /// Holds the actual unacked packet data, sorted by sequence number - private Dictionary m_packets = new Dictionary(); - /// Holds packets that need to be added to the unacknowledged list - private LocklessQueue m_pendingAdds = new LocklessQueue(); - /// Holds information about pending acknowledgements - private LocklessQueue m_pendingRemoves = new LocklessQueue(); - - /// - /// Add an unacked packet to the collection - /// - /// Packet that is awaiting acknowledgement - /// True if the packet was successfully added, false if the - /// packet already existed in the collection - /// This does not immediately add the ACK to the collection, - /// it only queues it so it can be added in a thread-safe way later - public void Add(OutgoingPacket packet) - { - m_pendingAdds.Enqueue(packet); - } - - /// - /// Marks a packet as acknowledged - /// - /// Sequence number of the packet to - /// acknowledge - /// Current value of Environment.TickCount - /// This does not immediately acknowledge the packet, it only - /// queues the ack so it can be handled in a thread-safe way later - public void Remove(uint sequenceNumber, int currentTime, bool fromResend) - { - m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); - } - - /// - /// Returns a list of all of the packets with a TickCount older than - /// the specified timeout - /// - /// Number of ticks (milliseconds) before a - /// packet is considered expired - /// A list of all expired packets according to the given - /// expiration timeout - /// This function is not thread safe, and cannot be called - /// multiple times concurrently - public List GetExpiredPackets(int timeoutMS) - { - ProcessQueues(); - - List expiredPackets = null; - - if (m_packets.Count > 0) - { - int now = Environment.TickCount & Int32.MaxValue; - - foreach (OutgoingPacket packet in m_packets.Values) - { - // TickCount of zero means a packet is in the resend queue - // but hasn't actually been sent over the wire yet - if (packet.TickCount == 0) - continue; - - if (now - packet.TickCount >= timeoutMS) - { - if (expiredPackets == null) - expiredPackets = new List(); - - // The TickCount will be set to the current time when the packet - // is actually sent out again - packet.TickCount = 0; - - expiredPackets.Add(packet); - } - } - } - - return expiredPackets; - } - - private void ProcessQueues() - { - // Process all the pending adds - OutgoingPacket pendingAdd; - while (m_pendingAdds.Dequeue(out pendingAdd)) - m_packets[pendingAdd.SequenceNumber] = pendingAdd; - - // Process all the pending removes, including updating statistics and round-trip times - PendingAck pendingRemove; - OutgoingPacket ackedPacket; - while (m_pendingRemoves.Dequeue(out pendingRemove)) - { - if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) - { - m_packets.Remove(pendingRemove.SequenceNumber); - - // Update stats - System.Threading.Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); - - if (!pendingRemove.FromResend) - { - // Calculate the round-trip time for this packet and its ACK - int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; - if (rtt > 0) - ackedPacket.Client.UpdateRoundTrip(rtt); - } - } - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Net; +using OpenMetaverse; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + /// + /// Special collection that is optimized for tracking unacknowledged packets + /// + public sealed class UnackedPacketCollection + { + /// + /// Holds information about a pending acknowledgement + /// + private struct PendingAck + { + /// Sequence number of the packet to remove + public uint SequenceNumber; + /// Environment.TickCount value when the remove was queued. + /// This is used to update round-trip times for packets + public int RemoveTime; + /// Whether or not this acknowledgement was attached to a + /// resent packet. If so, round-trip time will not be calculated + public bool FromResend; + + public PendingAck(uint sequenceNumber, int currentTime, bool fromResend) + { + SequenceNumber = sequenceNumber; + RemoveTime = currentTime; + FromResend = fromResend; + } + } + + /// Holds the actual unacked packet data, sorted by sequence number + private Dictionary m_packets = new Dictionary(); + /// Holds packets that need to be added to the unacknowledged list + private LocklessQueue m_pendingAdds = new LocklessQueue(); + /// Holds information about pending acknowledgements + private LocklessQueue m_pendingRemoves = new LocklessQueue(); + + /// + /// Add an unacked packet to the collection + /// + /// Packet that is awaiting acknowledgement + /// True if the packet was successfully added, false if the + /// packet already existed in the collection + /// This does not immediately add the ACK to the collection, + /// it only queues it so it can be added in a thread-safe way later + public void Add(OutgoingPacket packet) + { + m_pendingAdds.Enqueue(packet); + } + + /// + /// Marks a packet as acknowledged + /// + /// Sequence number of the packet to + /// acknowledge + /// Current value of Environment.TickCount + /// This does not immediately acknowledge the packet, it only + /// queues the ack so it can be handled in a thread-safe way later + public void Remove(uint sequenceNumber, int currentTime, bool fromResend) + { + m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); + } + + /// + /// Returns a list of all of the packets with a TickCount older than + /// the specified timeout + /// + /// Number of ticks (milliseconds) before a + /// packet is considered expired + /// A list of all expired packets according to the given + /// expiration timeout + /// This function is not thread safe, and cannot be called + /// multiple times concurrently + public List GetExpiredPackets(int timeoutMS) + { + ProcessQueues(); + + List expiredPackets = null; + + if (m_packets.Count > 0) + { + int now = Environment.TickCount & Int32.MaxValue; + + foreach (OutgoingPacket packet in m_packets.Values) + { + // TickCount of zero means a packet is in the resend queue + // but hasn't actually been sent over the wire yet + if (packet.TickCount == 0) + continue; + + if (now - packet.TickCount >= timeoutMS) + { + if (expiredPackets == null) + expiredPackets = new List(); + + // The TickCount will be set to the current time when the packet + // is actually sent out again + packet.TickCount = 0; + + expiredPackets.Add(packet); + } + } + } + + return expiredPackets; + } + + private void ProcessQueues() + { + // Process all the pending adds + + OutgoingPacket pendingAdd; + if (m_pendingAdds != null) + { + while (m_pendingAdds.Dequeue(out pendingAdd)) + { + if (pendingAdd != null && m_packets != null) + { + m_packets[pendingAdd.SequenceNumber] = pendingAdd; + } + } + } + + // Process all the pending removes, including updating statistics and round-trip times + PendingAck pendingRemove; + OutgoingPacket ackedPacket; + if (m_pendingRemoves != null) + { + while (m_pendingRemoves.Dequeue(out pendingRemove)) + { + if (m_pendingRemoves != null && m_packets != null) + { + if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) + { + m_packets.Remove(pendingRemove.SequenceNumber); + + // Update stats + System.Threading.Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); + + if (!pendingRemove.FromResend) + { + // Calculate the round-trip time for this packet and its ACK + int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; + if (rtt > 0) + ackedPacket.Client.UpdateRoundTrip(rtt); + } + } + } + } + } + } + } +} -- cgit v1.1 From 19debab060b246f61d633b06d926a068001f6510 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 08:17:11 -0700 Subject: Fix the general alert message so it doesn't get sent to child agents --- .../CoreModules/Avatar/Dialog/DialogModule.cs | 443 +++++++++++---------- 1 file changed, 223 insertions(+), 220 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index fb0bd1a..1498dba 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -1,220 +1,223 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenSim.Framework; - -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; - -namespace OpenSim.Region.CoreModules.Avatar.Dialog -{ - public class DialogModule : IRegionModule, IDialogModule - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected Scene m_scene; - - public void Initialise(Scene scene, IConfigSource source) - { - m_scene = scene; - m_scene.RegisterModuleInterface(this); - - m_scene.AddCommand( - this, "alert", "alert ", "Send an alert to a user", HandleAlertConsoleCommand); - - m_scene.AddCommand( - this, "alert general", "alert general ", "Send an alert to everyone", HandleAlertConsoleCommand); - - m_scene.AddCommand( - this, "alert dialog", "alert dialog ", "Send a dialog alert to everyone", HandleAlertConsoleCommand); - - - } - - public void PostInitialise() {} - public void Close() {} - public string Name { get { return "Dialog Module"; } } - public bool IsSharedModule { get { return false; } } - - public void SendAlertToUser(IClientAPI client, string message) - { - SendAlertToUser(client, message, false); - } - - public void SendAlertToUser(IClientAPI client, string message, bool modal) - { - client.SendAgentAlertMessage(message, modal); - } - - public void SendAlertToUser(UUID agentID, string message) - { - SendAlertToUser(agentID, message, false); - } - - public void SendAlertToUser(UUID agentID, string message, bool modal) - { - ScenePresence sp = m_scene.GetScenePresence(agentID); - - if (sp != null) - sp.ControllingClient.SendAgentAlertMessage(message, modal); - } - - public void SendAlertToUser(string firstName, string lastName, string message, bool modal) - { - ScenePresence presence = m_scene.GetScenePresence(firstName, lastName); - if (presence != null) - presence.ControllingClient.SendAgentAlertMessage(message, modal); - } - - public void SendGeneralAlert(string message) - { - m_scene.ForEachScenePresence(delegate(ScenePresence presence) - { - presence.ControllingClient.SendAlertMessage(message); - }); - } - - public void SendDialogToUser( - UUID avatarID, string objectName, UUID objectID, UUID ownerID, - string message, UUID textureID, int ch, string[] buttonlabels) - { - UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, ownerID); - string ownerFirstName, ownerLastName; - if (account != null) - { - ownerFirstName = account.FirstName; - ownerLastName = account.LastName; - } - else - { - ownerFirstName = "(unknown"; - ownerLastName = "user)"; - } - - ScenePresence sp = m_scene.GetScenePresence(avatarID); - if (sp != null) - sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); - } - - public void SendUrlToUser( - UUID avatarID, string objectName, UUID objectID, UUID ownerID, bool groupOwned, string message, string url) - { - ScenePresence sp = m_scene.GetScenePresence(avatarID); - - if (sp != null) - sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); - } - - public void SendTextBoxToUser(UUID avatarid, string message, int chatChannel, string name, UUID objectid, UUID ownerid) - { - UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, ownerid); - string ownerFirstName, ownerLastName; - if (account != null) - { - ownerFirstName = account.FirstName; - ownerLastName = account.LastName; - } - else - { - ownerFirstName = "(unknown"; - ownerLastName = "user)"; - } - - ScenePresence sp = m_scene.GetScenePresence(avatarid); - - if (sp != null) - sp.ControllingClient.SendTextBoxRequest(message, chatChannel, name, ownerFirstName, ownerLastName, objectid); - } - - public void SendNotificationToUsersInRegion( - UUID fromAvatarID, string fromAvatarName, string message) - { - m_scene.ForEachScenePresence(delegate(ScenePresence presence) - { - if (!presence.IsChildAgent) - presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message); - }); - } - - /// - /// Handle an alert command from the console. - /// - /// - /// - public void HandleAlertConsoleCommand(string module, string[] cmdparams) - { - if (m_scene.ConsoleScene() != null && m_scene.ConsoleScene() != m_scene) - return; - - if (cmdparams[1] == "general") - { - string message = CombineParams(cmdparams, 2); - - m_log.InfoFormat( - "[DIALOG]: Sending general alert in region {0} with message {1}", m_scene.RegionInfo.RegionName, message); - SendGeneralAlert(message); - } - else if (cmdparams[1] == "dialog") - { - string message = CombineParams(cmdparams, 2); - - m_log.InfoFormat( - "[DIALOG]: Sending dialog alert in region {0} with message {1}", m_scene.RegionInfo.RegionName, message); - SendNotificationToUsersInRegion(UUID.Zero, "System", message); - } - else - { - string firstName = cmdparams[1]; - string lastName = cmdparams[2]; - string message = CombineParams(cmdparams, 3); - - m_log.InfoFormat( - "[DIALOG]: Sending alert in region {0} to {1} {2} with message {3}", - m_scene.RegionInfo.RegionName, firstName, lastName, message); - SendAlertToUser(firstName, lastName, message, false); - } - } - - private string CombineParams(string[] commandParams, int pos) - { - string result = string.Empty; - for (int i = pos; i < commandParams.Length; i++) - { - result += commandParams[i] + " "; - } - - return result; - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; + +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.CoreModules.Avatar.Dialog +{ + public class DialogModule : IRegionModule, IDialogModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + + public void Initialise(Scene scene, IConfigSource source) + { + m_scene = scene; + m_scene.RegisterModuleInterface(this); + + m_scene.AddCommand( + this, "alert", "alert ", "Send an alert to a user", HandleAlertConsoleCommand); + + m_scene.AddCommand( + this, "alert general", "alert general ", "Send an alert to everyone", HandleAlertConsoleCommand); + + m_scene.AddCommand( + this, "alert dialog", "alert dialog ", "Send a dialog alert to everyone", HandleAlertConsoleCommand); + + + } + + public void PostInitialise() {} + public void Close() {} + public string Name { get { return "Dialog Module"; } } + public bool IsSharedModule { get { return false; } } + + public void SendAlertToUser(IClientAPI client, string message) + { + SendAlertToUser(client, message, false); + } + + public void SendAlertToUser(IClientAPI client, string message, bool modal) + { + client.SendAgentAlertMessage(message, modal); + } + + public void SendAlertToUser(UUID agentID, string message) + { + SendAlertToUser(agentID, message, false); + } + + public void SendAlertToUser(UUID agentID, string message, bool modal) + { + ScenePresence sp = m_scene.GetScenePresence(agentID); + + if (sp != null) + sp.ControllingClient.SendAgentAlertMessage(message, modal); + } + + public void SendAlertToUser(string firstName, string lastName, string message, bool modal) + { + ScenePresence presence = m_scene.GetScenePresence(firstName, lastName); + if (presence != null) + presence.ControllingClient.SendAgentAlertMessage(message, modal); + } + + public void SendGeneralAlert(string message) + { + m_scene.ForEachScenePresence(delegate(ScenePresence presence) + { + if (!presence.IsChildAgent) + { + presence.ControllingClient.SendAlertMessage(message); + } + }); + } + + public void SendDialogToUser( + UUID avatarID, string objectName, UUID objectID, UUID ownerID, + string message, UUID textureID, int ch, string[] buttonlabels) + { + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, ownerID); + string ownerFirstName, ownerLastName; + if (account != null) + { + ownerFirstName = account.FirstName; + ownerLastName = account.LastName; + } + else + { + ownerFirstName = "(unknown"; + ownerLastName = "user)"; + } + + ScenePresence sp = m_scene.GetScenePresence(avatarID); + if (sp != null) + sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); + } + + public void SendUrlToUser( + UUID avatarID, string objectName, UUID objectID, UUID ownerID, bool groupOwned, string message, string url) + { + ScenePresence sp = m_scene.GetScenePresence(avatarID); + + if (sp != null) + sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); + } + + public void SendTextBoxToUser(UUID avatarid, string message, int chatChannel, string name, UUID objectid, UUID ownerid) + { + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, ownerid); + string ownerFirstName, ownerLastName; + if (account != null) + { + ownerFirstName = account.FirstName; + ownerLastName = account.LastName; + } + else + { + ownerFirstName = "(unknown"; + ownerLastName = "user)"; + } + + ScenePresence sp = m_scene.GetScenePresence(avatarid); + + if (sp != null) + sp.ControllingClient.SendTextBoxRequest(message, chatChannel, name, ownerFirstName, ownerLastName, objectid); + } + + public void SendNotificationToUsersInRegion( + UUID fromAvatarID, string fromAvatarName, string message) + { + m_scene.ForEachScenePresence(delegate(ScenePresence presence) + { + if (!presence.IsChildAgent) + presence.ControllingClient.SendBlueBoxMessage(fromAvatarID, fromAvatarName, message); + }); + } + + /// + /// Handle an alert command from the console. + /// + /// + /// + public void HandleAlertConsoleCommand(string module, string[] cmdparams) + { + if (m_scene.ConsoleScene() != null && m_scene.ConsoleScene() != m_scene) + return; + + if (cmdparams[1] == "general") + { + string message = CombineParams(cmdparams, 2); + + m_log.InfoFormat( + "[DIALOG]: Sending general alert in region {0} with message {1}", m_scene.RegionInfo.RegionName, message); + SendGeneralAlert(message); + } + else if (cmdparams[1] == "dialog") + { + string message = CombineParams(cmdparams, 2); + + m_log.InfoFormat( + "[DIALOG]: Sending dialog alert in region {0} with message {1}", m_scene.RegionInfo.RegionName, message); + SendNotificationToUsersInRegion(UUID.Zero, "System", message); + } + else + { + string firstName = cmdparams[1]; + string lastName = cmdparams[2]; + string message = CombineParams(cmdparams, 3); + + m_log.InfoFormat( + "[DIALOG]: Sending alert in region {0} to {1} {2} with message {3}", + m_scene.RegionInfo.RegionName, firstName, lastName, message); + SendAlertToUser(firstName, lastName, message, false); + } + } + + private string CombineParams(string[] commandParams, int pos) + { + string result = string.Empty; + for (int i = pos; i < commandParams.Length; i++) + { + result += commandParams[i] + " "; + } + + return result; + } + } +} -- cgit v1.1 From 413b0525db81ebc39a3a79cc2763553058056a5c Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 11:06:07 -0700 Subject: It seems hippo disregards velocities in full updates, so also send a terse update when an agent sits to avoid drifting off --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 8656 +++++++++++----------- 1 file changed, 4328 insertions(+), 4328 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b3fa2f4..882f4a7 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1,4328 +1,4328 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Xml; -using System.Collections.Generic; -using System.Reflection; -using System.Timers; -using OpenMetaverse; -using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Client; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes.Animation; -using OpenSim.Region.Framework.Scenes.Types; -using OpenSim.Region.Physics.Manager; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; -using OpenSim.Services.Interfaces; - -namespace OpenSim.Region.Framework.Scenes -{ - enum ScriptControlled : uint - { - CONTROL_ZERO = 0, - CONTROL_FWD = 1, - CONTROL_BACK = 2, - CONTROL_LEFT = 4, - CONTROL_RIGHT = 8, - CONTROL_UP = 16, - CONTROL_DOWN = 32, - CONTROL_ROT_LEFT = 256, - CONTROL_ROT_RIGHT = 512, - CONTROL_LBUTTON = 268435456, - CONTROL_ML_LBUTTON = 1073741824 - } - - struct ScriptControllers - { - public UUID itemID; - public ScriptControlled ignoreControls; - public ScriptControlled eventControls; - } - - public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); - - public class ScenePresence : EntityBase, ISceneEntity - { -// ~ScenePresence() -// { -// m_log.Debug("[ScenePresence] Destructor called"); -// } - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; -// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); - private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); - private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); - - /// - /// Experimentally determined "fudge factor" to make sit-target positions - /// the same as in SecondLife. Fudge factor was tested for 36 different - /// test cases including prims of type box, sphere, cylinder, and torus, - /// with varying parameters for sit target location, prim size, prim - /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis - /// issue #1716 - /// -// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); - // Value revised by KF 091121 by comparison with SL. - private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); - - public UUID currentParcelUUID = UUID.Zero; - - private ISceneViewer m_sceneViewer; - - /// - /// The animator for this avatar - /// - public ScenePresenceAnimator Animator - { - get { return m_animator; } - } - protected ScenePresenceAnimator m_animator; - - /// - /// The scene objects attached to this avatar. Do not change this list directly - use methods such as - /// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it. - /// - public List Attachments - { - get { return m_attachments; } - } - protected List m_attachments = new List(); - - private Dictionary scriptedcontrols = new Dictionary(); - private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; - private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; - private bool MouseDown = false; - private SceneObjectGroup proxyObjectGroup; - //private SceneObjectPart proxyObjectPart = null; - public Vector3 lastKnownAllowedPosition; - public bool sentMessageAboutRestrictedParcelFlyingDown; - public Vector4 CollisionPlane = Vector4.UnitW; - - private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation - private Vector3 m_avUnscriptedSitPos; // for non-scripted prims - private Vector3 m_lastPosition; - private Vector3 m_lastWorldPosition; - private Quaternion m_lastRotation; - private Vector3 m_lastVelocity; - //private int m_lastTerseSent; - - private bool m_updateflag; - private byte m_movementflag; - private Vector3? m_forceToApply; - private uint m_requestedSitTargetID; - private UUID m_requestedSitTargetUUID; - public bool SitGround = false; - - private SendCourseLocationsMethod m_sendCourseLocationsMethod; - - private bool m_startAnimationSet; - - //private Vector3 m_requestedSitOffset = new Vector3(); - - private Vector3 m_LastFinitePos; - - private float m_sitAvatarHeight = 2.0f; - - private int m_godLevel; - private int m_userLevel; - - private bool m_invulnerable = true; - - private Vector3 m_lastChildAgentUpdatePosition; - private Vector3 m_lastChildAgentUpdateCamPosition; - - private int m_perfMonMS; - - private bool m_setAlwaysRun; - private bool m_forceFly; - private bool m_flyDisabled; - - private float m_speedModifier = 1.0f; - - private Quaternion m_bodyRot= Quaternion.Identity; - - private Quaternion m_bodyRotPrevious = Quaternion.Identity; - - private const int LAND_VELOCITYMAG_MAX = 12; - - public bool IsRestrictedToRegion; - - public string JID = String.Empty; - - private float m_health = 100f; - - // Default AV Height - private float m_avHeight = 127.0f; - - protected RegionInfo m_regionInfo; - protected ulong crossingFromRegion; - - private readonly Vector3[] Dir_Vectors = new Vector3[11]; - private bool m_isNudging = false; - - // Position of agent's camera in world (region cordinates) - protected Vector3 m_CameraCenter; - protected Vector3 m_lastCameraCenter; - - protected Timer m_reprioritization_timer; - protected bool m_reprioritizing; - protected bool m_reprioritization_called; - - // Use these three vectors to figure out what the agent is looking at - // Convert it to a Matrix and/or Quaternion - protected Vector3 m_CameraAtAxis; - protected Vector3 m_CameraLeftAxis; - protected Vector3 m_CameraUpAxis; - private AgentManager.ControlFlags m_AgentControlFlags; - private Quaternion m_headrotation = Quaternion.Identity; - private byte m_state; - - //Reuse the Vector3 instead of creating a new one on the UpdateMovement method -// private Vector3 movementvector; - - private bool m_autopilotMoving; - private Vector3 m_autoPilotTarget; - private bool m_sitAtAutoTarget; - private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit - - private string m_nextSitAnimation = String.Empty; - - //PauPaw:Proper PID Controler for autopilot************ - private bool m_moveToPositionInProgress; - private Vector3 m_moveToPositionTarget; - private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - - private bool m_followCamAuto; - - private int m_movementUpdateCount; - private int m_lastColCount = -1; //KF: Look for Collision chnages - private int m_updateCount = 0; //KF: Update Anims for a while - private static readonly int UPDATE_COUNT = 10; // how many frames to update for - private const int NumMovementsBetweenRayCast = 5; - private List m_lastColliders = new List(); - - private bool CameraConstraintActive; - //private int m_moveToPositionStateStatus; - //***************************************************** - - // Agent's Draw distance. - protected float m_DrawDistance; - - protected AvatarAppearance m_appearance; - - // neighbouring regions we have enabled a child agent in - // holds the seed cap for the child agent in that region - private Dictionary m_knownChildRegions = new Dictionary(); - - /// - /// Implemented Control Flags - /// - private enum Dir_ControlFlags - { - DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, - DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, - DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, - DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, - DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, - DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, - DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, - DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, - DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, - DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, - DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG - } - - /// - /// Position at which a significant movement was made - /// - private Vector3 posLastSignificantMove; - - // For teleports and crossings callbacks - string m_callbackURI; - UUID m_originRegionID; - - ulong m_rootRegionHandle; - - /// - /// Script engines present in the scene - /// - private IScriptModule[] m_scriptEngines; - - #region Properties - - /// - /// Physical scene representation of this Avatar. - /// - public PhysicsActor PhysicsActor - { - set { m_physicsActor = value; } - get { return m_physicsActor; } - } - - public byte MovementFlag - { - set { m_movementflag = value; } - get { return m_movementflag; } - } - - public bool Updated - { - set { m_updateflag = value; } - get { return m_updateflag; } - } - - public bool Invulnerable - { - set { m_invulnerable = value; } - get { return m_invulnerable; } - } - - public int UserLevel - { - get { return m_userLevel; } - } - - public int GodLevel - { - get { return m_godLevel; } - } - - public ulong RegionHandle - { - get { return m_rootRegionHandle; } - } - - public Vector3 CameraPosition - { - get { return m_CameraCenter; } - } - - public Quaternion CameraRotation - { - get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); } - } - - public Vector3 CameraAtAxis - { - get { return m_CameraAtAxis; } - } - - public Vector3 CameraLeftAxis - { - get { return m_CameraLeftAxis; } - } - - public Vector3 CameraUpAxis - { - get { return m_CameraUpAxis; } - } - - public Vector3 Lookat - { - get - { - Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0); - - if (a == Vector3.Zero) - return a; - - return Util.GetNormalizedVector(a); - } - } - - private readonly string m_firstname; - - public string Firstname - { - get { return m_firstname; } - } - - private readonly string m_lastname; - - public string Lastname - { - get { return m_lastname; } - } - - private string m_grouptitle; - - public string Grouptitle - { - get { return m_grouptitle; } - set { m_grouptitle = value; } - } - - public float DrawDistance - { - get { return m_DrawDistance; } - } - - protected bool m_allowMovement = true; - - public bool AllowMovement - { - get { return m_allowMovement; } - set { m_allowMovement = value; } - } - - public bool SetAlwaysRun - { - get - { - if (PhysicsActor != null) - { - return PhysicsActor.SetAlwaysRun; - } - else - { - return m_setAlwaysRun; - } - } - set - { - m_setAlwaysRun = value; - if (PhysicsActor != null) - { - PhysicsActor.SetAlwaysRun = value; - } - } - } - - public byte State - { - get { return m_state; } - set { m_state = value; } - } - - public uint AgentControlFlags - { - get { return (uint)m_AgentControlFlags; } - set { m_AgentControlFlags = (AgentManager.ControlFlags)value; } - } - - /// - /// This works out to be the ClientView object associated with this avatar, or it's client connection manager - /// - private IClientAPI m_controllingClient; - - protected PhysicsActor m_physicsActor; - - /// - /// The client controlling this presence - /// - public IClientAPI ControllingClient - { - get { return m_controllingClient; } - } - - public IClientCore ClientView - { - get { return (IClientCore) m_controllingClient; } - } - - protected Vector3 m_parentPosition; - public Vector3 ParentPosition - { - get { return m_parentPosition; } - set { m_parentPosition = value; } - } - - /// - /// Position of this avatar relative to the region the avatar is in - /// - public override Vector3 AbsolutePosition - { - get - { - PhysicsActor actor = m_physicsActor; -// if (actor != null) - if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting! - m_pos = actor.Position; - - // If we're sitting, we need to update our position - if (m_parentID != 0) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); - if (part != null) - m_parentPosition = part.AbsolutePosition; - } - - return m_parentPosition + m_pos; - } - set - { - PhysicsActor actor = m_physicsActor; - if (actor != null) - { - try - { - lock (m_scene.SyncRoot) - m_physicsActor.Position = value; - } - catch (Exception e) - { - m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message); - } - } - - if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting! - m_pos = value; - m_parentPosition = Vector3.Zero; - } - } - - public Vector3 OffsetPosition - { - get { return m_pos; } - set { m_pos = value; } - } - - /// - /// Current velocity of the avatar. - /// - public override Vector3 Velocity - { - get - { - PhysicsActor actor = m_physicsActor; - if (actor != null) - m_velocity = actor.Velocity; - - return m_velocity; - } - set - { - PhysicsActor actor = m_physicsActor; - if (actor != null) - { - try - { - lock (m_scene.SyncRoot) - actor.Velocity = value; - } - catch (Exception e) - { - m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message); - } - } - - m_velocity = value; - } - } - - public Quaternion OffsetRotation - { - get { return m_offsetRotation; } - set { m_offsetRotation = value; } - } - - public Quaternion Rotation - { - get { - if (m_parentID != 0) - { - if (m_offsetRotation != null) - { - return m_offsetRotation; - } - else - { - return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - } - - } - else - { - return m_bodyRot; - } - } - set { - m_bodyRot = value; - if (m_parentID != 0) - { - m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - } - } - } - - public Quaternion PreviousRotation - { - get { return m_bodyRotPrevious; } - set { m_bodyRotPrevious = value; } - } - - /// - /// If this is true, agent doesn't have a representation in this scene. - /// this is an agent 'looking into' this scene from a nearby scene(region) - /// - /// if False, this agent has a representation in this scene - /// - private bool m_isChildAgent = true; - - public bool IsChildAgent - { - get { return m_isChildAgent; } - set { m_isChildAgent = value; } - } - - private uint m_parentID; - - - private UUID m_linkedPrim; - - public uint ParentID - { - get { return m_parentID; } - set { m_parentID = value; } - } - - public UUID LinkedPrim - { - get { return m_linkedPrim; } - set { m_linkedPrim = value; } - } - - public float Health - { - get { return m_health; } - set { m_health = value; } - } - - /// - /// These are the region handles known by the avatar. - /// - public List KnownChildRegionHandles - { - get - { - if (m_knownChildRegions.Count == 0) - return new List(); - else - return new List(m_knownChildRegions.Keys); - } - } - - public Dictionary KnownRegions - { - get { return m_knownChildRegions; } - set - { - m_knownChildRegions = value; - } - } - - public ISceneViewer SceneViewer - { - get { return m_sceneViewer; } - } - - public void AdjustKnownSeeds() - { - Dictionary seeds; - - if (Scene.CapsModule != null) - seeds = Scene.CapsModule.GetChildrenSeeds(UUID); - else - seeds = new Dictionary(); - - List old = new List(); - foreach (ulong handle in seeds.Keys) - { - uint x, y; - Utils.LongToUInts(handle, out x, out y); - x = x / Constants.RegionSize; - y = y / Constants.RegionSize; - if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) - { - old.Add(handle); - } - } - DropOldNeighbours(old); - - if (Scene.CapsModule != null) - Scene.CapsModule.SetChildrenSeed(UUID, seeds); - - KnownRegions = seeds; - //m_log.Debug(" ++++++++++AFTER+++++++++++++ "); - //DumpKnownRegions(); - } - - public void DumpKnownRegions() - { - m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================"); - foreach (KeyValuePair kvp in KnownRegions) - { - uint x, y; - Utils.LongToUInts(kvp.Key, out x, out y); - x = x / Constants.RegionSize; - y = y / Constants.RegionSize; - m_log.Info(" >> "+x+", "+y+": "+kvp.Value); - } - } - - private bool m_inTransit; - private bool m_mouseLook; - private bool m_leftButtonDown; - - public bool IsInTransit - { - get { return m_inTransit; } - set { m_inTransit = value; } - } - - public float SpeedModifier - { - get { return m_speedModifier; } - set { m_speedModifier = value; } - } - - public bool ForceFly - { - get { return m_forceFly; } - set { m_forceFly = value; } - } - - public bool FlyDisabled - { - get { return m_flyDisabled; } - set { m_flyDisabled = value; } - } - - public string Viewer - { - get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; } - } - - #endregion - - #region Constructor(s) - - public ScenePresence() - { - m_sendCourseLocationsMethod = SendCoarseLocationsDefault; - CreateSceneViewer(); - m_animator = new ScenePresenceAnimator(this); - } - - private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() - { - m_rootRegionHandle = reginfo.RegionHandle; - m_controllingClient = client; - m_firstname = m_controllingClient.FirstName; - m_lastname = m_controllingClient.LastName; - m_name = String.Format("{0} {1}", m_firstname, m_lastname); - m_scene = world; - m_uuid = client.AgentId; - m_regionInfo = reginfo; - m_localId = m_scene.AllocateLocalId(); - - UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); - - if (account != null) - m_userLevel = account.UserLevel; - - IGroupsModule gm = m_scene.RequestModuleInterface(); - if (gm != null) - m_grouptitle = gm.GetGroupTitle(m_uuid); - - m_scriptEngines = m_scene.RequestModuleInterfaces(); - - AbsolutePosition = posLastSignificantMove = m_CameraCenter = - m_lastCameraCenter = m_controllingClient.StartPos; - - m_reprioritization_timer = new Timer(world.ReprioritizationInterval); - m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize); - m_reprioritization_timer.AutoReset = false; - - AdjustKnownSeeds(); - Animator.TrySetMovementAnimation("STAND"); - // we created a new ScenePresence (a new child agent) in a fresh region. - // Request info about all the (root) agents in this region - // Note: This won't send data *to* other clients in that region (children don't send) - SendInitialFullUpdateToAllClients(); - RegisterToEvents(); - if (m_controllingClient != null) - { - m_controllingClient.ProcessPendingPackets(); - } - SetDirectionVectors(); - } - - public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams, - AvatarWearable[] wearables) - : this(client, world, reginfo) - { - m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams); - } - - public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance) - : this(client, world, reginfo) - { - m_appearance = appearance; - } - - private void CreateSceneViewer() - { - m_sceneViewer = new SceneViewer(this); - } - - public void RegisterToEvents() - { - m_controllingClient.OnRequestWearables += SendWearables; - m_controllingClient.OnSetAppearance += SetAppearance; - m_controllingClient.OnCompleteMovementToRegion += CompleteMovement; - //m_controllingClient.OnCompleteMovementToRegion += SendInitialData; - m_controllingClient.OnAgentUpdate += HandleAgentUpdate; - m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit; - m_controllingClient.OnAgentSit += HandleAgentSit; - m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; - m_controllingClient.OnStartAnim += HandleStartAnim; - m_controllingClient.OnStopAnim += HandleStopAnim; - m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls; - m_controllingClient.OnAutoPilotGo += DoAutoPilot; - m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition); - - // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); - // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); - } - - private void SetDirectionVectors() - { - Dir_Vectors[0] = Vector3.UnitX; //FORWARD - Dir_Vectors[1] = -Vector3.UnitX; //BACK - Dir_Vectors[2] = Vector3.UnitY; //LEFT - Dir_Vectors[3] = -Vector3.UnitY; //RIGHT - Dir_Vectors[4] = Vector3.UnitZ; //UP - Dir_Vectors[5] = -Vector3.UnitZ; //DOWN - Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE - Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE - Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE - Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE - Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge - } - - private Vector3[] GetWalkDirectionVectors() - { - Vector3[] vector = new Vector3[11]; - vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD - vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK - vector[2] = Vector3.UnitY; //LEFT - vector[3] = -Vector3.UnitY; //RIGHT - vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP - vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN - vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE - vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE - vector[8] = Vector3.UnitY; //LEFT_NUDGE - vector[9] = -Vector3.UnitY; //RIGHT_NUDGE - vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE - return vector; - } - - private bool[] GetDirectionIsNudge() - { - bool[] isNudge = new bool[11]; - isNudge[0] = false; //FORWARD - isNudge[1] = false; //BACK - isNudge[2] = false; //LEFT - isNudge[3] = false; //RIGHT - isNudge[4] = false; //UP - isNudge[5] = false; //DOWN - isNudge[6] = true; //FORWARD_NUDGE - isNudge[7] = true; //BACK_NUDGE - isNudge[8] = true; //LEFT_NUDGE - isNudge[9] = true; //RIGHT_NUDGE - isNudge[10] = true; //DOWN_Nudge - return isNudge; - } - - - #endregion - - public uint GenerateClientFlags(UUID ObjectID) - { - return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID); - } - - /// - /// Send updates to the client about prims which have been placed on the update queue. We don't - /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent - /// timestamp has already been sent. - /// - public void SendPrimUpdates() - { - m_perfMonMS = Util.EnvironmentTickCount(); - - m_sceneViewer.SendPrimUpdates(); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - #region Status Methods - - /// - /// This turns a child agent, into a root agent - /// This is called when an agent teleports into a region, or if an - /// agent crosses into this region from a neighbor over the border - /// - public void MakeRootAgent(Vector3 pos, bool isFlying) - { - m_log.DebugFormat( - "[SCENE]: Upgrading child to root agent for {0} in {1}", - Name, m_scene.RegionInfo.RegionName); - - //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); - - IGroupsModule gm = m_scene.RequestModuleInterface(); - if (gm != null) - m_grouptitle = gm.GetGroupTitle(m_uuid); - - m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; - m_scene.SetRootAgentScene(m_uuid); - - // Moved this from SendInitialData to ensure that m_appearance is initialized - // before the inventory is processed in MakeRootAgent. This fixes a race condition - // related to the handling of attachments - //m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); - if (m_scene.TestBorderCross(pos, Cardinals.E)) - { - Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); - pos.X = crossedBorder.BorderLine.Z - 1; - } - - if (m_scene.TestBorderCross(pos, Cardinals.N)) - { - Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); - pos.Y = crossedBorder.BorderLine.Z - 1; - } - - //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet. - //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent, - //they'll bypass the landing point. But I can't think of any decent way of fixing this. - if (KnownChildRegionHandles.Count == 0) - { - ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); - if (land != null) - { - //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. - if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) - { - pos = land.LandData.UserLocation; - } - } - } - - if (pos.X < 0 || pos.Y < 0 || pos.Z < 0) - { - Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128); - - if (pos.X < 0) - { - emergencyPos.X = (int)Constants.RegionSize + pos.X; - if (!(pos.Y < 0)) - emergencyPos.Y = pos.Y; - if (!(pos.Z < 0)) - emergencyPos.Z = pos.Z; - } - if (pos.Y < 0) - { - emergencyPos.Y = (int)Constants.RegionSize + pos.Y; - if (!(pos.X < 0)) - emergencyPos.X = pos.X; - if (!(pos.Z < 0)) - emergencyPos.Z = pos.Z; - } - if (pos.Z < 0) - { - emergencyPos.Z = 128; - if (!(pos.Y < 0)) - emergencyPos.Y = pos.Y; - if (!(pos.X < 0)) - emergencyPos.X = pos.X; - } - } - - if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) - { - m_log.WarnFormat( - "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", - pos, Name, UUID); - - if (pos.X < 0f) pos.X = 0f; - if (pos.Y < 0f) pos.Y = 0f; - if (pos.Z < 0f) pos.Z = 0f; - } - - float localAVHeight = 1.56f; - if (m_avHeight != 127.0f) - { - localAVHeight = m_avHeight; - } - - float posZLimit = 0; - - if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) - posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; - - float newPosZ = posZLimit + localAVHeight / 2; - if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) - { - pos.Z = newPosZ; - } - AbsolutePosition = pos; - - AddToPhysicalScene(isFlying); - - if (m_forceFly) - { - m_physicsActor.Flying = true; - } - else if (m_flyDisabled) - { - m_physicsActor.Flying = false; - } - - if (m_appearance != null) - { - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); - } - else - { - m_log.ErrorFormat("[SCENE PRESENCE]: null appearance in MakeRoot in {0}", Scene.RegionInfo.RegionName); - // emergency; this really shouldn't happen - m_appearance = new AvatarAppearance(UUID); - } - - // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying - // avatar to return to the standing position in mid-air. On login it looks like this is being sent - // elsewhere anyway - // Animator.SendAnimPack(); - - m_scene.SwapRootAgentCount(false); - - //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid); - //if (userInfo != null) - // userInfo.FetchInventory(); - //else - // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid); - - // On the next prim update, all objects will be sent - // - m_sceneViewer.Reset(); - - m_isChildAgent = false; - - // send the animations of the other presences to me - m_scene.ForEachScenePresence(delegate(ScenePresence presence) - { - if (presence != this) - presence.Animator.SendAnimPackToClient(ControllingClient); - }); - - m_scene.EventManager.TriggerOnMakeRootAgent(this); - } - - /// - /// This turns a root agent into a child agent - /// when an agent departs this region for a neighbor, this gets called. - /// - /// It doesn't get called for a teleport. Reason being, an agent that - /// teleports out may not end up anywhere near this region - /// - public void MakeChildAgent() - { - // It looks like m_animator is set to null somewhere, and MakeChild - // is called after that. Probably in aborted teleports. - if (m_animator == null) - m_animator = new ScenePresenceAnimator(this); - else - Animator.ResetAnimations(); - -// m_log.DebugFormat( -// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", -// Name, UUID, m_scene.RegionInfo.RegionName); - - // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing, - // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated. - //Velocity = new Vector3(0, 0, 0); - - m_isChildAgent = true; - m_scene.SwapRootAgentCount(true); - RemoveFromPhysicalScene(); - - // FIXME: Set m_rootRegionHandle to the region handle of the scene this agent is moving into - - m_scene.EventManager.TriggerOnMakeChildAgent(this); - } - - /// - /// Removes physics plugin scene representation of this agent if it exists. - /// - private void RemoveFromPhysicalScene() - { - if (PhysicsActor != null) - { - m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; - m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; - m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); - m_physicsActor.UnSubscribeEvents(); - m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; - PhysicsActor = null; - } - } - - /// - /// - /// - /// - public void Teleport(Vector3 pos) - { - bool isFlying = false; - - if (m_physicsActor != null) - isFlying = m_physicsActor.Flying; - - RemoveFromPhysicalScene(); - Velocity = Vector3.Zero; - AbsolutePosition = pos; - AddToPhysicalScene(isFlying); - if (m_appearance != null) - { - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); - } - - SendTerseUpdateToAllClients(); - - } - - public void TeleportWithMomentum(Vector3 pos) - { - bool isFlying = false; - if (m_physicsActor != null) - isFlying = m_physicsActor.Flying; - - RemoveFromPhysicalScene(); - AbsolutePosition = pos; - AddToPhysicalScene(isFlying); - if (m_appearance != null) - { - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); - } - - SendTerseUpdateToAllClients(); - } - - /// - /// - /// - public void StopMovement() - { - } - - public void StopFlying() - { - ControllingClient.StopFlying(this); - } - - public void AddNeighbourRegion(ulong regionHandle, string cap) - { - lock (m_knownChildRegions) - { - if (!m_knownChildRegions.ContainsKey(regionHandle)) - { - uint x, y; - Utils.LongToUInts(regionHandle, out x, out y); - m_knownChildRegions.Add(regionHandle, cap); - } - } - } - - public void RemoveNeighbourRegion(ulong regionHandle) - { - lock (m_knownChildRegions) - { - if (m_knownChildRegions.ContainsKey(regionHandle)) - { - m_knownChildRegions.Remove(regionHandle); - //m_log.Debug(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); - } - } - } - - public void DropOldNeighbours(List oldRegions) - { - foreach (ulong handle in oldRegions) - { - RemoveNeighbourRegion(handle); - Scene.CapsModule.DropChildSeed(UUID, handle); - } - } - - public List GetKnownRegionList() - { - return new List(m_knownChildRegions.Keys); - } - - #endregion - - #region Event Handlers - - /// - /// Sets avatar height in the phyiscs plugin - /// - internal void SetHeight(float height) - { - m_avHeight = height; - if (PhysicsActor != null && !IsChildAgent) - { - Vector3 SetSize = new Vector3(0.45f, 0.6f, m_avHeight); - PhysicsActor.Size = SetSize; - } - } - - /// - /// Complete Avatar's movement into the region. - /// This is called upon a very important packet sent from the client, - /// so it's client-controlled. Never call this method directly. - /// - public void CompleteMovement(IClientAPI client) - { - //m_log.Debug("[SCENE PRESENCE]: CompleteMovement"); - - Vector3 look = Velocity; - if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) - { - look = new Vector3(0.99f, 0.042f, 0); - } - - // Prevent teleporting to an underground location - // (may crash client otherwise) - // - Vector3 pos = AbsolutePosition; - float ground = m_scene.GetGroundHeight(pos.X, pos.Y); - if (pos.Z < ground + 1.5f) - { - pos.Z = ground + 1.5f; - AbsolutePosition = pos; - } - m_isChildAgent = false; - bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - MakeRootAgent(AbsolutePosition, m_flying); - - if ((m_callbackURI != null) && !m_callbackURI.Equals("")) - { - m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI); - Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); - m_callbackURI = null; - } - - //m_log.DebugFormat("Completed movement"); - - m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); - SendInitialData(); - - // Create child agents in neighbouring regions - if (!m_isChildAgent) - { - IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); - if (m_agentTransfer != null) - m_agentTransfer.EnableChildAgents(this); - else - m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active"); - - IFriendsModule friendsModule = m_scene.RequestModuleInterface(); - if (friendsModule != null) - friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); - } - - } - - /// - /// Callback for the Camera view block check. Gets called with the results of the camera view block test - /// hitYN is true when there's something in the way. - /// - /// - /// - /// - /// - public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) - { - const float POSITION_TOLERANCE = 0.02f; - const float VELOCITY_TOLERANCE = 0.02f; - const float ROTATION_TOLERANCE = 0.02f; - - if (m_followCamAuto) - { - if (hitYN) - { - CameraConstraintActive = true; - //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance); - - Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint); - ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint))); - } - else - { - if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || - !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || - !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) - { - if (CameraConstraintActive) - { - ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f)); - CameraConstraintActive = false; - } - } - } - } - } - - /// - /// This is the event handler for client movement. If a client is moving, this event is triggering. - /// - public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) - { - //if (m_isChildAgent) - //{ - // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); - // return; - //} - - m_perfMonMS = Util.EnvironmentTickCount(); - - ++m_movementUpdateCount; - if (m_movementUpdateCount < 1) - m_movementUpdateCount = 1; - - #region Sanity Checking - - // This is irritating. Really. - if (!AbsolutePosition.IsFinite()) - { - RemoveFromPhysicalScene(); - m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); - - m_pos = m_LastFinitePos; - - if (!m_pos.IsFinite()) - { - m_pos.X = 127f; - m_pos.Y = 127f; - m_pos.Z = 127f; - m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); - } - - AddToPhysicalScene(false); - } - else - { - m_LastFinitePos = m_pos; - } - - #endregion Sanity Checking - - #region Inputs - - AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; - Quaternion bodyRotation = agentData.BodyRotation; - - // Camera location in world. We'll need to raytrace - // from this location from time to time. - m_CameraCenter = agentData.CameraCenter; - if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance) - { - ReprioritizeUpdates(); - m_lastCameraCenter = m_CameraCenter; - } - - // Use these three vectors to figure out what the agent is looking at - // Convert it to a Matrix and/or Quaternion - m_CameraAtAxis = agentData.CameraAtAxis; - m_CameraLeftAxis = agentData.CameraLeftAxis; - m_CameraUpAxis = agentData.CameraUpAxis; - - // The Agent's Draw distance setting - m_DrawDistance = agentData.Far; - - // Check if Client has camera in 'follow cam' or 'build' mode. - Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation); - - m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f) - && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; - - m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; - m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; - - #endregion Inputs - - if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) - { - StandUp(); - } - - //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); - // Raycast from the avatar's head to the camera to see if there's anything blocking the view - if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) - { - if (m_followCamAuto) - { - Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; - m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); - } - } - lock (scriptedcontrols) - { - if (scriptedcontrols.Count > 0) - { - SendControlToScripts((uint)flags); - flags = RemoveIgnoredControls(flags, IgnoredControls); - } - } - - if (m_autopilotMoving) - CheckAtSitTarget(); - - if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) - { - m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. - Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); - - // TODO: This doesn't prevent the user from walking yet. - // Setting parent ID would fix this, if we knew what value - // to use. Or we could add a m_isSitting variable. - //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); - SitGround = true; - } - - // In the future, these values might need to go global. - // Here's where you get them. - m_AgentControlFlags = flags; - m_headrotation = agentData.HeadRotation; - m_state = agentData.State; - - PhysicsActor actor = PhysicsActor; - if (actor == null) - { - return; - } - - bool update_movementflag = false; - - if (m_allowMovement && !SitGround) - { - if (agentData.UseClientAgentPosition) - { - m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; - m_moveToPositionTarget = agentData.ClientAgentPosition; - } - - int i = 0; - - bool update_rotation = false; - bool DCFlagKeyPressed = false; - Vector3 agent_control_v3 = Vector3.Zero; - Quaternion q = bodyRotation; - - bool oldflying = PhysicsActor.Flying; - - if (m_forceFly) - actor.Flying = true; - else if (m_flyDisabled) - actor.Flying = false; - else - actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - - if (actor.Flying != oldflying) - update_movementflag = true; - - if (q != m_bodyRot) - { - m_bodyRot = q; - update_rotation = true; - } - - //guilty until proven innocent.. - bool Nudging = true; - //Basically, if there is at least one non-nudge control then we don't need - //to worry about stopping the avatar - - if (m_parentID == 0) - { - bool bAllowUpdateMoveToPosition = false; - bool bResetMoveToPosition = false; - - Vector3[] dirVectors; - - // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying - // this prevents 'jumping' in inappropriate situations. - if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying)) - dirVectors = GetWalkDirectionVectors(); - else - dirVectors = Dir_Vectors; - - bool[] isNudge = GetDirectionIsNudge(); - - - - - - foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) - { - if (((uint)flags & (uint)DCF) != 0) - { - bResetMoveToPosition = true; - DCFlagKeyPressed = true; - try - { - agent_control_v3 += dirVectors[i]; - if (isNudge[i] == false) - { - Nudging = false; - } - } - catch (IndexOutOfRangeException) - { - // Why did I get this? - } - - if ((m_movementflag & (uint)DCF) == 0) - { - m_movementflag += (byte)(uint)DCF; - update_movementflag = true; - } - } - else - { - if ((m_movementflag & (uint)DCF) != 0) - { - m_movementflag -= (byte)(uint)DCF; - update_movementflag = true; - } - else - { - bAllowUpdateMoveToPosition = true; - } - } - i++; - } - //Paupaw:Do Proper PID for Autopilot here - if (bResetMoveToPosition) - { - m_moveToPositionTarget = Vector3.Zero; - m_moveToPositionInProgress = false; - update_movementflag = true; - bAllowUpdateMoveToPosition = false; - } - - if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) - { - //Check the error term of the current position in relation to the target position - if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) - { - // we are close enough to the target - m_moveToPositionTarget = Vector3.Zero; - m_moveToPositionInProgress = false; - update_movementflag = true; - } - else - { - try - { - // move avatar in 2D at one meter/second towards target, in avatar coordinate frame. - // This movement vector gets added to the velocity through AddNewMovement(). - // Theoretically we might need a more complex PID approach here if other - // unknown forces are acting on the avatar and we need to adaptively respond - // to such forces, but the following simple approach seems to works fine. - Vector3 LocalVectorToTarget3D = - (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords - * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords - // Ignore z component of vector - Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); - LocalVectorToTarget2D.Normalize(); - - //We're not nudging - Nudging = false; - agent_control_v3 += LocalVectorToTarget2D; - - // update avatar movement flags. the avatar coordinate system is as follows: - // - // +X (forward) - // - // ^ - // | - // | - // | - // | - // (left) +Y <--------o--------> -Y - // avatar - // | - // | - // | - // | - // v - // -X - // - - // based on the above avatar coordinate system, classify the movement into - // one of left/right/back/forward. - if (LocalVectorToTarget2D.Y > 0)//MoveLeft - { - m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; - //AgentControlFlags - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; - update_movementflag = true; - } - else if (LocalVectorToTarget2D.Y < 0) //MoveRight - { - m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; - update_movementflag = true; - } - if (LocalVectorToTarget2D.X < 0) //MoveBack - { - m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; - update_movementflag = true; - } - else if (LocalVectorToTarget2D.X > 0) //Move Forward - { - m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; - update_movementflag = true; - } - } - catch (Exception e) - { - //Avoid system crash, can be slower but... - m_log.DebugFormat("Crash! {0}", e.ToString()); - } - } - } - } - - // Cause the avatar to stop flying if it's colliding - // with something with the down arrow pressed. - - // Only do this if we're flying - if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly) - { - // Landing detection code - - // Are the landing controls requirements filled? - bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || - ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); - - // Are the collision requirements fulfilled? - bool colliding = (m_physicsActor.IsColliding == true); - - if (m_physicsActor.Flying && colliding && controlland) - { - // nesting this check because LengthSquared() is expensive and we don't - // want to do it every step when flying. - if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) - StopFlying(); - } - } - - if (update_movementflag || (update_rotation && DCFlagKeyPressed)) - { - // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed)); - // m_log.DebugFormat( - // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); - - AddNewMovement(agent_control_v3, q, Nudging); - - - } - } - - if (update_movementflag && !SitGround) - Animator.UpdateMovementAnimations(); - - m_scene.EventManager.TriggerOnClientMovement(this); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client) - { - m_autopilotMoving = true; - m_autoPilotTarget = Pos; - m_sitAtAutoTarget = false; - PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; - //proxy.PCode = (byte)PCode.ParticleSystem; - proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); - proxyObjectGroup.AttachToScene(m_scene); - - // Commented out this code since it could never have executed, but might still be informative. -// if (proxyObjectGroup != null) -// { - proxyObjectGroup.SendGroupFullUpdate(); - remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); - m_scene.DeleteSceneObject(proxyObjectGroup, false); -// } -// else -// { -// m_autopilotMoving = false; -// m_autoPilotTarget = Vector3.Zero; -// ControllingClient.SendAlertMessage("Autopilot cancelled"); -// } - } - - public void DoMoveToPosition(Object sender, string method, List args) - { - try - { - float locx = 0f; - float locy = 0f; - float locz = 0f; - uint regionX = 0; - uint regionY = 0; - try - { - Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); - locx = Convert.ToSingle(args[0]) - (float)regionX; - locy = Convert.ToSingle(args[1]) - (float)regionY; - locz = Convert.ToSingle(args[2]); - } - catch (InvalidCastException) - { - m_log.Error("[CLIENT]: Invalid autopilot request"); - return; - } - m_moveToPositionInProgress = true; - m_moveToPositionTarget = new Vector3(locx, locy, locz); - } - catch (Exception ex) - { - //Why did I get this error? - m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex); - } - } - - private void CheckAtSitTarget() - { - //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString()); - if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5) - { - if (m_sitAtAutoTarget) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID); - if (part != null) - { - AbsolutePosition = part.AbsolutePosition; - Velocity = Vector3.Zero; - SendFullUpdateToAllClients(); - - HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ?? - } - //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); - m_requestedSitTargetUUID = UUID.Zero; - } - /* - else - { - //ControllingClient.SendAlertMessage("Autopilot cancelled"); - //SendTerseUpdateToAllClients(); - //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; - //proxy.PCode = (byte)PCode.ParticleSystem; - ////uint nextUUID = m_scene.NextLocalId; - - //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy); - //if (proxyObjectGroup != null) - //{ - //proxyObjectGroup.SendGroupFullUpdate(); - //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); - //m_scene.DeleteSceneObject(proxyObjectGroup); - //} - } - */ - m_autoPilotTarget = Vector3.Zero; - m_autopilotMoving = false; - } - } - /// - /// Perform the logic necessary to stand the avatar up. This method also executes - /// the stand animation. - /// - public void StandUp() - { - SitGround = false; - - if (m_parentID != 0) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); - if (part != null) - { - part.TaskInventory.LockItemsForRead(true); - TaskInventoryDictionary taskIDict = part.TaskInventory; - if (taskIDict != null) - { - foreach (UUID taskID in taskIDict.Keys) - { - UnRegisterControlEventsToScript(LocalId, taskID); - taskIDict[taskID].PermsMask &= ~( - 2048 | //PERMISSION_CONTROL_CAMERA - 4); // PERMISSION_TAKE_CONTROLS - } - } - part.TaskInventory.LockItemsForRead(false); - // Reset sit target. - if (part.GetAvatarOnSitTarget() == UUID) - part.SetAvatarOnSitTarget(UUID.Zero); - m_parentPosition = part.GetWorldPosition(); - ControllingClient.SendClearFollowCamProperties(part.ParentUUID); - } - // part.GetWorldRotation() is the rotation of the object being sat on - // Rotation is the sittiing Av's rotation - - Quaternion partRot; -// if (part.LinkNum == 1) -// { // Root prim of linkset -// partRot = part.ParentGroup.RootPart.RotationOffset; -// } -// else -// { // single or child prim - -// } - if (part == null) //CW: Part may be gone. llDie() for example. - { - partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - } - else - { - partRot = part.GetWorldRotation(); - } - - Quaternion partIRot = Quaternion.Inverse(partRot); - - Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av - Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av - - - if (m_physicsActor == null) - { - AddToPhysicalScene(false); - } - //CW: If the part isn't null then we can set the current position - if (part != null) - { - Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset! - AbsolutePosition = avWorldStandUp; //KF: Fix stand up. - part.IsOccupied = false; - part.ParentGroup.DeleteAvatar(ControllingClient.AgentId); - } - else - { - //CW: Since the part doesn't exist, a coarse standup position isn't an issue - AbsolutePosition = m_lastWorldPosition; - } - - m_parentPosition = Vector3.Zero; - m_parentID = 0; - m_linkedPrim = UUID.Zero; - m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - SendFullUpdateToAllClients(); - m_requestedSitTargetID = 0; - - if ((m_physicsActor != null) && (m_avHeight > 0)) - { - SetHeight(m_avHeight); - } - } - Animator.TrySetMovementAnimation("STAND"); - } - - private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) - { - SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID); - if (targetPart == null) - return null; - - // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used. - // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used. - - // Get our own copy of the part array, and sort into the order we want to test - SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts(); - Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2) - { - // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1) - int linkNum1 = p1==targetPart ? -1 : p1.LinkNum; - int linkNum2 = p2==targetPart ? -1 : p2.LinkNum; - return linkNum1 - linkNum2; - } - ); - - //look for prims with explicit sit targets that are available - foreach (SceneObjectPart part in partArray) - { - // Is a sit target available? - Vector3 avSitOffSet = part.SitTargetPosition; - Quaternion avSitOrientation = part.SitTargetOrientation; - UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); - bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero); - bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. - if (SitTargetisSet && !SitTargetOccupied) - { - //switch the target to this prim - return part; - } - } - - // no explicit sit target found - use original target - return targetPart; - } - - private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) - { - bool autopilot = true; - Vector3 autopilotTarget = new Vector3(); - Quaternion sitOrientation = Quaternion.Identity; - Vector3 pos = new Vector3(); - Vector3 cameraEyeOffset = Vector3.Zero; - Vector3 cameraAtOffset = Vector3.Zero; - bool forceMouselook = false; - - //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); - SceneObjectPart part = FindNextAvailableSitTarget(targetID); - if (part == null) return; - - // TODO: determine position to sit at based on scene geometry; don't trust offset from client - // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it - - // part is the prim to sit on - // offset is the world-ref vector distance from that prim center to the click-spot - // UUID is the UUID of the Avatar doing the clicking - - m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation - - // Is a sit target available? - Vector3 avSitOffSet = part.SitTargetPosition; - Quaternion avSitOrientation = part.SitTargetOrientation; - - bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. - // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); - Quaternion partRot; -// if (part.LinkNum == 1) -// { // Root prim of linkset -// partRot = part.ParentGroup.RootPart.RotationOffset; -// } -// else -// { // single or child prim - partRot = part.GetWorldRotation(); -// } - Quaternion partIRot = Quaternion.Inverse(partRot); -//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet); - // Sit analysis rewritten by KF 091125 - if (SitTargetisSet) // scipted sit - { - if (!part.IsOccupied) - { -//Console.WriteLine("Scripted, unoccupied"); - part.SetAvatarOnSitTarget(UUID); // set that Av will be on it - offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one - - Quaternion nrot = avSitOrientation; - if (!part.IsRoot) - { - nrot = part.RotationOffset * avSitOrientation; - } - sitOrientation = nrot; // Change rotatione to the scripted one - OffsetRotation = nrot; - autopilot = false; // Jump direct to scripted llSitPos() - } - else - { -//Console.WriteLine("Scripted, occupied"); - return; - } - } - else // Not Scripted - { - if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) - { - // large prim & offset, ignore if other Avs sitting -// offset.Z -= 0.05f; - m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked - autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point - -//Console.WriteLine(" offset ={0}", offset); -//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos); -//Console.WriteLine(" autopilotTarget={0}", autopilotTarget); - - } - else // small offset - { -//Console.WriteLine("Small offset"); - if (!part.IsOccupied) - { - m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center - autopilotTarget = part.AbsolutePosition; -//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget); - } - else return; // occupied small - } // end large/small - } // end Scripted/not - cameraAtOffset = part.GetCameraAtOffset(); - cameraEyeOffset = part.GetCameraEyeOffset(); - forceMouselook = part.GetForceMouselook(); - if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); // - if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); // - - if (m_physicsActor != null) - { - // If we're not using the client autopilot, we're immediately warping the avatar to the location - // We can remove the physicsActor until they stand up. - m_sitAvatarHeight = m_physicsActor.Size.Z; - if (autopilot) - { // its not a scripted sit -// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) - if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) ) - { - autopilot = false; // close enough - m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup. - Not using the part's position because returning the AV to the last known standing - position is likely to be more friendly, isn't it? */ - RemoveFromPhysicalScene(); - AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target - } // else the autopilot will get us close - } - else - { // its a scripted sit - m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup. - I *am* using the part's position this time because we have no real idea how far away - the avatar is from the sit target. */ - RemoveFromPhysicalScene(); - } - } - else return; // physactor is null! - - Vector3 offsetr; // = offset * partIRot; - // KF: In a linkset, offsetr needs to be relative to the group root! 091208 - // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot); - // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error. - // { // Single, or Root prim of linkset, target is ClickOffset * RootRot - //offsetr = offset * partIRot; -// - // else - // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot) - // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + - // (offset * partRot); - // } - -//Console.WriteLine(" "); -//Console.WriteLine("link number ={0}", part.LinkNum); -//Console.WriteLine("Prim offset ={0}", part.OffsetPosition ); -//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset); -//Console.WriteLine("Click offst ={0}", offset); -//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation()); -//Console.WriteLine("offsetr ={0}", offsetr); -//Console.WriteLine("Camera At ={0}", cameraAtOffset); -//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); - - //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child - ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); - - m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target - // This calls HandleAgentSit twice, once from here, and the client calls - // HandleAgentSit itself after it gets to the location - // It doesn't get to the location until we've moved them there though - // which happens in HandleAgentSit :P - m_autopilotMoving = autopilot; - m_autoPilotTarget = autopilotTarget; - m_sitAtAutoTarget = autopilot; - m_initialSitTarget = autopilotTarget; - if (!autopilot) - HandleAgentSit(remoteClient, UUID); - } - - public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset) - { - if (m_parentID != 0) - { - StandUp(); - } - m_nextSitAnimation = "SIT"; - - //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); - SceneObjectPart part = FindNextAvailableSitTarget(targetID); - - if (part != null) - { - if (!String.IsNullOrEmpty(part.SitAnimation)) - { - m_nextSitAnimation = part.SitAnimation; - } - m_requestedSitTargetID = part.LocalId; - //m_requestedSitOffset = offset; - m_requestedSitTargetUUID = targetID; - - m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); - - if (m_scene.PhysicsScene.SupportsRayCast()) - { - //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback()); - //SitRayCastAvatarPosition(part); - //return; - } - } - else - { - - m_log.Warn("Sit requested on unknown object: " + targetID.ToString()); - } - - - - SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity); - } - /* - public void SitRayCastAvatarPosition(SceneObjectPart part) - { - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = AbsolutePosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse); - } - - public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); - } - else - { - SitRayCastAvatarPositionCameraZ(part); - } - } - else - { - SitRayCastAvatarPositionCameraZ(part); - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part) - { - // Next, try to raycast from the camera Z position - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse); - } - - public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal); - } - else - { - SitRayCastCameraPosition(part); - } - } - else - { - SitRayCastCameraPosition(part); - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - public void SitRayCastCameraPosition(SceneObjectPart part) - { - // Next, try to raycast from the camera position - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = CameraPosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse); - } - - public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); - } - else - { - SitRayHorizontal(part); - } - } - else - { - SitRayHorizontal(part); - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - public void SitRayHorizontal(SceneObjectPart part) - { - // Next, try to raycast from the avatar position to fwd - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = CameraPosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse); - } - - public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); - // Next, try to raycast from the camera position - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = CameraPosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition); - } - else - { - ControllingClient.SendAlertMessage("Sit position not accessable."); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - } - else - { - ControllingClient.SendAlertMessage("Sit position not accessable."); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal) - { - int i = 0; - //throw new NotImplementedException(); - //m_requestedSitTargetUUID = UUID.Zero; - //m_requestedSitTargetID = 0; - //m_requestedSitOffset = Vector3.Zero; - - SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity); - } - */ - public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation) - { - if (m_parentID != 0) - { - StandUp(); - } - if (!String.IsNullOrEmpty(sitAnimation)) - { - m_nextSitAnimation = sitAnimation; - } - else - { - m_nextSitAnimation = "SIT"; - } - - //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); - SceneObjectPart part = FindNextAvailableSitTarget(targetID); - if (part != null) - { - m_requestedSitTargetID = part.LocalId; - //m_requestedSitOffset = offset; - m_requestedSitTargetUUID = targetID; - - m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); - - if (m_scene.PhysicsScene.SupportsRayCast()) - { - //SitRayCastAvatarPosition(part); - //return; - } - } - else - { - m_log.Warn("Sit requested on unknown object: " + targetID); - } - - SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity); - } - - public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) - { - if (!String.IsNullOrEmpty(m_nextSitAnimation)) - { - HandleAgentSit(remoteClient, agentID, m_nextSitAnimation); - } - else - { - HandleAgentSit(remoteClient, agentID, "SIT"); - } - } - - public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); - - if (m_sitAtAutoTarget || !m_autopilotMoving) - { - if (part != null) - { -//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation()); - if (part.GetAvatarOnSitTarget() == UUID) - { -//Console.WriteLine("Scripted Sit"); - // Scripted sit - Vector3 sitTargetPos = part.SitTargetPosition; - Quaternion sitTargetOrient = part.SitTargetOrientation; - m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); - m_pos += SIT_TARGET_ADJUSTMENT; - if (!part.IsRoot) - { - m_pos *= part.RotationOffset; - } - m_bodyRot = sitTargetOrient; - m_parentPosition = part.AbsolutePosition; - part.IsOccupied = true; - part.ParentGroup.AddAvatar(agentID); -Console.WriteLine("Scripted Sit ofset {0}", m_pos); - } - else - { - // if m_avUnscriptedSitPos is zero then Av sits above center - // Else Av sits at m_avUnscriptedSitPos - - // Non-scripted sit by Kitto Flora 21Nov09 - // Calculate angle of line from prim to Av - Quaternion partIRot; -// if (part.LinkNum == 1) -// { // Root prim of linkset -// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); -// } -// else -// { // single or child prim - partIRot = Quaternion.Inverse(part.GetWorldRotation()); -// } - Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos; - float y_diff = (m_avInitialPos.Y - sitTargetPos.Y); - float x_diff = ( m_avInitialPos.X - sitTargetPos.X); - if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0 - if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0 - float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff); - // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'. - // Av sits at world euler <0,0, z>, translated by part rotation - m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click - - m_parentPosition = part.AbsolutePosition; - part.IsOccupied = true; - part.ParentGroup.AddAvatar(agentID); - m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation - (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center - (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) + - m_avUnscriptedSitPos; // adds click offset, if any - //Set up raytrace to find top surface of prim - Vector3 size = part.Scale; - float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); - Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); - Vector3 down = new Vector3(0f, 0f, -1f); -//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag); - m_scene.PhysicsScene.RaycastWorld( - start, // Vector3 position, - down, // Vector3 direction, - mag, // float length, - SitAltitudeCallback); // retMethod - } // end scripted/not - } - else // no Av - { - return; - } - } - - //We want our offsets to reference the root prim, not the child we may have sat on - if (!part.IsRoot) - { - m_parentID = part.ParentGroup.RootPart.LocalId; - m_pos += part.OffsetPosition; - } - else - { - m_parentID = m_requestedSitTargetID; - } - - m_linkedPrim = part.UUID; - - Velocity = Vector3.Zero; - RemoveFromPhysicalScene(); - - Animator.TrySetMovementAnimation(sitAnimation); - SendFullUpdateToAllClients(); - } - - public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal) - { - // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer - // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height. - if(hitYN) - { - // m_pos = Av offset from prim center to make look like on center - // m_parentPosition = Actual center pos of prim - // collisionPoint = spot on prim where we want to sit - // collisionPoint.Z = global sit surface height - SceneObjectPart part = m_scene.GetSceneObjectPart(localid); - Quaternion partIRot; -// if (part.LinkNum == 1) -/// { // Root prim of linkset -// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); -// } -// else -// { // single or child prim - partIRot = Quaternion.Inverse(part.GetWorldRotation()); -// } - if (m_initialSitTarget != null) - { - float offZ = collisionPoint.Z - m_initialSitTarget.Z; - Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction - //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); - m_pos += offset; - // ControllingClient.SendClearFollowCamProperties(part.UUID); - } - - } - } // End SitAltitudeCallback KF. - - /// - /// Event handler for the 'Always run' setting on the client - /// Tells the physics plugin to increase speed of movement. - /// - public void HandleSetAlwaysRun(IClientAPI remoteClient, bool pSetAlwaysRun) - { - m_setAlwaysRun = pSetAlwaysRun; - if (PhysicsActor != null) - { - PhysicsActor.SetAlwaysRun = pSetAlwaysRun; - } - } - - public void HandleStartAnim(IClientAPI remoteClient, UUID animID) - { - Animator.AddAnimation(animID, UUID.Zero); - } - - public void HandleStopAnim(IClientAPI remoteClient, UUID animID) - { - Animator.RemoveAnimation(animID); - } - - /// - /// Rotate the avatar to the given rotation and apply a movement in the given relative vector - /// - /// The vector in which to move. This is relative to the rotation argument - /// The direction in which this avatar should now face. - public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging) - { - if (m_isChildAgent) - { - // WHAT??? - m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); - - // we have to reset the user's child agent connections. - // Likely, here they've lost the eventqueue for other regions so border - // crossings will fail at this point unless we reset them. - - List regions = new List(KnownChildRegionHandles); - regions.Remove(m_scene.RegionInfo.RegionHandle); - - MakeRootAgent(new Vector3(127f, 127f, 127f), true); - - // Async command - if (m_scene.SceneGridService != null) - { - m_scene.SceneGridService.SendCloseChildAgentConnections(UUID, regions); - - // Give the above command some time to try and close the connections. - // this is really an emergency.. so sleep, or we'll get all discombobulated. - System.Threading.Thread.Sleep(500); - } - - if (m_scene.SceneGridService != null) - { - IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); - if (m_agentTransfer != null) - m_agentTransfer.EnableChildAgents(this); - } - - return; - } - - m_perfMonMS = Util.EnvironmentTickCount(); - - Rotation = rotation; - Vector3 direc = vec * rotation; - direc.Normalize(); - PhysicsActor actor = m_physicsActor; - if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up. - - direc *= 0.03f * 128f * m_speedModifier; - - if (actor != null) - { - if (actor.Flying) - { - direc *= 4.0f; - //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); - //bool colliding = (m_physicsActor.IsColliding==true); - //if (controlland) - // m_log.Info("[AGENT]: landCommand"); - //if (colliding) - // m_log.Info("[AGENT]: colliding"); - //if (m_physicsActor.Flying && colliding && controlland) - //{ - // StopFlying(); - // m_log.Info("[AGENT]: Stop FLying"); - //} - } - else if (!actor.Flying && actor.IsColliding) - { - if (direc.Z > 2.0f) - { - if(m_animator.m_animTickJump == -1) - { - direc.Z *= 3.0f; // jump - } - else - { - direc.Z *= 0.1f; // prejump - } - /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs - Animator.TrySetMovementAnimation("PREJUMP"); - Animator.TrySetMovementAnimation("JUMP"); - */ - } - } - } - - // TODO: Add the force instead of only setting it to support multiple forces per frame? - m_forceToApply = direc; - m_isNudging = Nudging; - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - #endregion - - #region Overridden Methods - - public override void Update() - { - const float ROTATION_TOLERANCE = 0.01f; - const float VELOCITY_TOLERANCE = 0.001f; - const float POSITION_TOLERANCE = 0.05f; - //const int TIME_MS_TOLERANCE = 3000; - - - - if (m_isChildAgent == false) - { -// PhysicsActor actor = m_physicsActor; - - // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to - // grab the latest PhysicsActor velocity, whereas m_velocity is often - // storing a requested force instead of an actual traveling velocity - - // Throw away duplicate or insignificant updates - if (!m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || - !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || - !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) - //Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) - { - SendTerseUpdateToAllClients(); - - // Update the "last" values - m_lastPosition = m_pos; - m_lastRotation = m_bodyRot; - m_lastVelocity = Velocity; - //m_lastTerseSent = Environment.TickCount; - } - - // followed suggestion from mic bowman. reversed the two lines below. - if (m_parentID == 0 && m_physicsActor != null || m_parentID != 0) // Check that we have a physics actor or we're sitting on something - CheckForBorderCrossing(); - CheckForSignificantMovement(); // sends update to the modules. - } - - //Sending prim updates AFTER the avatar terse updates are sent - SendPrimUpdates(); - } - - #endregion - - #region Update Client(s) - - /// - /// Sends a location update to the client connected to this scenePresence - /// - /// - public void SendTerseUpdateToClient(IClientAPI remoteClient) - { - // If the client is inactive, it's getting its updates from another - // server. - if (remoteClient.IsActive) - { - m_perfMonMS = Util.EnvironmentTickCount(); - - PhysicsActor actor = m_physicsActor; - Vector3 velocity = (actor != null) ? actor.Velocity : Vector3.Zero; - - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - - //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); - - remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - m_scene.StatsReporter.AddAgentUpdates(1); - } - } - - /// - /// Send a location/velocity/accelleration update to all agents in scene - /// - public void SendTerseUpdateToAllClients() - { - m_perfMonMS = Util.EnvironmentTickCount(); - - m_scene.ForEachClient(SendTerseUpdateToClient); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - public void SendCoarseLocations(List coarseLocations, List avatarUUIDs) - { - SendCourseLocationsMethod d = m_sendCourseLocationsMethod; - if (d != null) - { - d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); - } - } - - public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) - { - if (d != null) - m_sendCourseLocationsMethod = d; - } - - public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs) - { - m_perfMonMS = Util.EnvironmentTickCount(); - m_controllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - /// - /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar) - /// - /// - public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar) - { - // 2 stage check is needed. - if (remoteAvatar == null) - return; - IClientAPI cl=remoteAvatar.ControllingClient; - if (cl == null) - return; - if (m_appearance.Texture == null) - return; - - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - - remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this); - m_scene.StatsReporter.AddAgentUpdates(1); - } - - /// - /// Tell *ALL* agents about this agent - /// - public void SendInitialFullUpdateToAllClients() - { - m_perfMonMS = Util.EnvironmentTickCount(); - int avUpdates = 0; - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - ++avUpdates; - // only send if this is the root (children are only "listening posts" in a foreign region) - if (!IsChildAgent) - { - SendFullUpdateToOtherClient(avatar); - } - - if (avatar.LocalId != LocalId) - { - if (!avatar.IsChildAgent) - { - avatar.SendFullUpdateToOtherClient(this); - avatar.SendAppearanceToOtherAgent(this); - avatar.Animator.SendAnimPackToClient(ControllingClient); - } - } - }); - - m_scene.StatsReporter.AddAgentUpdates(avUpdates); - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - - //Animator.SendAnimPack(); - } - - public void SendFullUpdateToAllClients() - { - m_perfMonMS = Util.EnvironmentTickCount(); - - // only send update from root agents to other clients; children are only "listening posts" - int count = 0; - m_scene.ForEachScenePresence(delegate(ScenePresence sp) - { - if (sp.IsChildAgent) - return; - SendFullUpdateToOtherClient(sp); - ++count; - }); - m_scene.StatsReporter.AddAgentUpdates(count); - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - - Animator.SendAnimPack(); - } - - /// - /// Do everything required once a client completes its movement into a region - /// - public void SendInitialData() - { - // Moved this into CompleteMovement to ensure that m_appearance is initialized before - // the inventory arrives - // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); - - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - - m_controllingClient.SendAvatarDataImmediate(this); - - SendInitialFullUpdateToAllClients(); - SendAppearanceToAllOtherAgents(); - } - - /// - /// Tell the client for this scene presence what items it should be wearing now - /// - public void SendWearables() - { - m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name); - - ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); - } - - /// - /// - /// - public void SendAppearanceToAllOtherAgents() - { - m_perfMonMS = Util.EnvironmentTickCount(); - - m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) - { - if (scenePresence.UUID != UUID) - { - SendAppearanceToOtherAgent(scenePresence); - } - }); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - /// - /// Send appearance data to an agent that isn't this one. - /// - /// - public void SendAppearanceToOtherAgent(ScenePresence avatar) - { - avatar.ControllingClient.SendAppearance( - m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes()); - } - - /// - /// Set appearance data (textureentry and slider settings) received from the client - /// - /// - /// - public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams) - { - if (m_physicsActor != null) - { - if (!IsChildAgent) - { - // This may seem like it's redundant, remove the avatar from the physics scene - // just to add it back again, but it saves us from having to update - // 3 variables 10 times a second. - bool flyingTemp = m_physicsActor.Flying; - RemoveFromPhysicalScene(); - //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor); - - //PhysicsActor = null; - - AddToPhysicalScene(flyingTemp); - } - } - - #region Bake Cache Check - - if (textureEntry != null) - { - for (int i = 0; i < BAKE_INDICES.Length; i++) - { - int j = BAKE_INDICES[i]; - Primitive.TextureEntryFace face = textureEntry.FaceTextures[j]; - - if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) - { - if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) - { - m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name); - this.ControllingClient.SendRebakeAvatarTextures(face.TextureID); - } - } - } - - } - - - #endregion Bake Cache Check - - m_appearance.SetAppearance(textureEntry, visualParams); - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); - - // This is not needed, because only the transient data changed - //AvatarData adata = new AvatarData(m_appearance); - //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); - - SendAppearanceToAllOtherAgents(); - if (!m_startAnimationSet) - { - Animator.UpdateMovementAnimations(); - m_startAnimationSet = true; - } - - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - - m_controllingClient.SendAvatarDataImmediate(this); - } - - public void SetWearable(int wearableId, AvatarWearable wearable) - { - m_appearance.SetWearable(wearableId, wearable); - AvatarData adata = new AvatarData(m_appearance); - m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); - m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); - } - - // Because appearance setting is in a module, we actually need - // to give it access to our appearance directly, otherwise we - // get a synchronization issue. - public AvatarAppearance Appearance - { - get { return m_appearance; } - set { m_appearance = value; } - } - - #endregion - - #region Significant Movement Method - - /// - /// This checks for a significant movement and sends a courselocationchange update - /// - protected void CheckForSignificantMovement() - { - // Movement updates for agents in neighboring regions are sent directly to clients. - // This value only affects how often agent positions are sent to neighbor regions - // for things such as distance-based update prioritization - const float SIGNIFICANT_MOVEMENT = 2.0f; - - if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT) - { - posLastSignificantMove = AbsolutePosition; - m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient); - } - - // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m - if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || - Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance) - { - m_lastChildAgentUpdatePosition = AbsolutePosition; - m_lastChildAgentUpdateCamPosition = CameraPosition; - - ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); - cadu.ActiveGroupID = UUID.Zero.Guid; - cadu.AgentID = UUID.Guid; - cadu.alwaysrun = m_setAlwaysRun; - cadu.AVHeight = m_avHeight; - Vector3 tempCameraCenter = m_CameraCenter; - cadu.cameraPosition = tempCameraCenter; - cadu.drawdistance = m_DrawDistance; - cadu.GroupAccess = 0; - cadu.Position = AbsolutePosition; - cadu.regionHandle = m_rootRegionHandle; - float multiplier = 1; - int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); - if (innacurateNeighbors != 0) - { - multiplier = 1f / (float)innacurateNeighbors; - } - if (multiplier <= 0f) - { - multiplier = 0.25f; - } - - //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); - cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); - cadu.Velocity = Velocity; - - AgentPosition agentpos = new AgentPosition(); - agentpos.CopyFrom(cadu); - - m_scene.SendOutChildAgentUpdates(agentpos, this); - } - } - - #endregion - - #region Border Crossing Methods - - /// - /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion - /// - protected void CheckForBorderCrossing() - { - if (IsChildAgent) - return; - - Vector3 pos2 = AbsolutePosition; - Vector3 vel = Velocity; - int neighbor = 0; - int[] fix = new int[2]; - - float timeStep = 0.1f; - pos2.X = pos2.X + (vel.X*timeStep); - pos2.Y = pos2.Y + (vel.Y*timeStep); - pos2.Z = pos2.Z + (vel.Z*timeStep); - - if (!IsInTransit) - { - // Checks if where it's headed exists a region - - bool needsTransit = false; - if (m_scene.TestBorderCross(pos2, Cardinals.W)) - { - if (m_scene.TestBorderCross(pos2, Cardinals.S)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.SW, ref fix); - } - else if (m_scene.TestBorderCross(pos2, Cardinals.N)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.NW, ref fix); - } - else - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.W, ref fix); - } - } - else if (m_scene.TestBorderCross(pos2, Cardinals.E)) - { - if (m_scene.TestBorderCross(pos2, Cardinals.S)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.SE, ref fix); - } - else if (m_scene.TestBorderCross(pos2, Cardinals.N)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.NE, ref fix); - } - else - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.E, ref fix); - } - } - else if (m_scene.TestBorderCross(pos2, Cardinals.S)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.S, ref fix); - } - else if (m_scene.TestBorderCross(pos2, Cardinals.N)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.N, ref fix); - } - - - // Makes sure avatar does not end up outside region - if (neighbor <= 0) - { - if (!needsTransit) - { - if (m_requestedSitTargetUUID == UUID.Zero) - { - Vector3 pos = AbsolutePosition; - if (AbsolutePosition.X < 0) - pos.X += Velocity.X; - else if (AbsolutePosition.X > Constants.RegionSize) - pos.X -= Velocity.X; - if (AbsolutePosition.Y < 0) - pos.Y += Velocity.Y; - else if (AbsolutePosition.Y > Constants.RegionSize) - pos.Y -= Velocity.Y; - AbsolutePosition = pos; - } - } - } - else if (neighbor > 0) - CrossToNewRegion(); - } - else - { - RemoveFromPhysicalScene(); - // This constant has been inferred from experimentation - // I'm not sure what this value should be, so I tried a few values. - timeStep = 0.04f; - pos2 = AbsolutePosition; - pos2.X = pos2.X + (vel.X * timeStep); - pos2.Y = pos2.Y + (vel.Y * timeStep); - pos2.Z = pos2.Z + (vel.Z * timeStep); - m_pos = pos2; - } - } - - protected int HaveNeighbor(Cardinals car, ref int[] fix) - { - uint neighbourx = m_regionInfo.RegionLocX; - uint neighboury = m_regionInfo.RegionLocY; - - int dir = (int)car; - - if (dir > 1 && dir < 5) //Heading East - neighbourx++; - else if (dir > 5) // Heading West - neighbourx--; - - if (dir < 3 || dir == 8) // Heading North - neighboury++; - else if (dir > 3 && dir < 7) // Heading Sout - neighboury--; - - int x = (int)(neighbourx * Constants.RegionSize); - int y = (int)(neighboury * Constants.RegionSize); - GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y); - - if (neighbourRegion == null) - { - fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx); - fix[1] = (int)(m_regionInfo.RegionLocY - neighboury); - return dir * (-1); - } - else - return dir; - } - - /// - /// Moves the agent outside the region bounds - /// Tells neighbor region that we're crossing to it - /// If the neighbor accepts, remove the agent's viewable avatar from this scene - /// set them to a child agent. - /// - protected void CrossToNewRegion() - { - InTransit(); - try - { - m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying); - } - catch - { - m_scene.CrossAgentToNewRegion(this, false); - } - } - - public void InTransit() - { - m_inTransit = true; - - if ((m_physicsActor != null) && m_physicsActor.Flying) - m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY; - else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) - m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY; - } - - public void NotInTransit() - { - m_inTransit = false; - } - - public void RestoreInCurrentScene() - { - AddToPhysicalScene(false); // not exactly false - } - - public void Reset() - { - // Put the child agent back at the center - AbsolutePosition - = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); - Animator.ResetAnimations(); - } - - /// - /// Computes which child agents to close when the scene presence moves to another region. - /// Removes those regions from m_knownRegions. - /// - /// The new region's x on the map - /// The new region's y on the map - /// - public void CloseChildAgents(uint newRegionX, uint newRegionY) - { - List byebyeRegions = new List(); - m_log.DebugFormat( - "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", - m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName); - //DumpKnownRegions(); - - lock (m_knownChildRegions) - { - foreach (ulong handle in m_knownChildRegions.Keys) - { - // Don't close the agent on this region yet - if (handle != Scene.RegionInfo.RegionHandle) - { - uint x, y; - Utils.LongToUInts(handle, out x, out y); - x = x / Constants.RegionSize; - y = y / Constants.RegionSize; - - //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); - //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); - if (Util.IsOutsideView(x, newRegionX, y, newRegionY)) - { - byebyeRegions.Add(handle); - } - } - } - } - - if (byebyeRegions.Count > 0) - { - m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); - m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions); - } - - foreach (ulong handle in byebyeRegions) - { - RemoveNeighbourRegion(handle); - } - } - - #endregion - - /// - /// This allows the Sim owner the abiility to kick users from their sim currently. - /// It tells the client that the agent has permission to do so. - /// - public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) - { - if (godStatus) - { - // For now, assign god level 200 to anyone - // who is granted god powers, but has no god level set. - // - UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID); - if (account != null) - { - if (account.UserLevel > 0) - m_godLevel = account.UserLevel; - else - m_godLevel = 200; - } - } - else - { - m_godLevel = 0; - } - - ControllingClient.SendAdminResponse(token, (uint)m_godLevel); - } - - #region Child Agent Updates - - public void ChildAgentDataUpdate(AgentData cAgentData) - { - //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); - if (!IsChildAgent) - return; - - CopyFrom(cAgentData); - } - - /// - /// This updates important decision making data about a child agent - /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region - /// - public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) - { - if (!IsChildAgent) - return; - - //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); - int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; - int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; - - Vector3 offset = new Vector3(shiftx, shifty, 0f); - - m_DrawDistance = cAgentData.Far; - if (cAgentData.Position != new Vector3(-1f, -1f, -1f)) // UGH!! - m_pos = cAgentData.Position + offset; - - if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance) - { - posLastSignificantMove = AbsolutePosition; - ReprioritizeUpdates(); - } - - m_CameraCenter = cAgentData.Center + offset; - - m_avHeight = cAgentData.Size.Z; - //SetHeight(cAgentData.AVHeight); - - if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) - ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); - - // Sends out the objects in the user's draw distance if m_sendTasksToChild is true. - if (m_scene.m_seeIntoRegionFromNeighbor) - m_sceneViewer.Reset(); - - //cAgentData.AVHeight; - m_rootRegionHandle = cAgentData.RegionHandle; - //m_velocity = cAgentData.Velocity; - } - - public void CopyTo(AgentData cAgent) - { - cAgent.AgentID = UUID; - cAgent.RegionID = Scene.RegionInfo.RegionID; - - cAgent.Position = AbsolutePosition; - cAgent.Velocity = m_velocity; - cAgent.Center = m_CameraCenter; - // Don't copy the size; it is inferred from apearance parameters - //cAgent.Size = new Vector3(0, 0, m_avHeight); - cAgent.AtAxis = m_CameraAtAxis; - cAgent.LeftAxis = m_CameraLeftAxis; - cAgent.UpAxis = m_CameraUpAxis; - - cAgent.Far = m_DrawDistance; - - // Throttles - float multiplier = 1; - int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); - if (innacurateNeighbors != 0) - { - multiplier = 1f / innacurateNeighbors; - } - if (multiplier <= 0f) - { - multiplier = 0.25f; - } - //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); - cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); - - cAgent.HeadRotation = m_headrotation; - cAgent.BodyRotation = m_bodyRot; - cAgent.ControlFlags = (uint)m_AgentControlFlags; - - if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) - cAgent.GodLevel = (byte)m_godLevel; - else - cAgent.GodLevel = (byte) 0; - - cAgent.AlwaysRun = m_setAlwaysRun; - - try - { - // We might not pass the Wearables in all cases... - // They're only needed so that persistent changes to the appearance - // are preserved in the new region where the user is moving to. - // But in Hypergrid we might not let this happen. - int i = 0; - UUID[] wears = new UUID[m_appearance.Wearables.Length * 2]; - foreach (AvatarWearable aw in m_appearance.Wearables) - { - if (aw != null) - { - wears[i++] = aw.ItemID; - wears[i++] = aw.AssetID; - } - else - { - wears[i++] = UUID.Zero; - wears[i++] = UUID.Zero; - } - } - cAgent.Wearables = wears; - - cAgent.VisualParams = m_appearance.VisualParams; - - if (m_appearance.Texture != null) - cAgent.AgentTextures = m_appearance.Texture.GetBytes(); - } - catch (Exception e) - { - m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message); - } - - //Attachments - List attPoints = m_appearance.GetAttachedPoints(); - if (attPoints != null) - { - //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count); - int i = 0; - AttachmentData[] attachs = new AttachmentData[attPoints.Count]; - foreach (int point in attPoints) - { - attachs[i++] = new AttachmentData(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point)); - } - cAgent.Attachments = attachs; - } - - lock (scriptedcontrols) - { - ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; - int i = 0; - - foreach (ScriptControllers c in scriptedcontrols.Values) - { - controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); - } - cAgent.Controllers = controls; - } - - // Animations - try - { - cAgent.Anims = Animator.Animations.ToArray(); - } - catch { } - - // cAgent.GroupID = ?? - // Groups??? - - } - - public void CopyFrom(AgentData cAgent) - { - m_originRegionID = cAgent.RegionID; - - m_callbackURI = cAgent.CallbackURI; - - m_pos = cAgent.Position; - - m_velocity = cAgent.Velocity; - m_CameraCenter = cAgent.Center; - //m_avHeight = cAgent.Size.Z; - m_CameraAtAxis = cAgent.AtAxis; - m_CameraLeftAxis = cAgent.LeftAxis; - m_CameraUpAxis = cAgent.UpAxis; - - m_DrawDistance = cAgent.Far; - - if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) - ControllingClient.SetChildAgentThrottle(cAgent.Throttles); - - m_headrotation = cAgent.HeadRotation; - m_bodyRot = cAgent.BodyRotation; - m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; - - if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) - m_godLevel = cAgent.GodLevel; - m_setAlwaysRun = cAgent.AlwaysRun; - - uint i = 0; - try - { - if (cAgent.Wearables == null) - cAgent.Wearables = new UUID[0]; - AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2]; - for (uint n = 0; n < cAgent.Wearables.Length; n += 2) - { - UUID itemId = cAgent.Wearables[n]; - UUID assetId = cAgent.Wearables[n + 1]; - wears[i++] = new AvatarWearable(itemId, assetId); - } - m_appearance.Wearables = wears; - Primitive.TextureEntry te; - if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1) - te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); - else - te = AvatarAppearance.GetDefaultTexture(); - if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) - cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams(); - m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone()); - } - catch (Exception e) - { - m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message); - } - - // Attachments - try - { - if (cAgent.Attachments != null) - { - m_appearance.ClearAttachments(); - foreach (AttachmentData att in cAgent.Attachments) - { - m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); - } - } - } - catch { } - - try - { - lock (scriptedcontrols) - { - if (cAgent.Controllers != null) - { - scriptedcontrols.Clear(); - - foreach (ControllerData c in cAgent.Controllers) - { - ScriptControllers sc = new ScriptControllers(); - sc.itemID = c.ItemID; - sc.ignoreControls = (ScriptControlled)c.IgnoreControls; - sc.eventControls = (ScriptControlled)c.EventControls; - - scriptedcontrols[sc.itemID] = sc; - } - } - } - } - catch { } - // Animations - try - { - Animator.ResetAnimations(); - Animator.Animations.FromArray(cAgent.Anims); - } - catch { } - - //cAgent.GroupID = ?? - //Groups??? - } - - public bool CopyAgent(out IAgentData agent) - { - agent = new CompleteAgentData(); - CopyTo((AgentData)agent); - return true; - } - - #endregion Child Agent Updates - - /// - /// Handles part of the PID controller function for moving an avatar. - /// - public override void UpdateMovement() - { - if (m_forceToApply.HasValue) - { - - Vector3 force = m_forceToApply.Value; - m_updateflag = true; - Velocity = force; - - m_forceToApply = null; - } - else - { - if (m_isNudging) - { - Vector3 force = Vector3.Zero; - - m_updateflag = true; - Velocity = force; - m_isNudging = false; - m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND" - } - } - } - - public override void SetText(string text, Vector3 color, double alpha) - { - throw new Exception("Can't set Text on avatar."); - } - - /// - /// Adds a physical representation of the avatar to the Physics plugin - /// - public void AddToPhysicalScene(bool isFlying) - { - PhysicsScene scene = m_scene.PhysicsScene; - - Vector3 pVec = AbsolutePosition; - - // Old bug where the height was in centimeters instead of meters - if (m_avHeight == 127.0f) - { - m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new Vector3(0f, 0f, 1.56f), - isFlying); - } - else - { - m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, - new Vector3(0f, 0f, m_avHeight), isFlying); - } - scene.AddPhysicsActorTaint(m_physicsActor); - //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; - m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; - m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong - m_physicsActor.SubscribeEvents(500); - m_physicsActor.LocalID = LocalId; - } - - private void OutOfBoundsCall(Vector3 pos) - { - //bool flying = m_physicsActor.Flying; - //RemoveFromPhysicalScene(); - - //AddToPhysicalScene(flying); - if (ControllingClient != null) - ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); - } - - // Event called by the physics plugin to tell the avatar about a collision. - private void PhysicsCollisionUpdate(EventArgs e) - { - if (e == null) - return; - - // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents( - // as of this comment the interval is set in AddToPhysicalScene - if (Animator!=null) - { - if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper, - { // else its will lock out other animation changes, like ground sit. - Animator.UpdateMovementAnimations(); - m_updateCount--; - } - } - - CollisionEventUpdate collisionData = (CollisionEventUpdate)e; - Dictionary coldata = collisionData.m_objCollisionList; - - CollisionPlane = Vector4.UnitW; - - if (m_lastColCount != coldata.Count) - { - m_updateCount = UPDATE_COUNT; - m_lastColCount = coldata.Count; - } - - if (coldata.Count != 0 && Animator != null) - { - switch (Animator.CurrentMovementAnimation) - { - case "STAND": - case "WALK": - case "RUN": - case "CROUCH": - case "CROUCHWALK": - { - ContactPoint lowest; - lowest.SurfaceNormal = Vector3.Zero; - lowest.Position = Vector3.Zero; - lowest.Position.Z = Single.NaN; - - foreach (ContactPoint contact in coldata.Values) - { - if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z) - { - lowest = contact; - } - } - - CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal)); - } - break; - } - } - - List thisHitColliders = new List(); - List endedColliders = new List(); - List startedColliders = new List(); - - foreach (uint localid in coldata.Keys) - { - thisHitColliders.Add(localid); - if (!m_lastColliders.Contains(localid)) - { - startedColliders.Add(localid); - } - //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString()); - } - - // calculate things that ended colliding - foreach (uint localID in m_lastColliders) - { - if (!thisHitColliders.Contains(localID)) - { - endedColliders.Add(localID); - } - } - //add the items that started colliding this time to the last colliders list. - foreach (uint localID in startedColliders) - { - m_lastColliders.Add(localID); - } - // remove things that ended colliding from the last colliders list - foreach (uint localID in endedColliders) - { - m_lastColliders.Remove(localID); - } - - // do event notification - if (startedColliders.Count > 0) - { - ColliderArgs StartCollidingMessage = new ColliderArgs(); - List colliding = new List(); - foreach (uint localId in startedColliders) - { - if (localId == 0) - continue; - - SceneObjectPart obj = Scene.GetSceneObjectPart(localId); - string data = ""; - if (obj != null) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = obj.UUID; - detobj.nameStr = obj.Name; - detobj.ownerUUID = obj.OwnerID; - detobj.posVector = obj.AbsolutePosition; - detobj.rotQuat = obj.GetWorldRotation(); - detobj.velVector = obj.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = obj.GroupID; - colliding.Add(detobj); - } - } - - if (colliding.Count > 0) - { - StartCollidingMessage.Colliders = colliding; - - foreach (SceneObjectGroup att in Attachments) - Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage); - } - } - - if (endedColliders.Count > 0) - { - ColliderArgs EndCollidingMessage = new ColliderArgs(); - List colliding = new List(); - foreach (uint localId in endedColliders) - { - if (localId == 0) - continue; - - SceneObjectPart obj = Scene.GetSceneObjectPart(localId); - string data = ""; - if (obj != null) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = obj.UUID; - detobj.nameStr = obj.Name; - detobj.ownerUUID = obj.OwnerID; - detobj.posVector = obj.AbsolutePosition; - detobj.rotQuat = obj.GetWorldRotation(); - detobj.velVector = obj.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = obj.GroupID; - colliding.Add(detobj); - } - } - - if (colliding.Count > 0) - { - EndCollidingMessage.Colliders = colliding; - - foreach (SceneObjectGroup att in Attachments) - Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage); - } - } - - if (thisHitColliders.Count > 0) - { - ColliderArgs CollidingMessage = new ColliderArgs(); - List colliding = new List(); - foreach (uint localId in thisHitColliders) - { - if (localId == 0) - continue; - - SceneObjectPart obj = Scene.GetSceneObjectPart(localId); - string data = ""; - if (obj != null) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = obj.UUID; - detobj.nameStr = obj.Name; - detobj.ownerUUID = obj.OwnerID; - detobj.posVector = obj.AbsolutePosition; - detobj.rotQuat = obj.GetWorldRotation(); - detobj.velVector = obj.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = obj.GroupID; - colliding.Add(detobj); - } - } - - if (colliding.Count > 0) - { - CollidingMessage.Colliders = colliding; - - lock (m_attachments) - { - foreach (SceneObjectGroup att in m_attachments) - Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage); - } - } - } - - if (m_invulnerable) - return; - - float starthealth = Health; - uint killerObj = 0; - foreach (uint localid in coldata.Keys) - { - SceneObjectPart part = Scene.GetSceneObjectPart(localid); - - if (part != null && part.ParentGroup.Damage != -1.0f) - Health -= part.ParentGroup.Damage; - else - { - if (coldata[localid].PenetrationDepth >= 0.10f) - Health -= coldata[localid].PenetrationDepth * 5.0f; - } - - if (Health <= 0.0f) - { - if (localid != 0) - killerObj = localid; - } - //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString()); - } - //Health = 100; - if (!m_invulnerable) - { - if (starthealth != Health) - { - ControllingClient.SendHealth(Health); - } - if (m_health <= 0) - m_scene.EventManager.TriggerAvatarKill(killerObj, this); - } - } - - public void setHealthWithUpdate(float health) - { - Health = health; - ControllingClient.SendHealth(Health); - } - - public void Close() - { - lock (m_attachments) - { - // Delete attachments from scene - // Don't try to save, as this thread won't live long - // enough to complete the save. This would cause no copy - // attachments to poof! - // - foreach (SceneObjectGroup grp in m_attachments) - { - m_scene.DeleteSceneObject(grp, false); - } - m_attachments.Clear(); - } - - lock (m_knownChildRegions) - { - m_knownChildRegions.Clear(); - } - - lock (m_reprioritization_timer) - { - m_reprioritization_timer.Enabled = false; - m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize); - } - - // I don't get it but mono crashes when you try to dispose of this timer, - // unsetting the elapsed callback should be enough to allow for cleanup however. - // m_reprioritizationTimer.Dispose(); - - m_sceneViewer.Close(); - - RemoveFromPhysicalScene(); - m_animator.Close(); - m_animator = null; - } - - public void AddAttachment(SceneObjectGroup gobj) - { - lock (m_attachments) - { - m_attachments.Add(gobj); - } - } - - public bool HasAttachments() - { - return m_attachments.Count > 0; - } - - public bool HasScriptedAttachments() - { - lock (m_attachments) - { - foreach (SceneObjectGroup gobj in m_attachments) - { - if (gobj != null) - { - if (gobj.RootPart.Inventory.ContainsScripts()) - return true; - } - } - } - return false; - } - - public void RemoveAttachment(SceneObjectGroup gobj) - { - lock (m_attachments) - { - if (m_attachments.Contains(gobj)) - { - m_attachments.Remove(gobj); - } - } - } - - public bool ValidateAttachments() - { - lock (m_attachments) - { - // Validate - foreach (SceneObjectGroup gobj in m_attachments) - { - if (gobj == null) - return false; - - if (gobj.IsDeleted) - return false; - } - } - return true; - } - - /// - /// Send a script event to this scene presence's attachments - /// - /// The name of the event - /// The arguments for the event - public void SendScriptEventToAttachments(string eventName, Object[] args) - { - if (m_scriptEngines != null) - { - lock (m_attachments) - { - foreach (SceneObjectGroup grp in m_attachments) - { - // 16384 is CHANGED_ANIMATION - // - // Send this to all attachment root prims - // - foreach (IScriptModule m in m_scriptEngines) - { - if (m == null) // No script engine loaded - continue; - - m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION }); - } - } - } - } - } - - - public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene) - { - m_controllingClient = client; - m_regionInfo = region; - m_scene = scene; - - RegisterToEvents(); - if (m_controllingClient != null) - { - m_controllingClient.ProcessPendingPackets(); - } - /* - AbsolutePosition = client.StartPos; - - Animations = new AvatarAnimations(); - Animations.LoadAnims(); - - m_animations = new List(); - m_animations.Add(Animations.AnimsUUID["STAND"]); - m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber); - - SetDirectionVectors(); - */ - } - - internal void PushForce(Vector3 impulse) - { - if (PhysicsActor != null) - { - PhysicsActor.AddForce(impulse,true); - } - } - - public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) - { - ScriptControllers obj = new ScriptControllers(); - obj.ignoreControls = ScriptControlled.CONTROL_ZERO; - obj.eventControls = ScriptControlled.CONTROL_ZERO; - - obj.itemID = Script_item_UUID; - if (pass_on == 0 && accept == 0) - { - IgnoredControls |= (ScriptControlled)controls; - obj.ignoreControls = (ScriptControlled)controls; - } - - if (pass_on == 0 && accept == 1) - { - IgnoredControls |= (ScriptControlled)controls; - obj.ignoreControls = (ScriptControlled)controls; - obj.eventControls = (ScriptControlled)controls; - } - if (pass_on == 1 && accept == 1) - { - IgnoredControls = ScriptControlled.CONTROL_ZERO; - obj.eventControls = (ScriptControlled)controls; - obj.ignoreControls = ScriptControlled.CONTROL_ZERO; - } - - lock (scriptedcontrols) - { - if (pass_on == 1 && accept == 0) - { - IgnoredControls &= ~(ScriptControlled)controls; - if (scriptedcontrols.ContainsKey(Script_item_UUID)) - scriptedcontrols.Remove(Script_item_UUID); - } - else - { - scriptedcontrols[Script_item_UUID] = obj; - } - } - ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); - } - - public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID) - { - IgnoredControls = ScriptControlled.CONTROL_ZERO; - lock (scriptedcontrols) - { - scriptedcontrols.Clear(); - } - ControllingClient.SendTakeControls(int.MaxValue, false, false); - } - - public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) - { - ScriptControllers takecontrols; - - lock (scriptedcontrols) - { - if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols)) - { - ScriptControlled sctc = takecontrols.eventControls; - - ControllingClient.SendTakeControls((int)sctc, false, false); - ControllingClient.SendTakeControls((int)sctc, true, false); - - scriptedcontrols.Remove(Script_item_UUID); - IgnoredControls = ScriptControlled.CONTROL_ZERO; - foreach (ScriptControllers scData in scriptedcontrols.Values) - { - IgnoredControls |= scData.ignoreControls; - } - } - } - } - - internal void SendControlToScripts(uint flags) - { - ScriptControlled allflags = ScriptControlled.CONTROL_ZERO; - - if (MouseDown) - { - allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0) - { - allflags = ScriptControlled.CONTROL_ZERO; - MouseDown = true; - } - } - - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0) - { - allflags |= ScriptControlled.CONTROL_ML_LBUTTON; - MouseDown = true; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0) - { - allflags |= ScriptControlled.CONTROL_LBUTTON; - MouseDown = true; - } - - // find all activated controls, whether the scripts are interested in them or not - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0) - { - allflags |= ScriptControlled.CONTROL_FWD; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0) - { - allflags |= ScriptControlled.CONTROL_BACK; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0) - { - allflags |= ScriptControlled.CONTROL_UP; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0) - { - allflags |= ScriptControlled.CONTROL_DOWN; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0) - { - allflags |= ScriptControlled.CONTROL_LEFT; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0) - { - allflags |= ScriptControlled.CONTROL_RIGHT; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) - { - allflags |= ScriptControlled.CONTROL_ROT_RIGHT; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) - { - allflags |= ScriptControlled.CONTROL_ROT_LEFT; - } - // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that - if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands) - { - lock (scriptedcontrols) - { - foreach (KeyValuePair kvp in scriptedcontrols) - { - UUID scriptUUID = kvp.Key; - ScriptControllers scriptControlData = kvp.Value; - - ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us - ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle - ScriptControlled localChange = localHeld ^ localLast; // the changed bits - if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO) - { - // only send if still pressed or just changed - m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange); - } - } - } - } - - LastCommands = allflags; - } - - internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored) - { - if (ignored == ScriptControlled.CONTROL_ZERO) - return flags; - - if ((ignored & ScriptControlled.CONTROL_BACK) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); - if ((ignored & ScriptControlled.CONTROL_FWD) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS); - if ((ignored & ScriptControlled.CONTROL_DOWN) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG); - if ((ignored & ScriptControlled.CONTROL_UP) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS); - if ((ignored & ScriptControlled.CONTROL_LEFT) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); - if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG); - if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG); - if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS); - if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN); - if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN); - - //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, - //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, - //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, - //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, - //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, - //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, - //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG - - return flags; - } - - /// - /// RezAttachments. This should only be called upon login on the first region. - /// Attachment rezzings on crossings and TPs are done in a different way. - /// - public void RezAttachments() - { - if (null == m_appearance) - { - m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID); - return; - } - - XmlDocument doc = new XmlDocument(); - string stateData = String.Empty; - - IAttachmentsService attServ = m_scene.RequestModuleInterface(); - if (attServ != null) - { - m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service"); - stateData = attServ.Get(ControllingClient.AgentId.ToString()); - if (stateData != String.Empty) - { - try - { - doc.LoadXml(stateData); - } - catch { } - } - } - - Dictionary itemData = new Dictionary(); - - XmlNodeList nodes = doc.GetElementsByTagName("Attachment"); - if (nodes.Count > 0) - { - foreach (XmlNode n in nodes) - { - XmlElement elem = (XmlElement)n; - string itemID = elem.GetAttribute("ItemID"); - string xml = elem.InnerXml; - - itemData[new UUID(itemID)] = xml; - } - } - - List attPoints = m_appearance.GetAttachedPoints(); - foreach (int p in attPoints) - { - if (m_isDeleted) - return; - - UUID itemID = m_appearance.GetAttachedItem(p); - UUID assetID = m_appearance.GetAttachedAsset(p); - - // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down - // But they're not used anyway, the item is being looked up for now, so let's proceed. - //if (UUID.Zero == assetID) - //{ - // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); - // continue; - //} - - try - { - string xmlData; - XmlDocument d = new XmlDocument(); - UUID asset; - if (itemData.TryGetValue(itemID, out xmlData)) - { - d.LoadXml(xmlData); - m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID); - - // Rez from inventory - asset - = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d); - - } - else - { - // Rez from inventory (with a null doc to let - // CHANGED_OWNER happen) - asset - = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null); - } - - m_log.InfoFormat( - "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", - p, itemID, assetID, asset); - } - catch (Exception e) - { - m_log.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}", e.ToString()); - } - } - } - - private void ReprioritizeUpdates() - { - if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time) - { - lock (m_reprioritization_timer) - { - if (!m_reprioritizing) - m_reprioritization_timer.Enabled = m_reprioritizing = true; - else - m_reprioritization_called = true; - } - } - } - - private void Reprioritize(object sender, ElapsedEventArgs e) - { - m_controllingClient.ReprioritizeUpdates(); - - lock (m_reprioritization_timer) - { - m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called; - m_reprioritization_called = false; - } - } - - private Vector3 Quat2Euler(Quaternion rot){ - float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) , - (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z))); - float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W))); - float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) , - (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z))); - return(new Vector3(x,y,z)); - } - - - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Xml; +using System.Collections.Generic; +using System.Reflection; +using System.Timers; +using OpenMetaverse; +using log4net; +using OpenSim.Framework; +using OpenSim.Framework.Client; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes.Animation; +using OpenSim.Region.Framework.Scenes.Types; +using OpenSim.Region.Physics.Manager; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.Framework.Scenes +{ + enum ScriptControlled : uint + { + CONTROL_ZERO = 0, + CONTROL_FWD = 1, + CONTROL_BACK = 2, + CONTROL_LEFT = 4, + CONTROL_RIGHT = 8, + CONTROL_UP = 16, + CONTROL_DOWN = 32, + CONTROL_ROT_LEFT = 256, + CONTROL_ROT_RIGHT = 512, + CONTROL_LBUTTON = 268435456, + CONTROL_ML_LBUTTON = 1073741824 + } + + struct ScriptControllers + { + public UUID itemID; + public ScriptControlled ignoreControls; + public ScriptControlled eventControls; + } + + public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); + + public class ScenePresence : EntityBase, ISceneEntity + { +// ~ScenePresence() +// { +// m_log.Debug("[ScenePresence] Destructor called"); +// } + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; +// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); + private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); + private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); + + /// + /// Experimentally determined "fudge factor" to make sit-target positions + /// the same as in SecondLife. Fudge factor was tested for 36 different + /// test cases including prims of type box, sphere, cylinder, and torus, + /// with varying parameters for sit target location, prim size, prim + /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis + /// issue #1716 + /// +// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); + // Value revised by KF 091121 by comparison with SL. + private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); + + public UUID currentParcelUUID = UUID.Zero; + + private ISceneViewer m_sceneViewer; + + /// + /// The animator for this avatar + /// + public ScenePresenceAnimator Animator + { + get { return m_animator; } + } + protected ScenePresenceAnimator m_animator; + + /// + /// The scene objects attached to this avatar. Do not change this list directly - use methods such as + /// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it. + /// + public List Attachments + { + get { return m_attachments; } + } + protected List m_attachments = new List(); + + private Dictionary scriptedcontrols = new Dictionary(); + private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; + private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; + private bool MouseDown = false; + private SceneObjectGroup proxyObjectGroup; + //private SceneObjectPart proxyObjectPart = null; + public Vector3 lastKnownAllowedPosition; + public bool sentMessageAboutRestrictedParcelFlyingDown; + public Vector4 CollisionPlane = Vector4.UnitW; + + private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation + private Vector3 m_avUnscriptedSitPos; // for non-scripted prims + private Vector3 m_lastPosition; + private Vector3 m_lastWorldPosition; + private Quaternion m_lastRotation; + private Vector3 m_lastVelocity; + //private int m_lastTerseSent; + + private bool m_updateflag; + private byte m_movementflag; + private Vector3? m_forceToApply; + private uint m_requestedSitTargetID; + private UUID m_requestedSitTargetUUID; + public bool SitGround = false; + + private SendCourseLocationsMethod m_sendCourseLocationsMethod; + + private bool m_startAnimationSet; + + //private Vector3 m_requestedSitOffset = new Vector3(); + + private Vector3 m_LastFinitePos; + + private float m_sitAvatarHeight = 2.0f; + + private int m_godLevel; + private int m_userLevel; + + private bool m_invulnerable = true; + + private Vector3 m_lastChildAgentUpdatePosition; + private Vector3 m_lastChildAgentUpdateCamPosition; + + private int m_perfMonMS; + + private bool m_setAlwaysRun; + private bool m_forceFly; + private bool m_flyDisabled; + + private float m_speedModifier = 1.0f; + + private Quaternion m_bodyRot= Quaternion.Identity; + + private Quaternion m_bodyRotPrevious = Quaternion.Identity; + + private const int LAND_VELOCITYMAG_MAX = 12; + + public bool IsRestrictedToRegion; + + public string JID = String.Empty; + + private float m_health = 100f; + + // Default AV Height + private float m_avHeight = 127.0f; + + protected RegionInfo m_regionInfo; + protected ulong crossingFromRegion; + + private readonly Vector3[] Dir_Vectors = new Vector3[11]; + private bool m_isNudging = false; + + // Position of agent's camera in world (region cordinates) + protected Vector3 m_CameraCenter; + protected Vector3 m_lastCameraCenter; + + protected Timer m_reprioritization_timer; + protected bool m_reprioritizing; + protected bool m_reprioritization_called; + + // Use these three vectors to figure out what the agent is looking at + // Convert it to a Matrix and/or Quaternion + protected Vector3 m_CameraAtAxis; + protected Vector3 m_CameraLeftAxis; + protected Vector3 m_CameraUpAxis; + private AgentManager.ControlFlags m_AgentControlFlags; + private Quaternion m_headrotation = Quaternion.Identity; + private byte m_state; + + //Reuse the Vector3 instead of creating a new one on the UpdateMovement method +// private Vector3 movementvector; + + private bool m_autopilotMoving; + private Vector3 m_autoPilotTarget; + private bool m_sitAtAutoTarget; + private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit + + private string m_nextSitAnimation = String.Empty; + + //PauPaw:Proper PID Controler for autopilot************ + private bool m_moveToPositionInProgress; + private Vector3 m_moveToPositionTarget; + private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + + private bool m_followCamAuto; + + private int m_movementUpdateCount; + private int m_lastColCount = -1; //KF: Look for Collision chnages + private int m_updateCount = 0; //KF: Update Anims for a while + private static readonly int UPDATE_COUNT = 10; // how many frames to update for + private const int NumMovementsBetweenRayCast = 5; + private List m_lastColliders = new List(); + + private bool CameraConstraintActive; + //private int m_moveToPositionStateStatus; + //***************************************************** + + // Agent's Draw distance. + protected float m_DrawDistance; + + protected AvatarAppearance m_appearance; + + // neighbouring regions we have enabled a child agent in + // holds the seed cap for the child agent in that region + private Dictionary m_knownChildRegions = new Dictionary(); + + /// + /// Implemented Control Flags + /// + private enum Dir_ControlFlags + { + DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, + DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, + DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, + DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, + DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, + DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, + DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, + DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, + DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, + DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, + DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG + } + + /// + /// Position at which a significant movement was made + /// + private Vector3 posLastSignificantMove; + + // For teleports and crossings callbacks + string m_callbackURI; + UUID m_originRegionID; + + ulong m_rootRegionHandle; + + /// + /// Script engines present in the scene + /// + private IScriptModule[] m_scriptEngines; + + #region Properties + + /// + /// Physical scene representation of this Avatar. + /// + public PhysicsActor PhysicsActor + { + set { m_physicsActor = value; } + get { return m_physicsActor; } + } + + public byte MovementFlag + { + set { m_movementflag = value; } + get { return m_movementflag; } + } + + public bool Updated + { + set { m_updateflag = value; } + get { return m_updateflag; } + } + + public bool Invulnerable + { + set { m_invulnerable = value; } + get { return m_invulnerable; } + } + + public int UserLevel + { + get { return m_userLevel; } + } + + public int GodLevel + { + get { return m_godLevel; } + } + + public ulong RegionHandle + { + get { return m_rootRegionHandle; } + } + + public Vector3 CameraPosition + { + get { return m_CameraCenter; } + } + + public Quaternion CameraRotation + { + get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); } + } + + public Vector3 CameraAtAxis + { + get { return m_CameraAtAxis; } + } + + public Vector3 CameraLeftAxis + { + get { return m_CameraLeftAxis; } + } + + public Vector3 CameraUpAxis + { + get { return m_CameraUpAxis; } + } + + public Vector3 Lookat + { + get + { + Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0); + + if (a == Vector3.Zero) + return a; + + return Util.GetNormalizedVector(a); + } + } + + private readonly string m_firstname; + + public string Firstname + { + get { return m_firstname; } + } + + private readonly string m_lastname; + + public string Lastname + { + get { return m_lastname; } + } + + private string m_grouptitle; + + public string Grouptitle + { + get { return m_grouptitle; } + set { m_grouptitle = value; } + } + + public float DrawDistance + { + get { return m_DrawDistance; } + } + + protected bool m_allowMovement = true; + + public bool AllowMovement + { + get { return m_allowMovement; } + set { m_allowMovement = value; } + } + + public bool SetAlwaysRun + { + get + { + if (PhysicsActor != null) + { + return PhysicsActor.SetAlwaysRun; + } + else + { + return m_setAlwaysRun; + } + } + set + { + m_setAlwaysRun = value; + if (PhysicsActor != null) + { + PhysicsActor.SetAlwaysRun = value; + } + } + } + + public byte State + { + get { return m_state; } + set { m_state = value; } + } + + public uint AgentControlFlags + { + get { return (uint)m_AgentControlFlags; } + set { m_AgentControlFlags = (AgentManager.ControlFlags)value; } + } + + /// + /// This works out to be the ClientView object associated with this avatar, or it's client connection manager + /// + private IClientAPI m_controllingClient; + + protected PhysicsActor m_physicsActor; + + /// + /// The client controlling this presence + /// + public IClientAPI ControllingClient + { + get { return m_controllingClient; } + } + + public IClientCore ClientView + { + get { return (IClientCore) m_controllingClient; } + } + + protected Vector3 m_parentPosition; + public Vector3 ParentPosition + { + get { return m_parentPosition; } + set { m_parentPosition = value; } + } + + /// + /// Position of this avatar relative to the region the avatar is in + /// + public override Vector3 AbsolutePosition + { + get + { + PhysicsActor actor = m_physicsActor; +// if (actor != null) + if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting! + m_pos = actor.Position; + + // If we're sitting, we need to update our position + if (m_parentID != 0) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); + if (part != null) + m_parentPosition = part.AbsolutePosition; + } + + return m_parentPosition + m_pos; + } + set + { + PhysicsActor actor = m_physicsActor; + if (actor != null) + { + try + { + lock (m_scene.SyncRoot) + m_physicsActor.Position = value; + } + catch (Exception e) + { + m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message); + } + } + + if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting! + m_pos = value; + m_parentPosition = Vector3.Zero; + } + } + + public Vector3 OffsetPosition + { + get { return m_pos; } + set { m_pos = value; } + } + + /// + /// Current velocity of the avatar. + /// + public override Vector3 Velocity + { + get + { + PhysicsActor actor = m_physicsActor; + if (actor != null) + m_velocity = actor.Velocity; + + return m_velocity; + } + set + { + PhysicsActor actor = m_physicsActor; + if (actor != null) + { + try + { + lock (m_scene.SyncRoot) + actor.Velocity = value; + } + catch (Exception e) + { + m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message); + } + } + + m_velocity = value; + } + } + + public Quaternion OffsetRotation + { + get { return m_offsetRotation; } + set { m_offsetRotation = value; } + } + + public Quaternion Rotation + { + get { + if (m_parentID != 0) + { + if (m_offsetRotation != null) + { + return m_offsetRotation; + } + else + { + return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + + } + else + { + return m_bodyRot; + } + } + set { + m_bodyRot = value; + if (m_parentID != 0) + { + m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + } + } + + public Quaternion PreviousRotation + { + get { return m_bodyRotPrevious; } + set { m_bodyRotPrevious = value; } + } + + /// + /// If this is true, agent doesn't have a representation in this scene. + /// this is an agent 'looking into' this scene from a nearby scene(region) + /// + /// if False, this agent has a representation in this scene + /// + private bool m_isChildAgent = true; + + public bool IsChildAgent + { + get { return m_isChildAgent; } + set { m_isChildAgent = value; } + } + + private uint m_parentID; + + + private UUID m_linkedPrim; + + public uint ParentID + { + get { return m_parentID; } + set { m_parentID = value; } + } + + public UUID LinkedPrim + { + get { return m_linkedPrim; } + set { m_linkedPrim = value; } + } + + public float Health + { + get { return m_health; } + set { m_health = value; } + } + + /// + /// These are the region handles known by the avatar. + /// + public List KnownChildRegionHandles + { + get + { + if (m_knownChildRegions.Count == 0) + return new List(); + else + return new List(m_knownChildRegions.Keys); + } + } + + public Dictionary KnownRegions + { + get { return m_knownChildRegions; } + set + { + m_knownChildRegions = value; + } + } + + public ISceneViewer SceneViewer + { + get { return m_sceneViewer; } + } + + public void AdjustKnownSeeds() + { + Dictionary seeds; + + if (Scene.CapsModule != null) + seeds = Scene.CapsModule.GetChildrenSeeds(UUID); + else + seeds = new Dictionary(); + + List old = new List(); + foreach (ulong handle in seeds.Keys) + { + uint x, y; + Utils.LongToUInts(handle, out x, out y); + x = x / Constants.RegionSize; + y = y / Constants.RegionSize; + if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) + { + old.Add(handle); + } + } + DropOldNeighbours(old); + + if (Scene.CapsModule != null) + Scene.CapsModule.SetChildrenSeed(UUID, seeds); + + KnownRegions = seeds; + //m_log.Debug(" ++++++++++AFTER+++++++++++++ "); + //DumpKnownRegions(); + } + + public void DumpKnownRegions() + { + m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================"); + foreach (KeyValuePair kvp in KnownRegions) + { + uint x, y; + Utils.LongToUInts(kvp.Key, out x, out y); + x = x / Constants.RegionSize; + y = y / Constants.RegionSize; + m_log.Info(" >> "+x+", "+y+": "+kvp.Value); + } + } + + private bool m_inTransit; + private bool m_mouseLook; + private bool m_leftButtonDown; + + public bool IsInTransit + { + get { return m_inTransit; } + set { m_inTransit = value; } + } + + public float SpeedModifier + { + get { return m_speedModifier; } + set { m_speedModifier = value; } + } + + public bool ForceFly + { + get { return m_forceFly; } + set { m_forceFly = value; } + } + + public bool FlyDisabled + { + get { return m_flyDisabled; } + set { m_flyDisabled = value; } + } + + public string Viewer + { + get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; } + } + + #endregion + + #region Constructor(s) + + public ScenePresence() + { + m_sendCourseLocationsMethod = SendCoarseLocationsDefault; + CreateSceneViewer(); + m_animator = new ScenePresenceAnimator(this); + } + + private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() + { + m_rootRegionHandle = reginfo.RegionHandle; + m_controllingClient = client; + m_firstname = m_controllingClient.FirstName; + m_lastname = m_controllingClient.LastName; + m_name = String.Format("{0} {1}", m_firstname, m_lastname); + m_scene = world; + m_uuid = client.AgentId; + m_regionInfo = reginfo; + m_localId = m_scene.AllocateLocalId(); + + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); + + if (account != null) + m_userLevel = account.UserLevel; + + IGroupsModule gm = m_scene.RequestModuleInterface(); + if (gm != null) + m_grouptitle = gm.GetGroupTitle(m_uuid); + + m_scriptEngines = m_scene.RequestModuleInterfaces(); + + AbsolutePosition = posLastSignificantMove = m_CameraCenter = + m_lastCameraCenter = m_controllingClient.StartPos; + + m_reprioritization_timer = new Timer(world.ReprioritizationInterval); + m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize); + m_reprioritization_timer.AutoReset = false; + + AdjustKnownSeeds(); + Animator.TrySetMovementAnimation("STAND"); + // we created a new ScenePresence (a new child agent) in a fresh region. + // Request info about all the (root) agents in this region + // Note: This won't send data *to* other clients in that region (children don't send) + SendInitialFullUpdateToAllClients(); + RegisterToEvents(); + if (m_controllingClient != null) + { + m_controllingClient.ProcessPendingPackets(); + } + SetDirectionVectors(); + } + + public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams, + AvatarWearable[] wearables) + : this(client, world, reginfo) + { + m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams); + } + + public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance) + : this(client, world, reginfo) + { + m_appearance = appearance; + } + + private void CreateSceneViewer() + { + m_sceneViewer = new SceneViewer(this); + } + + public void RegisterToEvents() + { + m_controllingClient.OnRequestWearables += SendWearables; + m_controllingClient.OnSetAppearance += SetAppearance; + m_controllingClient.OnCompleteMovementToRegion += CompleteMovement; + //m_controllingClient.OnCompleteMovementToRegion += SendInitialData; + m_controllingClient.OnAgentUpdate += HandleAgentUpdate; + m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit; + m_controllingClient.OnAgentSit += HandleAgentSit; + m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; + m_controllingClient.OnStartAnim += HandleStartAnim; + m_controllingClient.OnStopAnim += HandleStopAnim; + m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls; + m_controllingClient.OnAutoPilotGo += DoAutoPilot; + m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition); + + // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); + // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); + } + + private void SetDirectionVectors() + { + Dir_Vectors[0] = Vector3.UnitX; //FORWARD + Dir_Vectors[1] = -Vector3.UnitX; //BACK + Dir_Vectors[2] = Vector3.UnitY; //LEFT + Dir_Vectors[3] = -Vector3.UnitY; //RIGHT + Dir_Vectors[4] = Vector3.UnitZ; //UP + Dir_Vectors[5] = -Vector3.UnitZ; //DOWN + Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE + Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE + Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE + Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE + Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge + } + + private Vector3[] GetWalkDirectionVectors() + { + Vector3[] vector = new Vector3[11]; + vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD + vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK + vector[2] = Vector3.UnitY; //LEFT + vector[3] = -Vector3.UnitY; //RIGHT + vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP + vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN + vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE + vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE + vector[8] = Vector3.UnitY; //LEFT_NUDGE + vector[9] = -Vector3.UnitY; //RIGHT_NUDGE + vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE + return vector; + } + + private bool[] GetDirectionIsNudge() + { + bool[] isNudge = new bool[11]; + isNudge[0] = false; //FORWARD + isNudge[1] = false; //BACK + isNudge[2] = false; //LEFT + isNudge[3] = false; //RIGHT + isNudge[4] = false; //UP + isNudge[5] = false; //DOWN + isNudge[6] = true; //FORWARD_NUDGE + isNudge[7] = true; //BACK_NUDGE + isNudge[8] = true; //LEFT_NUDGE + isNudge[9] = true; //RIGHT_NUDGE + isNudge[10] = true; //DOWN_Nudge + return isNudge; + } + + + #endregion + + public uint GenerateClientFlags(UUID ObjectID) + { + return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID); + } + + /// + /// Send updates to the client about prims which have been placed on the update queue. We don't + /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent + /// timestamp has already been sent. + /// + public void SendPrimUpdates() + { + m_perfMonMS = Util.EnvironmentTickCount(); + + m_sceneViewer.SendPrimUpdates(); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + #region Status Methods + + /// + /// This turns a child agent, into a root agent + /// This is called when an agent teleports into a region, or if an + /// agent crosses into this region from a neighbor over the border + /// + public void MakeRootAgent(Vector3 pos, bool isFlying) + { + m_log.DebugFormat( + "[SCENE]: Upgrading child to root agent for {0} in {1}", + Name, m_scene.RegionInfo.RegionName); + + //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); + + IGroupsModule gm = m_scene.RequestModuleInterface(); + if (gm != null) + m_grouptitle = gm.GetGroupTitle(m_uuid); + + m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; + m_scene.SetRootAgentScene(m_uuid); + + // Moved this from SendInitialData to ensure that m_appearance is initialized + // before the inventory is processed in MakeRootAgent. This fixes a race condition + // related to the handling of attachments + //m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); + if (m_scene.TestBorderCross(pos, Cardinals.E)) + { + Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); + pos.X = crossedBorder.BorderLine.Z - 1; + } + + if (m_scene.TestBorderCross(pos, Cardinals.N)) + { + Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); + pos.Y = crossedBorder.BorderLine.Z - 1; + } + + //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet. + //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent, + //they'll bypass the landing point. But I can't think of any decent way of fixing this. + if (KnownChildRegionHandles.Count == 0) + { + ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); + if (land != null) + { + //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. + if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) + { + pos = land.LandData.UserLocation; + } + } + } + + if (pos.X < 0 || pos.Y < 0 || pos.Z < 0) + { + Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128); + + if (pos.X < 0) + { + emergencyPos.X = (int)Constants.RegionSize + pos.X; + if (!(pos.Y < 0)) + emergencyPos.Y = pos.Y; + if (!(pos.Z < 0)) + emergencyPos.Z = pos.Z; + } + if (pos.Y < 0) + { + emergencyPos.Y = (int)Constants.RegionSize + pos.Y; + if (!(pos.X < 0)) + emergencyPos.X = pos.X; + if (!(pos.Z < 0)) + emergencyPos.Z = pos.Z; + } + if (pos.Z < 0) + { + emergencyPos.Z = 128; + if (!(pos.Y < 0)) + emergencyPos.Y = pos.Y; + if (!(pos.X < 0)) + emergencyPos.X = pos.X; + } + } + + if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) + { + m_log.WarnFormat( + "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", + pos, Name, UUID); + + if (pos.X < 0f) pos.X = 0f; + if (pos.Y < 0f) pos.Y = 0f; + if (pos.Z < 0f) pos.Z = 0f; + } + + float localAVHeight = 1.56f; + if (m_avHeight != 127.0f) + { + localAVHeight = m_avHeight; + } + + float posZLimit = 0; + + if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) + posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; + + float newPosZ = posZLimit + localAVHeight / 2; + if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) + { + pos.Z = newPosZ; + } + AbsolutePosition = pos; + + AddToPhysicalScene(isFlying); + + if (m_forceFly) + { + m_physicsActor.Flying = true; + } + else if (m_flyDisabled) + { + m_physicsActor.Flying = false; + } + + if (m_appearance != null) + { + if (m_appearance.AvatarHeight > 0) + SetHeight(m_appearance.AvatarHeight); + } + else + { + m_log.ErrorFormat("[SCENE PRESENCE]: null appearance in MakeRoot in {0}", Scene.RegionInfo.RegionName); + // emergency; this really shouldn't happen + m_appearance = new AvatarAppearance(UUID); + } + + // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying + // avatar to return to the standing position in mid-air. On login it looks like this is being sent + // elsewhere anyway + // Animator.SendAnimPack(); + + m_scene.SwapRootAgentCount(false); + + //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid); + //if (userInfo != null) + // userInfo.FetchInventory(); + //else + // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid); + + // On the next prim update, all objects will be sent + // + m_sceneViewer.Reset(); + + m_isChildAgent = false; + + // send the animations of the other presences to me + m_scene.ForEachScenePresence(delegate(ScenePresence presence) + { + if (presence != this) + presence.Animator.SendAnimPackToClient(ControllingClient); + }); + + m_scene.EventManager.TriggerOnMakeRootAgent(this); + } + + /// + /// This turns a root agent into a child agent + /// when an agent departs this region for a neighbor, this gets called. + /// + /// It doesn't get called for a teleport. Reason being, an agent that + /// teleports out may not end up anywhere near this region + /// + public void MakeChildAgent() + { + // It looks like m_animator is set to null somewhere, and MakeChild + // is called after that. Probably in aborted teleports. + if (m_animator == null) + m_animator = new ScenePresenceAnimator(this); + else + Animator.ResetAnimations(); + +// m_log.DebugFormat( +// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", +// Name, UUID, m_scene.RegionInfo.RegionName); + + // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing, + // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated. + //Velocity = new Vector3(0, 0, 0); + + m_isChildAgent = true; + m_scene.SwapRootAgentCount(true); + RemoveFromPhysicalScene(); + + // FIXME: Set m_rootRegionHandle to the region handle of the scene this agent is moving into + + m_scene.EventManager.TriggerOnMakeChildAgent(this); + } + + /// + /// Removes physics plugin scene representation of this agent if it exists. + /// + private void RemoveFromPhysicalScene() + { + if (PhysicsActor != null) + { + m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; + m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; + m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); + m_physicsActor.UnSubscribeEvents(); + m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; + PhysicsActor = null; + } + } + + /// + /// + /// + /// + public void Teleport(Vector3 pos) + { + bool isFlying = false; + + if (m_physicsActor != null) + isFlying = m_physicsActor.Flying; + + RemoveFromPhysicalScene(); + Velocity = Vector3.Zero; + AbsolutePosition = pos; + AddToPhysicalScene(isFlying); + if (m_appearance != null) + { + if (m_appearance.AvatarHeight > 0) + SetHeight(m_appearance.AvatarHeight); + } + + SendTerseUpdateToAllClients(); + + } + + public void TeleportWithMomentum(Vector3 pos) + { + bool isFlying = false; + if (m_physicsActor != null) + isFlying = m_physicsActor.Flying; + + RemoveFromPhysicalScene(); + AbsolutePosition = pos; + AddToPhysicalScene(isFlying); + if (m_appearance != null) + { + if (m_appearance.AvatarHeight > 0) + SetHeight(m_appearance.AvatarHeight); + } + + SendTerseUpdateToAllClients(); + } + + /// + /// + /// + public void StopMovement() + { + } + + public void StopFlying() + { + ControllingClient.StopFlying(this); + } + + public void AddNeighbourRegion(ulong regionHandle, string cap) + { + lock (m_knownChildRegions) + { + if (!m_knownChildRegions.ContainsKey(regionHandle)) + { + uint x, y; + Utils.LongToUInts(regionHandle, out x, out y); + m_knownChildRegions.Add(regionHandle, cap); + } + } + } + + public void RemoveNeighbourRegion(ulong regionHandle) + { + lock (m_knownChildRegions) + { + if (m_knownChildRegions.ContainsKey(regionHandle)) + { + m_knownChildRegions.Remove(regionHandle); + //m_log.Debug(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); + } + } + } + + public void DropOldNeighbours(List oldRegions) + { + foreach (ulong handle in oldRegions) + { + RemoveNeighbourRegion(handle); + Scene.CapsModule.DropChildSeed(UUID, handle); + } + } + + public List GetKnownRegionList() + { + return new List(m_knownChildRegions.Keys); + } + + #endregion + + #region Event Handlers + + /// + /// Sets avatar height in the phyiscs plugin + /// + internal void SetHeight(float height) + { + m_avHeight = height; + if (PhysicsActor != null && !IsChildAgent) + { + Vector3 SetSize = new Vector3(0.45f, 0.6f, m_avHeight); + PhysicsActor.Size = SetSize; + } + } + + /// + /// Complete Avatar's movement into the region. + /// This is called upon a very important packet sent from the client, + /// so it's client-controlled. Never call this method directly. + /// + public void CompleteMovement(IClientAPI client) + { + //m_log.Debug("[SCENE PRESENCE]: CompleteMovement"); + + Vector3 look = Velocity; + if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) + { + look = new Vector3(0.99f, 0.042f, 0); + } + + // Prevent teleporting to an underground location + // (may crash client otherwise) + // + Vector3 pos = AbsolutePosition; + float ground = m_scene.GetGroundHeight(pos.X, pos.Y); + if (pos.Z < ground + 1.5f) + { + pos.Z = ground + 1.5f; + AbsolutePosition = pos; + } + m_isChildAgent = false; + bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + MakeRootAgent(AbsolutePosition, m_flying); + + if ((m_callbackURI != null) && !m_callbackURI.Equals("")) + { + m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI); + Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); + m_callbackURI = null; + } + + //m_log.DebugFormat("Completed movement"); + + m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); + SendInitialData(); + + // Create child agents in neighbouring regions + if (!m_isChildAgent) + { + IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); + if (m_agentTransfer != null) + m_agentTransfer.EnableChildAgents(this); + else + m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active"); + + IFriendsModule friendsModule = m_scene.RequestModuleInterface(); + if (friendsModule != null) + friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); + } + + } + + /// + /// Callback for the Camera view block check. Gets called with the results of the camera view block test + /// hitYN is true when there's something in the way. + /// + /// + /// + /// + /// + public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) + { + const float POSITION_TOLERANCE = 0.02f; + const float VELOCITY_TOLERANCE = 0.02f; + const float ROTATION_TOLERANCE = 0.02f; + + if (m_followCamAuto) + { + if (hitYN) + { + CameraConstraintActive = true; + //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance); + + Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint); + ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint))); + } + else + { + if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || + !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || + !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) + { + if (CameraConstraintActive) + { + ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f)); + CameraConstraintActive = false; + } + } + } + } + } + + /// + /// This is the event handler for client movement. If a client is moving, this event is triggering. + /// + public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) + { + //if (m_isChildAgent) + //{ + // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); + // return; + //} + + m_perfMonMS = Util.EnvironmentTickCount(); + + ++m_movementUpdateCount; + if (m_movementUpdateCount < 1) + m_movementUpdateCount = 1; + + #region Sanity Checking + + // This is irritating. Really. + if (!AbsolutePosition.IsFinite()) + { + RemoveFromPhysicalScene(); + m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); + + m_pos = m_LastFinitePos; + + if (!m_pos.IsFinite()) + { + m_pos.X = 127f; + m_pos.Y = 127f; + m_pos.Z = 127f; + m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); + } + + AddToPhysicalScene(false); + } + else + { + m_LastFinitePos = m_pos; + } + + #endregion Sanity Checking + + #region Inputs + + AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; + Quaternion bodyRotation = agentData.BodyRotation; + + // Camera location in world. We'll need to raytrace + // from this location from time to time. + m_CameraCenter = agentData.CameraCenter; + if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance) + { + ReprioritizeUpdates(); + m_lastCameraCenter = m_CameraCenter; + } + + // Use these three vectors to figure out what the agent is looking at + // Convert it to a Matrix and/or Quaternion + m_CameraAtAxis = agentData.CameraAtAxis; + m_CameraLeftAxis = agentData.CameraLeftAxis; + m_CameraUpAxis = agentData.CameraUpAxis; + + // The Agent's Draw distance setting + m_DrawDistance = agentData.Far; + + // Check if Client has camera in 'follow cam' or 'build' mode. + Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation); + + m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f) + && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; + + m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; + m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; + + #endregion Inputs + + if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) + { + StandUp(); + } + + //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); + // Raycast from the avatar's head to the camera to see if there's anything blocking the view + if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) + { + if (m_followCamAuto) + { + Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; + m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); + } + } + lock (scriptedcontrols) + { + if (scriptedcontrols.Count > 0) + { + SendControlToScripts((uint)flags); + flags = RemoveIgnoredControls(flags, IgnoredControls); + } + } + + if (m_autopilotMoving) + CheckAtSitTarget(); + + if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) + { + m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. + Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); + + // TODO: This doesn't prevent the user from walking yet. + // Setting parent ID would fix this, if we knew what value + // to use. Or we could add a m_isSitting variable. + //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); + SitGround = true; + } + + // In the future, these values might need to go global. + // Here's where you get them. + m_AgentControlFlags = flags; + m_headrotation = agentData.HeadRotation; + m_state = agentData.State; + + PhysicsActor actor = PhysicsActor; + if (actor == null) + { + return; + } + + bool update_movementflag = false; + + if (m_allowMovement && !SitGround) + { + if (agentData.UseClientAgentPosition) + { + m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; + m_moveToPositionTarget = agentData.ClientAgentPosition; + } + + int i = 0; + + bool update_rotation = false; + bool DCFlagKeyPressed = false; + Vector3 agent_control_v3 = Vector3.Zero; + Quaternion q = bodyRotation; + + bool oldflying = PhysicsActor.Flying; + + if (m_forceFly) + actor.Flying = true; + else if (m_flyDisabled) + actor.Flying = false; + else + actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + + if (actor.Flying != oldflying) + update_movementflag = true; + + if (q != m_bodyRot) + { + m_bodyRot = q; + update_rotation = true; + } + + //guilty until proven innocent.. + bool Nudging = true; + //Basically, if there is at least one non-nudge control then we don't need + //to worry about stopping the avatar + + if (m_parentID == 0) + { + bool bAllowUpdateMoveToPosition = false; + bool bResetMoveToPosition = false; + + Vector3[] dirVectors; + + // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying + // this prevents 'jumping' in inappropriate situations. + if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying)) + dirVectors = GetWalkDirectionVectors(); + else + dirVectors = Dir_Vectors; + + bool[] isNudge = GetDirectionIsNudge(); + + + + + + foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) + { + if (((uint)flags & (uint)DCF) != 0) + { + bResetMoveToPosition = true; + DCFlagKeyPressed = true; + try + { + agent_control_v3 += dirVectors[i]; + if (isNudge[i] == false) + { + Nudging = false; + } + } + catch (IndexOutOfRangeException) + { + // Why did I get this? + } + + if ((m_movementflag & (uint)DCF) == 0) + { + m_movementflag += (byte)(uint)DCF; + update_movementflag = true; + } + } + else + { + if ((m_movementflag & (uint)DCF) != 0) + { + m_movementflag -= (byte)(uint)DCF; + update_movementflag = true; + } + else + { + bAllowUpdateMoveToPosition = true; + } + } + i++; + } + //Paupaw:Do Proper PID for Autopilot here + if (bResetMoveToPosition) + { + m_moveToPositionTarget = Vector3.Zero; + m_moveToPositionInProgress = false; + update_movementflag = true; + bAllowUpdateMoveToPosition = false; + } + + if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) + { + //Check the error term of the current position in relation to the target position + if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) + { + // we are close enough to the target + m_moveToPositionTarget = Vector3.Zero; + m_moveToPositionInProgress = false; + update_movementflag = true; + } + else + { + try + { + // move avatar in 2D at one meter/second towards target, in avatar coordinate frame. + // This movement vector gets added to the velocity through AddNewMovement(). + // Theoretically we might need a more complex PID approach here if other + // unknown forces are acting on the avatar and we need to adaptively respond + // to such forces, but the following simple approach seems to works fine. + Vector3 LocalVectorToTarget3D = + (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords + * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords + // Ignore z component of vector + Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); + LocalVectorToTarget2D.Normalize(); + + //We're not nudging + Nudging = false; + agent_control_v3 += LocalVectorToTarget2D; + + // update avatar movement flags. the avatar coordinate system is as follows: + // + // +X (forward) + // + // ^ + // | + // | + // | + // | + // (left) +Y <--------o--------> -Y + // avatar + // | + // | + // | + // | + // v + // -X + // + + // based on the above avatar coordinate system, classify the movement into + // one of left/right/back/forward. + if (LocalVectorToTarget2D.Y > 0)//MoveLeft + { + m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; + //AgentControlFlags + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; + update_movementflag = true; + } + else if (LocalVectorToTarget2D.Y < 0) //MoveRight + { + m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; + update_movementflag = true; + } + if (LocalVectorToTarget2D.X < 0) //MoveBack + { + m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; + update_movementflag = true; + } + else if (LocalVectorToTarget2D.X > 0) //Move Forward + { + m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; + update_movementflag = true; + } + } + catch (Exception e) + { + //Avoid system crash, can be slower but... + m_log.DebugFormat("Crash! {0}", e.ToString()); + } + } + } + } + + // Cause the avatar to stop flying if it's colliding + // with something with the down arrow pressed. + + // Only do this if we're flying + if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly) + { + // Landing detection code + + // Are the landing controls requirements filled? + bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || + ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); + + // Are the collision requirements fulfilled? + bool colliding = (m_physicsActor.IsColliding == true); + + if (m_physicsActor.Flying && colliding && controlland) + { + // nesting this check because LengthSquared() is expensive and we don't + // want to do it every step when flying. + if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) + StopFlying(); + } + } + + if (update_movementflag || (update_rotation && DCFlagKeyPressed)) + { + // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed)); + // m_log.DebugFormat( + // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); + + AddNewMovement(agent_control_v3, q, Nudging); + + + } + } + + if (update_movementflag && !SitGround) + Animator.UpdateMovementAnimations(); + + m_scene.EventManager.TriggerOnClientMovement(this); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client) + { + m_autopilotMoving = true; + m_autoPilotTarget = Pos; + m_sitAtAutoTarget = false; + PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; + //proxy.PCode = (byte)PCode.ParticleSystem; + proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); + proxyObjectGroup.AttachToScene(m_scene); + + // Commented out this code since it could never have executed, but might still be informative. +// if (proxyObjectGroup != null) +// { + proxyObjectGroup.SendGroupFullUpdate(); + remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); + m_scene.DeleteSceneObject(proxyObjectGroup, false); +// } +// else +// { +// m_autopilotMoving = false; +// m_autoPilotTarget = Vector3.Zero; +// ControllingClient.SendAlertMessage("Autopilot cancelled"); +// } + } + + public void DoMoveToPosition(Object sender, string method, List args) + { + try + { + float locx = 0f; + float locy = 0f; + float locz = 0f; + uint regionX = 0; + uint regionY = 0; + try + { + Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); + locx = Convert.ToSingle(args[0]) - (float)regionX; + locy = Convert.ToSingle(args[1]) - (float)regionY; + locz = Convert.ToSingle(args[2]); + } + catch (InvalidCastException) + { + m_log.Error("[CLIENT]: Invalid autopilot request"); + return; + } + m_moveToPositionInProgress = true; + m_moveToPositionTarget = new Vector3(locx, locy, locz); + } + catch (Exception ex) + { + //Why did I get this error? + m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex); + } + } + + private void CheckAtSitTarget() + { + //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString()); + if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5) + { + if (m_sitAtAutoTarget) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID); + if (part != null) + { + AbsolutePosition = part.AbsolutePosition; + Velocity = Vector3.Zero; + SendFullUpdateToAllClients(); + + HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ?? + } + //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); + m_requestedSitTargetUUID = UUID.Zero; + } + /* + else + { + //ControllingClient.SendAlertMessage("Autopilot cancelled"); + //SendTerseUpdateToAllClients(); + //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; + //proxy.PCode = (byte)PCode.ParticleSystem; + ////uint nextUUID = m_scene.NextLocalId; + + //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy); + //if (proxyObjectGroup != null) + //{ + //proxyObjectGroup.SendGroupFullUpdate(); + //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); + //m_scene.DeleteSceneObject(proxyObjectGroup); + //} + } + */ + m_autoPilotTarget = Vector3.Zero; + m_autopilotMoving = false; + } + } + /// + /// Perform the logic necessary to stand the avatar up. This method also executes + /// the stand animation. + /// + public void StandUp() + { + SitGround = false; + + if (m_parentID != 0) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); + if (part != null) + { + part.TaskInventory.LockItemsForRead(true); + TaskInventoryDictionary taskIDict = part.TaskInventory; + if (taskIDict != null) + { + foreach (UUID taskID in taskIDict.Keys) + { + UnRegisterControlEventsToScript(LocalId, taskID); + taskIDict[taskID].PermsMask &= ~( + 2048 | //PERMISSION_CONTROL_CAMERA + 4); // PERMISSION_TAKE_CONTROLS + } + } + part.TaskInventory.LockItemsForRead(false); + // Reset sit target. + if (part.GetAvatarOnSitTarget() == UUID) + part.SetAvatarOnSitTarget(UUID.Zero); + m_parentPosition = part.GetWorldPosition(); + ControllingClient.SendClearFollowCamProperties(part.ParentUUID); + } + // part.GetWorldRotation() is the rotation of the object being sat on + // Rotation is the sittiing Av's rotation + + Quaternion partRot; +// if (part.LinkNum == 1) +// { // Root prim of linkset +// partRot = part.ParentGroup.RootPart.RotationOffset; +// } +// else +// { // single or child prim + +// } + if (part == null) //CW: Part may be gone. llDie() for example. + { + partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + else + { + partRot = part.GetWorldRotation(); + } + + Quaternion partIRot = Quaternion.Inverse(partRot); + + Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av + Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av + + + if (m_physicsActor == null) + { + AddToPhysicalScene(false); + } + //CW: If the part isn't null then we can set the current position + if (part != null) + { + Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset! + AbsolutePosition = avWorldStandUp; //KF: Fix stand up. + part.IsOccupied = false; + part.ParentGroup.DeleteAvatar(ControllingClient.AgentId); + } + else + { + //CW: Since the part doesn't exist, a coarse standup position isn't an issue + AbsolutePosition = m_lastWorldPosition; + } + + m_parentPosition = Vector3.Zero; + m_parentID = 0; + m_linkedPrim = UUID.Zero; + m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + SendFullUpdateToAllClients(); + m_requestedSitTargetID = 0; + + if ((m_physicsActor != null) && (m_avHeight > 0)) + { + SetHeight(m_avHeight); + } + } + Animator.TrySetMovementAnimation("STAND"); + } + + private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) + { + SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID); + if (targetPart == null) + return null; + + // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used. + // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used. + + // Get our own copy of the part array, and sort into the order we want to test + SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts(); + Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2) + { + // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1) + int linkNum1 = p1==targetPart ? -1 : p1.LinkNum; + int linkNum2 = p2==targetPart ? -1 : p2.LinkNum; + return linkNum1 - linkNum2; + } + ); + + //look for prims with explicit sit targets that are available + foreach (SceneObjectPart part in partArray) + { + // Is a sit target available? + Vector3 avSitOffSet = part.SitTargetPosition; + Quaternion avSitOrientation = part.SitTargetOrientation; + UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); + bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero); + bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. + if (SitTargetisSet && !SitTargetOccupied) + { + //switch the target to this prim + return part; + } + } + + // no explicit sit target found - use original target + return targetPart; + } + + private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) + { + bool autopilot = true; + Vector3 autopilotTarget = new Vector3(); + Quaternion sitOrientation = Quaternion.Identity; + Vector3 pos = new Vector3(); + Vector3 cameraEyeOffset = Vector3.Zero; + Vector3 cameraAtOffset = Vector3.Zero; + bool forceMouselook = false; + + //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); + SceneObjectPart part = FindNextAvailableSitTarget(targetID); + if (part == null) return; + + // TODO: determine position to sit at based on scene geometry; don't trust offset from client + // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it + + // part is the prim to sit on + // offset is the world-ref vector distance from that prim center to the click-spot + // UUID is the UUID of the Avatar doing the clicking + + m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation + + // Is a sit target available? + Vector3 avSitOffSet = part.SitTargetPosition; + Quaternion avSitOrientation = part.SitTargetOrientation; + + bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. + // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); + Quaternion partRot; +// if (part.LinkNum == 1) +// { // Root prim of linkset +// partRot = part.ParentGroup.RootPart.RotationOffset; +// } +// else +// { // single or child prim + partRot = part.GetWorldRotation(); +// } + Quaternion partIRot = Quaternion.Inverse(partRot); +//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet); + // Sit analysis rewritten by KF 091125 + if (SitTargetisSet) // scipted sit + { + if (!part.IsOccupied) + { +//Console.WriteLine("Scripted, unoccupied"); + part.SetAvatarOnSitTarget(UUID); // set that Av will be on it + offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one + + Quaternion nrot = avSitOrientation; + if (!part.IsRoot) + { + nrot = part.RotationOffset * avSitOrientation; + } + sitOrientation = nrot; // Change rotatione to the scripted one + OffsetRotation = nrot; + autopilot = false; // Jump direct to scripted llSitPos() + } + else + { +//Console.WriteLine("Scripted, occupied"); + return; + } + } + else // Not Scripted + { + if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) + { + // large prim & offset, ignore if other Avs sitting +// offset.Z -= 0.05f; + m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked + autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point + +//Console.WriteLine(" offset ={0}", offset); +//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos); +//Console.WriteLine(" autopilotTarget={0}", autopilotTarget); + + } + else // small offset + { +//Console.WriteLine("Small offset"); + if (!part.IsOccupied) + { + m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center + autopilotTarget = part.AbsolutePosition; +//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget); + } + else return; // occupied small + } // end large/small + } // end Scripted/not + cameraAtOffset = part.GetCameraAtOffset(); + cameraEyeOffset = part.GetCameraEyeOffset(); + forceMouselook = part.GetForceMouselook(); + if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); // + if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); // + + if (m_physicsActor != null) + { + // If we're not using the client autopilot, we're immediately warping the avatar to the location + // We can remove the physicsActor until they stand up. + m_sitAvatarHeight = m_physicsActor.Size.Z; + if (autopilot) + { // its not a scripted sit +// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) + if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) ) + { + autopilot = false; // close enough + m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup. + Not using the part's position because returning the AV to the last known standing + position is likely to be more friendly, isn't it? */ + RemoveFromPhysicalScene(); + AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target + } // else the autopilot will get us close + } + else + { // its a scripted sit + m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup. + I *am* using the part's position this time because we have no real idea how far away + the avatar is from the sit target. */ + RemoveFromPhysicalScene(); + } + } + else return; // physactor is null! + + Vector3 offsetr; // = offset * partIRot; + // KF: In a linkset, offsetr needs to be relative to the group root! 091208 + // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot); + // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error. + // { // Single, or Root prim of linkset, target is ClickOffset * RootRot + //offsetr = offset * partIRot; +// + // else + // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot) + // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + + // (offset * partRot); + // } + +//Console.WriteLine(" "); +//Console.WriteLine("link number ={0}", part.LinkNum); +//Console.WriteLine("Prim offset ={0}", part.OffsetPosition ); +//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset); +//Console.WriteLine("Click offst ={0}", offset); +//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation()); +//Console.WriteLine("offsetr ={0}", offsetr); +//Console.WriteLine("Camera At ={0}", cameraAtOffset); +//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); + + //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child + ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); + + m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target + // This calls HandleAgentSit twice, once from here, and the client calls + // HandleAgentSit itself after it gets to the location + // It doesn't get to the location until we've moved them there though + // which happens in HandleAgentSit :P + m_autopilotMoving = autopilot; + m_autoPilotTarget = autopilotTarget; + m_sitAtAutoTarget = autopilot; + m_initialSitTarget = autopilotTarget; + if (!autopilot) + HandleAgentSit(remoteClient, UUID); + } + + public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset) + { + if (m_parentID != 0) + { + StandUp(); + } + m_nextSitAnimation = "SIT"; + + //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); + SceneObjectPart part = FindNextAvailableSitTarget(targetID); + + if (part != null) + { + if (!String.IsNullOrEmpty(part.SitAnimation)) + { + m_nextSitAnimation = part.SitAnimation; + } + m_requestedSitTargetID = part.LocalId; + //m_requestedSitOffset = offset; + m_requestedSitTargetUUID = targetID; + + m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); + + if (m_scene.PhysicsScene.SupportsRayCast()) + { + //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback()); + //SitRayCastAvatarPosition(part); + //return; + } + } + else + { + + m_log.Warn("Sit requested on unknown object: " + targetID.ToString()); + } + + + + SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity); + } + /* + public void SitRayCastAvatarPosition(SceneObjectPart part) + { + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = AbsolutePosition; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse); + } + + public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) + { + SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); + if (part != null) + { + if (hitYN) + { + if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) + { + SitRaycastFindEdge(collisionPoint, normal); + m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); + } + else + { + SitRayCastAvatarPositionCameraZ(part); + } + } + else + { + SitRayCastAvatarPositionCameraZ(part); + } + } + else + { + ControllingClient.SendAlertMessage("Sit position no longer exists"); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + + } + + public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part) + { + // Next, try to raycast from the camera Z position + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse); + } + + public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) + { + SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); + if (part != null) + { + if (hitYN) + { + if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) + { + SitRaycastFindEdge(collisionPoint, normal); + m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal); + } + else + { + SitRayCastCameraPosition(part); + } + } + else + { + SitRayCastCameraPosition(part); + } + } + else + { + ControllingClient.SendAlertMessage("Sit position no longer exists"); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + + } + + public void SitRayCastCameraPosition(SceneObjectPart part) + { + // Next, try to raycast from the camera position + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = CameraPosition; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse); + } + + public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) + { + SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); + if (part != null) + { + if (hitYN) + { + if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) + { + SitRaycastFindEdge(collisionPoint, normal); + m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); + } + else + { + SitRayHorizontal(part); + } + } + else + { + SitRayHorizontal(part); + } + } + else + { + ControllingClient.SendAlertMessage("Sit position no longer exists"); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + + } + + public void SitRayHorizontal(SceneObjectPart part) + { + // Next, try to raycast from the avatar position to fwd + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = CameraPosition; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse); + } + + public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) + { + SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); + if (part != null) + { + if (hitYN) + { + if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) + { + SitRaycastFindEdge(collisionPoint, normal); + m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); + // Next, try to raycast from the camera position + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = CameraPosition; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition); + } + else + { + ControllingClient.SendAlertMessage("Sit position not accessable."); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + } + else + { + ControllingClient.SendAlertMessage("Sit position not accessable."); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + } + else + { + ControllingClient.SendAlertMessage("Sit position no longer exists"); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + + } + + private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal) + { + int i = 0; + //throw new NotImplementedException(); + //m_requestedSitTargetUUID = UUID.Zero; + //m_requestedSitTargetID = 0; + //m_requestedSitOffset = Vector3.Zero; + + SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity); + } + */ + public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation) + { + if (m_parentID != 0) + { + StandUp(); + } + if (!String.IsNullOrEmpty(sitAnimation)) + { + m_nextSitAnimation = sitAnimation; + } + else + { + m_nextSitAnimation = "SIT"; + } + + //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); + SceneObjectPart part = FindNextAvailableSitTarget(targetID); + if (part != null) + { + m_requestedSitTargetID = part.LocalId; + //m_requestedSitOffset = offset; + m_requestedSitTargetUUID = targetID; + + m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); + + if (m_scene.PhysicsScene.SupportsRayCast()) + { + //SitRayCastAvatarPosition(part); + //return; + } + } + else + { + m_log.Warn("Sit requested on unknown object: " + targetID); + } + + SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity); + } + + public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) + { + if (!String.IsNullOrEmpty(m_nextSitAnimation)) + { + HandleAgentSit(remoteClient, agentID, m_nextSitAnimation); + } + else + { + HandleAgentSit(remoteClient, agentID, "SIT"); + } + } + + public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); + + if (m_sitAtAutoTarget || !m_autopilotMoving) + { + if (part != null) + { +//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation()); + if (part.GetAvatarOnSitTarget() == UUID) + { +//Console.WriteLine("Scripted Sit"); + // Scripted sit + Vector3 sitTargetPos = part.SitTargetPosition; + Quaternion sitTargetOrient = part.SitTargetOrientation; + m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); + m_pos += SIT_TARGET_ADJUSTMENT; + if (!part.IsRoot) + { + m_pos *= part.RotationOffset; + } + m_bodyRot = sitTargetOrient; + m_parentPosition = part.AbsolutePosition; + part.IsOccupied = true; + part.ParentGroup.AddAvatar(agentID); +Console.WriteLine("Scripted Sit ofset {0}", m_pos); + } + else + { + // if m_avUnscriptedSitPos is zero then Av sits above center + // Else Av sits at m_avUnscriptedSitPos + + // Non-scripted sit by Kitto Flora 21Nov09 + // Calculate angle of line from prim to Av + Quaternion partIRot; +// if (part.LinkNum == 1) +// { // Root prim of linkset +// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); +// } +// else +// { // single or child prim + partIRot = Quaternion.Inverse(part.GetWorldRotation()); +// } + Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos; + float y_diff = (m_avInitialPos.Y - sitTargetPos.Y); + float x_diff = ( m_avInitialPos.X - sitTargetPos.X); + if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0 + if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0 + float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff); + // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'. + // Av sits at world euler <0,0, z>, translated by part rotation + m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click + + m_parentPosition = part.AbsolutePosition; + part.IsOccupied = true; + part.ParentGroup.AddAvatar(agentID); + m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation + (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center + (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) + + m_avUnscriptedSitPos; // adds click offset, if any + //Set up raytrace to find top surface of prim + Vector3 size = part.Scale; + float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); + Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); + Vector3 down = new Vector3(0f, 0f, -1f); +//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag); + m_scene.PhysicsScene.RaycastWorld( + start, // Vector3 position, + down, // Vector3 direction, + mag, // float length, + SitAltitudeCallback); // retMethod + } // end scripted/not + } + else // no Av + { + return; + } + } + + //We want our offsets to reference the root prim, not the child we may have sat on + if (!part.IsRoot) + { + m_parentID = part.ParentGroup.RootPart.LocalId; + m_pos += part.OffsetPosition; + } + else + { + m_parentID = m_requestedSitTargetID; + } + + m_linkedPrim = part.UUID; + + Velocity = Vector3.Zero; + RemoveFromPhysicalScene(); + Animator.TrySetMovementAnimation(sitAnimation); + SendFullUpdateToAllClients(); + SendTerseUpdateToAllClients(); + } + + public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal) + { + // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer + // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height. + if(hitYN) + { + // m_pos = Av offset from prim center to make look like on center + // m_parentPosition = Actual center pos of prim + // collisionPoint = spot on prim where we want to sit + // collisionPoint.Z = global sit surface height + SceneObjectPart part = m_scene.GetSceneObjectPart(localid); + Quaternion partIRot; +// if (part.LinkNum == 1) +/// { // Root prim of linkset +// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); +// } +// else +// { // single or child prim + partIRot = Quaternion.Inverse(part.GetWorldRotation()); +// } + if (m_initialSitTarget != null) + { + float offZ = collisionPoint.Z - m_initialSitTarget.Z; + Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction + //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); + m_pos += offset; + // ControllingClient.SendClearFollowCamProperties(part.UUID); + } + + } + } // End SitAltitudeCallback KF. + + /// + /// Event handler for the 'Always run' setting on the client + /// Tells the physics plugin to increase speed of movement. + /// + public void HandleSetAlwaysRun(IClientAPI remoteClient, bool pSetAlwaysRun) + { + m_setAlwaysRun = pSetAlwaysRun; + if (PhysicsActor != null) + { + PhysicsActor.SetAlwaysRun = pSetAlwaysRun; + } + } + + public void HandleStartAnim(IClientAPI remoteClient, UUID animID) + { + Animator.AddAnimation(animID, UUID.Zero); + } + + public void HandleStopAnim(IClientAPI remoteClient, UUID animID) + { + Animator.RemoveAnimation(animID); + } + + /// + /// Rotate the avatar to the given rotation and apply a movement in the given relative vector + /// + /// The vector in which to move. This is relative to the rotation argument + /// The direction in which this avatar should now face. + public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging) + { + if (m_isChildAgent) + { + // WHAT??? + m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); + + // we have to reset the user's child agent connections. + // Likely, here they've lost the eventqueue for other regions so border + // crossings will fail at this point unless we reset them. + + List regions = new List(KnownChildRegionHandles); + regions.Remove(m_scene.RegionInfo.RegionHandle); + + MakeRootAgent(new Vector3(127f, 127f, 127f), true); + + // Async command + if (m_scene.SceneGridService != null) + { + m_scene.SceneGridService.SendCloseChildAgentConnections(UUID, regions); + + // Give the above command some time to try and close the connections. + // this is really an emergency.. so sleep, or we'll get all discombobulated. + System.Threading.Thread.Sleep(500); + } + + if (m_scene.SceneGridService != null) + { + IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); + if (m_agentTransfer != null) + m_agentTransfer.EnableChildAgents(this); + } + + return; + } + + m_perfMonMS = Util.EnvironmentTickCount(); + + Rotation = rotation; + Vector3 direc = vec * rotation; + direc.Normalize(); + PhysicsActor actor = m_physicsActor; + if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up. + + direc *= 0.03f * 128f * m_speedModifier; + + if (actor != null) + { + if (actor.Flying) + { + direc *= 4.0f; + //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); + //bool colliding = (m_physicsActor.IsColliding==true); + //if (controlland) + // m_log.Info("[AGENT]: landCommand"); + //if (colliding) + // m_log.Info("[AGENT]: colliding"); + //if (m_physicsActor.Flying && colliding && controlland) + //{ + // StopFlying(); + // m_log.Info("[AGENT]: Stop FLying"); + //} + } + else if (!actor.Flying && actor.IsColliding) + { + if (direc.Z > 2.0f) + { + if(m_animator.m_animTickJump == -1) + { + direc.Z *= 3.0f; // jump + } + else + { + direc.Z *= 0.1f; // prejump + } + /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs + Animator.TrySetMovementAnimation("PREJUMP"); + Animator.TrySetMovementAnimation("JUMP"); + */ + } + } + } + + // TODO: Add the force instead of only setting it to support multiple forces per frame? + m_forceToApply = direc; + m_isNudging = Nudging; + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + #endregion + + #region Overridden Methods + + public override void Update() + { + const float ROTATION_TOLERANCE = 0.01f; + const float VELOCITY_TOLERANCE = 0.001f; + const float POSITION_TOLERANCE = 0.05f; + //const int TIME_MS_TOLERANCE = 3000; + + + + if (m_isChildAgent == false) + { +// PhysicsActor actor = m_physicsActor; + + // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to + // grab the latest PhysicsActor velocity, whereas m_velocity is often + // storing a requested force instead of an actual traveling velocity + + // Throw away duplicate or insignificant updates + if (!m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || + !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || + !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) + //Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) + { + SendTerseUpdateToAllClients(); + + // Update the "last" values + m_lastPosition = m_pos; + m_lastRotation = m_bodyRot; + m_lastVelocity = Velocity; + //m_lastTerseSent = Environment.TickCount; + } + + // followed suggestion from mic bowman. reversed the two lines below. + if (m_parentID == 0 && m_physicsActor != null || m_parentID != 0) // Check that we have a physics actor or we're sitting on something + CheckForBorderCrossing(); + CheckForSignificantMovement(); // sends update to the modules. + } + + //Sending prim updates AFTER the avatar terse updates are sent + SendPrimUpdates(); + } + + #endregion + + #region Update Client(s) + + /// + /// Sends a location update to the client connected to this scenePresence + /// + /// + public void SendTerseUpdateToClient(IClientAPI remoteClient) + { + // If the client is inactive, it's getting its updates from another + // server. + if (remoteClient.IsActive) + { + m_perfMonMS = Util.EnvironmentTickCount(); + + PhysicsActor actor = m_physicsActor; + Vector3 velocity = (actor != null) ? actor.Velocity : Vector3.Zero; + + Vector3 pos = m_pos; + pos.Z += m_appearance.HipOffset; + + //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); + + remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + m_scene.StatsReporter.AddAgentUpdates(1); + } + } + + /// + /// Send a location/velocity/accelleration update to all agents in scene + /// + public void SendTerseUpdateToAllClients() + { + m_perfMonMS = Util.EnvironmentTickCount(); + + m_scene.ForEachClient(SendTerseUpdateToClient); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + public void SendCoarseLocations(List coarseLocations, List avatarUUIDs) + { + SendCourseLocationsMethod d = m_sendCourseLocationsMethod; + if (d != null) + { + d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); + } + } + + public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) + { + if (d != null) + m_sendCourseLocationsMethod = d; + } + + public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs) + { + m_perfMonMS = Util.EnvironmentTickCount(); + m_controllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + /// + /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar) + /// + /// + public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar) + { + // 2 stage check is needed. + if (remoteAvatar == null) + return; + IClientAPI cl=remoteAvatar.ControllingClient; + if (cl == null) + return; + if (m_appearance.Texture == null) + return; + + Vector3 pos = m_pos; + pos.Z += m_appearance.HipOffset; + + remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this); + m_scene.StatsReporter.AddAgentUpdates(1); + } + + /// + /// Tell *ALL* agents about this agent + /// + public void SendInitialFullUpdateToAllClients() + { + m_perfMonMS = Util.EnvironmentTickCount(); + int avUpdates = 0; + m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + ++avUpdates; + // only send if this is the root (children are only "listening posts" in a foreign region) + if (!IsChildAgent) + { + SendFullUpdateToOtherClient(avatar); + } + + if (avatar.LocalId != LocalId) + { + if (!avatar.IsChildAgent) + { + avatar.SendFullUpdateToOtherClient(this); + avatar.SendAppearanceToOtherAgent(this); + avatar.Animator.SendAnimPackToClient(ControllingClient); + } + } + }); + + m_scene.StatsReporter.AddAgentUpdates(avUpdates); + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + + //Animator.SendAnimPack(); + } + + public void SendFullUpdateToAllClients() + { + m_perfMonMS = Util.EnvironmentTickCount(); + + // only send update from root agents to other clients; children are only "listening posts" + int count = 0; + m_scene.ForEachScenePresence(delegate(ScenePresence sp) + { + if (sp.IsChildAgent) + return; + SendFullUpdateToOtherClient(sp); + ++count; + }); + m_scene.StatsReporter.AddAgentUpdates(count); + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + + Animator.SendAnimPack(); + } + + /// + /// Do everything required once a client completes its movement into a region + /// + public void SendInitialData() + { + // Moved this into CompleteMovement to ensure that m_appearance is initialized before + // the inventory arrives + // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); + + Vector3 pos = m_pos; + pos.Z += m_appearance.HipOffset; + + m_controllingClient.SendAvatarDataImmediate(this); + + SendInitialFullUpdateToAllClients(); + SendAppearanceToAllOtherAgents(); + } + + /// + /// Tell the client for this scene presence what items it should be wearing now + /// + public void SendWearables() + { + m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name); + + ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); + } + + /// + /// + /// + public void SendAppearanceToAllOtherAgents() + { + m_perfMonMS = Util.EnvironmentTickCount(); + + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + if (scenePresence.UUID != UUID) + { + SendAppearanceToOtherAgent(scenePresence); + } + }); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + /// + /// Send appearance data to an agent that isn't this one. + /// + /// + public void SendAppearanceToOtherAgent(ScenePresence avatar) + { + avatar.ControllingClient.SendAppearance( + m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes()); + } + + /// + /// Set appearance data (textureentry and slider settings) received from the client + /// + /// + /// + public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams) + { + if (m_physicsActor != null) + { + if (!IsChildAgent) + { + // This may seem like it's redundant, remove the avatar from the physics scene + // just to add it back again, but it saves us from having to update + // 3 variables 10 times a second. + bool flyingTemp = m_physicsActor.Flying; + RemoveFromPhysicalScene(); + //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor); + + //PhysicsActor = null; + + AddToPhysicalScene(flyingTemp); + } + } + + #region Bake Cache Check + + if (textureEntry != null) + { + for (int i = 0; i < BAKE_INDICES.Length; i++) + { + int j = BAKE_INDICES[i]; + Primitive.TextureEntryFace face = textureEntry.FaceTextures[j]; + + if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) + { + if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) + { + m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name); + this.ControllingClient.SendRebakeAvatarTextures(face.TextureID); + } + } + } + + } + + + #endregion Bake Cache Check + + m_appearance.SetAppearance(textureEntry, visualParams); + if (m_appearance.AvatarHeight > 0) + SetHeight(m_appearance.AvatarHeight); + + // This is not needed, because only the transient data changed + //AvatarData adata = new AvatarData(m_appearance); + //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); + + SendAppearanceToAllOtherAgents(); + if (!m_startAnimationSet) + { + Animator.UpdateMovementAnimations(); + m_startAnimationSet = true; + } + + Vector3 pos = m_pos; + pos.Z += m_appearance.HipOffset; + + m_controllingClient.SendAvatarDataImmediate(this); + } + + public void SetWearable(int wearableId, AvatarWearable wearable) + { + m_appearance.SetWearable(wearableId, wearable); + AvatarData adata = new AvatarData(m_appearance); + m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); + m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); + } + + // Because appearance setting is in a module, we actually need + // to give it access to our appearance directly, otherwise we + // get a synchronization issue. + public AvatarAppearance Appearance + { + get { return m_appearance; } + set { m_appearance = value; } + } + + #endregion + + #region Significant Movement Method + + /// + /// This checks for a significant movement and sends a courselocationchange update + /// + protected void CheckForSignificantMovement() + { + // Movement updates for agents in neighboring regions are sent directly to clients. + // This value only affects how often agent positions are sent to neighbor regions + // for things such as distance-based update prioritization + const float SIGNIFICANT_MOVEMENT = 2.0f; + + if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT) + { + posLastSignificantMove = AbsolutePosition; + m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient); + } + + // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m + if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || + Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance) + { + m_lastChildAgentUpdatePosition = AbsolutePosition; + m_lastChildAgentUpdateCamPosition = CameraPosition; + + ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); + cadu.ActiveGroupID = UUID.Zero.Guid; + cadu.AgentID = UUID.Guid; + cadu.alwaysrun = m_setAlwaysRun; + cadu.AVHeight = m_avHeight; + Vector3 tempCameraCenter = m_CameraCenter; + cadu.cameraPosition = tempCameraCenter; + cadu.drawdistance = m_DrawDistance; + cadu.GroupAccess = 0; + cadu.Position = AbsolutePosition; + cadu.regionHandle = m_rootRegionHandle; + float multiplier = 1; + int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); + if (innacurateNeighbors != 0) + { + multiplier = 1f / (float)innacurateNeighbors; + } + if (multiplier <= 0f) + { + multiplier = 0.25f; + } + + //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); + cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); + cadu.Velocity = Velocity; + + AgentPosition agentpos = new AgentPosition(); + agentpos.CopyFrom(cadu); + + m_scene.SendOutChildAgentUpdates(agentpos, this); + } + } + + #endregion + + #region Border Crossing Methods + + /// + /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion + /// + protected void CheckForBorderCrossing() + { + if (IsChildAgent) + return; + + Vector3 pos2 = AbsolutePosition; + Vector3 vel = Velocity; + int neighbor = 0; + int[] fix = new int[2]; + + float timeStep = 0.1f; + pos2.X = pos2.X + (vel.X*timeStep); + pos2.Y = pos2.Y + (vel.Y*timeStep); + pos2.Z = pos2.Z + (vel.Z*timeStep); + + if (!IsInTransit) + { + // Checks if where it's headed exists a region + + bool needsTransit = false; + if (m_scene.TestBorderCross(pos2, Cardinals.W)) + { + if (m_scene.TestBorderCross(pos2, Cardinals.S)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.SW, ref fix); + } + else if (m_scene.TestBorderCross(pos2, Cardinals.N)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.NW, ref fix); + } + else + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.W, ref fix); + } + } + else if (m_scene.TestBorderCross(pos2, Cardinals.E)) + { + if (m_scene.TestBorderCross(pos2, Cardinals.S)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.SE, ref fix); + } + else if (m_scene.TestBorderCross(pos2, Cardinals.N)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.NE, ref fix); + } + else + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.E, ref fix); + } + } + else if (m_scene.TestBorderCross(pos2, Cardinals.S)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.S, ref fix); + } + else if (m_scene.TestBorderCross(pos2, Cardinals.N)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.N, ref fix); + } + + + // Makes sure avatar does not end up outside region + if (neighbor <= 0) + { + if (!needsTransit) + { + if (m_requestedSitTargetUUID == UUID.Zero) + { + Vector3 pos = AbsolutePosition; + if (AbsolutePosition.X < 0) + pos.X += Velocity.X; + else if (AbsolutePosition.X > Constants.RegionSize) + pos.X -= Velocity.X; + if (AbsolutePosition.Y < 0) + pos.Y += Velocity.Y; + else if (AbsolutePosition.Y > Constants.RegionSize) + pos.Y -= Velocity.Y; + AbsolutePosition = pos; + } + } + } + else if (neighbor > 0) + CrossToNewRegion(); + } + else + { + RemoveFromPhysicalScene(); + // This constant has been inferred from experimentation + // I'm not sure what this value should be, so I tried a few values. + timeStep = 0.04f; + pos2 = AbsolutePosition; + pos2.X = pos2.X + (vel.X * timeStep); + pos2.Y = pos2.Y + (vel.Y * timeStep); + pos2.Z = pos2.Z + (vel.Z * timeStep); + m_pos = pos2; + } + } + + protected int HaveNeighbor(Cardinals car, ref int[] fix) + { + uint neighbourx = m_regionInfo.RegionLocX; + uint neighboury = m_regionInfo.RegionLocY; + + int dir = (int)car; + + if (dir > 1 && dir < 5) //Heading East + neighbourx++; + else if (dir > 5) // Heading West + neighbourx--; + + if (dir < 3 || dir == 8) // Heading North + neighboury++; + else if (dir > 3 && dir < 7) // Heading Sout + neighboury--; + + int x = (int)(neighbourx * Constants.RegionSize); + int y = (int)(neighboury * Constants.RegionSize); + GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y); + + if (neighbourRegion == null) + { + fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx); + fix[1] = (int)(m_regionInfo.RegionLocY - neighboury); + return dir * (-1); + } + else + return dir; + } + + /// + /// Moves the agent outside the region bounds + /// Tells neighbor region that we're crossing to it + /// If the neighbor accepts, remove the agent's viewable avatar from this scene + /// set them to a child agent. + /// + protected void CrossToNewRegion() + { + InTransit(); + try + { + m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying); + } + catch + { + m_scene.CrossAgentToNewRegion(this, false); + } + } + + public void InTransit() + { + m_inTransit = true; + + if ((m_physicsActor != null) && m_physicsActor.Flying) + m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY; + else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) + m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY; + } + + public void NotInTransit() + { + m_inTransit = false; + } + + public void RestoreInCurrentScene() + { + AddToPhysicalScene(false); // not exactly false + } + + public void Reset() + { + // Put the child agent back at the center + AbsolutePosition + = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); + Animator.ResetAnimations(); + } + + /// + /// Computes which child agents to close when the scene presence moves to another region. + /// Removes those regions from m_knownRegions. + /// + /// The new region's x on the map + /// The new region's y on the map + /// + public void CloseChildAgents(uint newRegionX, uint newRegionY) + { + List byebyeRegions = new List(); + m_log.DebugFormat( + "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", + m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName); + //DumpKnownRegions(); + + lock (m_knownChildRegions) + { + foreach (ulong handle in m_knownChildRegions.Keys) + { + // Don't close the agent on this region yet + if (handle != Scene.RegionInfo.RegionHandle) + { + uint x, y; + Utils.LongToUInts(handle, out x, out y); + x = x / Constants.RegionSize; + y = y / Constants.RegionSize; + + //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); + //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); + if (Util.IsOutsideView(x, newRegionX, y, newRegionY)) + { + byebyeRegions.Add(handle); + } + } + } + } + + if (byebyeRegions.Count > 0) + { + m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); + m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions); + } + + foreach (ulong handle in byebyeRegions) + { + RemoveNeighbourRegion(handle); + } + } + + #endregion + + /// + /// This allows the Sim owner the abiility to kick users from their sim currently. + /// It tells the client that the agent has permission to do so. + /// + public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) + { + if (godStatus) + { + // For now, assign god level 200 to anyone + // who is granted god powers, but has no god level set. + // + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID); + if (account != null) + { + if (account.UserLevel > 0) + m_godLevel = account.UserLevel; + else + m_godLevel = 200; + } + } + else + { + m_godLevel = 0; + } + + ControllingClient.SendAdminResponse(token, (uint)m_godLevel); + } + + #region Child Agent Updates + + public void ChildAgentDataUpdate(AgentData cAgentData) + { + //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); + if (!IsChildAgent) + return; + + CopyFrom(cAgentData); + } + + /// + /// This updates important decision making data about a child agent + /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region + /// + public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) + { + if (!IsChildAgent) + return; + + //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); + int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; + int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; + + Vector3 offset = new Vector3(shiftx, shifty, 0f); + + m_DrawDistance = cAgentData.Far; + if (cAgentData.Position != new Vector3(-1f, -1f, -1f)) // UGH!! + m_pos = cAgentData.Position + offset; + + if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance) + { + posLastSignificantMove = AbsolutePosition; + ReprioritizeUpdates(); + } + + m_CameraCenter = cAgentData.Center + offset; + + m_avHeight = cAgentData.Size.Z; + //SetHeight(cAgentData.AVHeight); + + if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) + ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); + + // Sends out the objects in the user's draw distance if m_sendTasksToChild is true. + if (m_scene.m_seeIntoRegionFromNeighbor) + m_sceneViewer.Reset(); + + //cAgentData.AVHeight; + m_rootRegionHandle = cAgentData.RegionHandle; + //m_velocity = cAgentData.Velocity; + } + + public void CopyTo(AgentData cAgent) + { + cAgent.AgentID = UUID; + cAgent.RegionID = Scene.RegionInfo.RegionID; + + cAgent.Position = AbsolutePosition; + cAgent.Velocity = m_velocity; + cAgent.Center = m_CameraCenter; + // Don't copy the size; it is inferred from apearance parameters + //cAgent.Size = new Vector3(0, 0, m_avHeight); + cAgent.AtAxis = m_CameraAtAxis; + cAgent.LeftAxis = m_CameraLeftAxis; + cAgent.UpAxis = m_CameraUpAxis; + + cAgent.Far = m_DrawDistance; + + // Throttles + float multiplier = 1; + int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); + if (innacurateNeighbors != 0) + { + multiplier = 1f / innacurateNeighbors; + } + if (multiplier <= 0f) + { + multiplier = 0.25f; + } + //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); + cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); + + cAgent.HeadRotation = m_headrotation; + cAgent.BodyRotation = m_bodyRot; + cAgent.ControlFlags = (uint)m_AgentControlFlags; + + if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) + cAgent.GodLevel = (byte)m_godLevel; + else + cAgent.GodLevel = (byte) 0; + + cAgent.AlwaysRun = m_setAlwaysRun; + + try + { + // We might not pass the Wearables in all cases... + // They're only needed so that persistent changes to the appearance + // are preserved in the new region where the user is moving to. + // But in Hypergrid we might not let this happen. + int i = 0; + UUID[] wears = new UUID[m_appearance.Wearables.Length * 2]; + foreach (AvatarWearable aw in m_appearance.Wearables) + { + if (aw != null) + { + wears[i++] = aw.ItemID; + wears[i++] = aw.AssetID; + } + else + { + wears[i++] = UUID.Zero; + wears[i++] = UUID.Zero; + } + } + cAgent.Wearables = wears; + + cAgent.VisualParams = m_appearance.VisualParams; + + if (m_appearance.Texture != null) + cAgent.AgentTextures = m_appearance.Texture.GetBytes(); + } + catch (Exception e) + { + m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message); + } + + //Attachments + List attPoints = m_appearance.GetAttachedPoints(); + if (attPoints != null) + { + //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count); + int i = 0; + AttachmentData[] attachs = new AttachmentData[attPoints.Count]; + foreach (int point in attPoints) + { + attachs[i++] = new AttachmentData(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point)); + } + cAgent.Attachments = attachs; + } + + lock (scriptedcontrols) + { + ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; + int i = 0; + + foreach (ScriptControllers c in scriptedcontrols.Values) + { + controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); + } + cAgent.Controllers = controls; + } + + // Animations + try + { + cAgent.Anims = Animator.Animations.ToArray(); + } + catch { } + + // cAgent.GroupID = ?? + // Groups??? + + } + + public void CopyFrom(AgentData cAgent) + { + m_originRegionID = cAgent.RegionID; + + m_callbackURI = cAgent.CallbackURI; + + m_pos = cAgent.Position; + + m_velocity = cAgent.Velocity; + m_CameraCenter = cAgent.Center; + //m_avHeight = cAgent.Size.Z; + m_CameraAtAxis = cAgent.AtAxis; + m_CameraLeftAxis = cAgent.LeftAxis; + m_CameraUpAxis = cAgent.UpAxis; + + m_DrawDistance = cAgent.Far; + + if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) + ControllingClient.SetChildAgentThrottle(cAgent.Throttles); + + m_headrotation = cAgent.HeadRotation; + m_bodyRot = cAgent.BodyRotation; + m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; + + if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) + m_godLevel = cAgent.GodLevel; + m_setAlwaysRun = cAgent.AlwaysRun; + + uint i = 0; + try + { + if (cAgent.Wearables == null) + cAgent.Wearables = new UUID[0]; + AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2]; + for (uint n = 0; n < cAgent.Wearables.Length; n += 2) + { + UUID itemId = cAgent.Wearables[n]; + UUID assetId = cAgent.Wearables[n + 1]; + wears[i++] = new AvatarWearable(itemId, assetId); + } + m_appearance.Wearables = wears; + Primitive.TextureEntry te; + if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1) + te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); + else + te = AvatarAppearance.GetDefaultTexture(); + if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) + cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams(); + m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone()); + } + catch (Exception e) + { + m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message); + } + + // Attachments + try + { + if (cAgent.Attachments != null) + { + m_appearance.ClearAttachments(); + foreach (AttachmentData att in cAgent.Attachments) + { + m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); + } + } + } + catch { } + + try + { + lock (scriptedcontrols) + { + if (cAgent.Controllers != null) + { + scriptedcontrols.Clear(); + + foreach (ControllerData c in cAgent.Controllers) + { + ScriptControllers sc = new ScriptControllers(); + sc.itemID = c.ItemID; + sc.ignoreControls = (ScriptControlled)c.IgnoreControls; + sc.eventControls = (ScriptControlled)c.EventControls; + + scriptedcontrols[sc.itemID] = sc; + } + } + } + } + catch { } + // Animations + try + { + Animator.ResetAnimations(); + Animator.Animations.FromArray(cAgent.Anims); + } + catch { } + + //cAgent.GroupID = ?? + //Groups??? + } + + public bool CopyAgent(out IAgentData agent) + { + agent = new CompleteAgentData(); + CopyTo((AgentData)agent); + return true; + } + + #endregion Child Agent Updates + + /// + /// Handles part of the PID controller function for moving an avatar. + /// + public override void UpdateMovement() + { + if (m_forceToApply.HasValue) + { + + Vector3 force = m_forceToApply.Value; + m_updateflag = true; + Velocity = force; + + m_forceToApply = null; + } + else + { + if (m_isNudging) + { + Vector3 force = Vector3.Zero; + + m_updateflag = true; + Velocity = force; + m_isNudging = false; + m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND" + } + } + } + + public override void SetText(string text, Vector3 color, double alpha) + { + throw new Exception("Can't set Text on avatar."); + } + + /// + /// Adds a physical representation of the avatar to the Physics plugin + /// + public void AddToPhysicalScene(bool isFlying) + { + PhysicsScene scene = m_scene.PhysicsScene; + + Vector3 pVec = AbsolutePosition; + + // Old bug where the height was in centimeters instead of meters + if (m_avHeight == 127.0f) + { + m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new Vector3(0f, 0f, 1.56f), + isFlying); + } + else + { + m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, + new Vector3(0f, 0f, m_avHeight), isFlying); + } + scene.AddPhysicsActorTaint(m_physicsActor); + //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; + m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; + m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong + m_physicsActor.SubscribeEvents(500); + m_physicsActor.LocalID = LocalId; + } + + private void OutOfBoundsCall(Vector3 pos) + { + //bool flying = m_physicsActor.Flying; + //RemoveFromPhysicalScene(); + + //AddToPhysicalScene(flying); + if (ControllingClient != null) + ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); + } + + // Event called by the physics plugin to tell the avatar about a collision. + private void PhysicsCollisionUpdate(EventArgs e) + { + if (e == null) + return; + + // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents( + // as of this comment the interval is set in AddToPhysicalScene + if (Animator!=null) + { + if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper, + { // else its will lock out other animation changes, like ground sit. + Animator.UpdateMovementAnimations(); + m_updateCount--; + } + } + + CollisionEventUpdate collisionData = (CollisionEventUpdate)e; + Dictionary coldata = collisionData.m_objCollisionList; + + CollisionPlane = Vector4.UnitW; + + if (m_lastColCount != coldata.Count) + { + m_updateCount = UPDATE_COUNT; + m_lastColCount = coldata.Count; + } + + if (coldata.Count != 0 && Animator != null) + { + switch (Animator.CurrentMovementAnimation) + { + case "STAND": + case "WALK": + case "RUN": + case "CROUCH": + case "CROUCHWALK": + { + ContactPoint lowest; + lowest.SurfaceNormal = Vector3.Zero; + lowest.Position = Vector3.Zero; + lowest.Position.Z = Single.NaN; + + foreach (ContactPoint contact in coldata.Values) + { + if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z) + { + lowest = contact; + } + } + + CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal)); + } + break; + } + } + + List thisHitColliders = new List(); + List endedColliders = new List(); + List startedColliders = new List(); + + foreach (uint localid in coldata.Keys) + { + thisHitColliders.Add(localid); + if (!m_lastColliders.Contains(localid)) + { + startedColliders.Add(localid); + } + //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString()); + } + + // calculate things that ended colliding + foreach (uint localID in m_lastColliders) + { + if (!thisHitColliders.Contains(localID)) + { + endedColliders.Add(localID); + } + } + //add the items that started colliding this time to the last colliders list. + foreach (uint localID in startedColliders) + { + m_lastColliders.Add(localID); + } + // remove things that ended colliding from the last colliders list + foreach (uint localID in endedColliders) + { + m_lastColliders.Remove(localID); + } + + // do event notification + if (startedColliders.Count > 0) + { + ColliderArgs StartCollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in startedColliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = Scene.GetSceneObjectPart(localId); + string data = ""; + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + } + + if (colliding.Count > 0) + { + StartCollidingMessage.Colliders = colliding; + + foreach (SceneObjectGroup att in Attachments) + Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage); + } + } + + if (endedColliders.Count > 0) + { + ColliderArgs EndCollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in endedColliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = Scene.GetSceneObjectPart(localId); + string data = ""; + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + } + + if (colliding.Count > 0) + { + EndCollidingMessage.Colliders = colliding; + + foreach (SceneObjectGroup att in Attachments) + Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage); + } + } + + if (thisHitColliders.Count > 0) + { + ColliderArgs CollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in thisHitColliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = Scene.GetSceneObjectPart(localId); + string data = ""; + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + } + + if (colliding.Count > 0) + { + CollidingMessage.Colliders = colliding; + + lock (m_attachments) + { + foreach (SceneObjectGroup att in m_attachments) + Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage); + } + } + } + + if (m_invulnerable) + return; + + float starthealth = Health; + uint killerObj = 0; + foreach (uint localid in coldata.Keys) + { + SceneObjectPart part = Scene.GetSceneObjectPart(localid); + + if (part != null && part.ParentGroup.Damage != -1.0f) + Health -= part.ParentGroup.Damage; + else + { + if (coldata[localid].PenetrationDepth >= 0.10f) + Health -= coldata[localid].PenetrationDepth * 5.0f; + } + + if (Health <= 0.0f) + { + if (localid != 0) + killerObj = localid; + } + //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString()); + } + //Health = 100; + if (!m_invulnerable) + { + if (starthealth != Health) + { + ControllingClient.SendHealth(Health); + } + if (m_health <= 0) + m_scene.EventManager.TriggerAvatarKill(killerObj, this); + } + } + + public void setHealthWithUpdate(float health) + { + Health = health; + ControllingClient.SendHealth(Health); + } + + public void Close() + { + lock (m_attachments) + { + // Delete attachments from scene + // Don't try to save, as this thread won't live long + // enough to complete the save. This would cause no copy + // attachments to poof! + // + foreach (SceneObjectGroup grp in m_attachments) + { + m_scene.DeleteSceneObject(grp, false); + } + m_attachments.Clear(); + } + + lock (m_knownChildRegions) + { + m_knownChildRegions.Clear(); + } + + lock (m_reprioritization_timer) + { + m_reprioritization_timer.Enabled = false; + m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize); + } + + // I don't get it but mono crashes when you try to dispose of this timer, + // unsetting the elapsed callback should be enough to allow for cleanup however. + // m_reprioritizationTimer.Dispose(); + + m_sceneViewer.Close(); + + RemoveFromPhysicalScene(); + m_animator.Close(); + m_animator = null; + } + + public void AddAttachment(SceneObjectGroup gobj) + { + lock (m_attachments) + { + m_attachments.Add(gobj); + } + } + + public bool HasAttachments() + { + return m_attachments.Count > 0; + } + + public bool HasScriptedAttachments() + { + lock (m_attachments) + { + foreach (SceneObjectGroup gobj in m_attachments) + { + if (gobj != null) + { + if (gobj.RootPart.Inventory.ContainsScripts()) + return true; + } + } + } + return false; + } + + public void RemoveAttachment(SceneObjectGroup gobj) + { + lock (m_attachments) + { + if (m_attachments.Contains(gobj)) + { + m_attachments.Remove(gobj); + } + } + } + + public bool ValidateAttachments() + { + lock (m_attachments) + { + // Validate + foreach (SceneObjectGroup gobj in m_attachments) + { + if (gobj == null) + return false; + + if (gobj.IsDeleted) + return false; + } + } + return true; + } + + /// + /// Send a script event to this scene presence's attachments + /// + /// The name of the event + /// The arguments for the event + public void SendScriptEventToAttachments(string eventName, Object[] args) + { + if (m_scriptEngines != null) + { + lock (m_attachments) + { + foreach (SceneObjectGroup grp in m_attachments) + { + // 16384 is CHANGED_ANIMATION + // + // Send this to all attachment root prims + // + foreach (IScriptModule m in m_scriptEngines) + { + if (m == null) // No script engine loaded + continue; + + m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION }); + } + } + } + } + } + + + public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene) + { + m_controllingClient = client; + m_regionInfo = region; + m_scene = scene; + + RegisterToEvents(); + if (m_controllingClient != null) + { + m_controllingClient.ProcessPendingPackets(); + } + /* + AbsolutePosition = client.StartPos; + + Animations = new AvatarAnimations(); + Animations.LoadAnims(); + + m_animations = new List(); + m_animations.Add(Animations.AnimsUUID["STAND"]); + m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber); + + SetDirectionVectors(); + */ + } + + internal void PushForce(Vector3 impulse) + { + if (PhysicsActor != null) + { + PhysicsActor.AddForce(impulse,true); + } + } + + public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) + { + ScriptControllers obj = new ScriptControllers(); + obj.ignoreControls = ScriptControlled.CONTROL_ZERO; + obj.eventControls = ScriptControlled.CONTROL_ZERO; + + obj.itemID = Script_item_UUID; + if (pass_on == 0 && accept == 0) + { + IgnoredControls |= (ScriptControlled)controls; + obj.ignoreControls = (ScriptControlled)controls; + } + + if (pass_on == 0 && accept == 1) + { + IgnoredControls |= (ScriptControlled)controls; + obj.ignoreControls = (ScriptControlled)controls; + obj.eventControls = (ScriptControlled)controls; + } + if (pass_on == 1 && accept == 1) + { + IgnoredControls = ScriptControlled.CONTROL_ZERO; + obj.eventControls = (ScriptControlled)controls; + obj.ignoreControls = ScriptControlled.CONTROL_ZERO; + } + + lock (scriptedcontrols) + { + if (pass_on == 1 && accept == 0) + { + IgnoredControls &= ~(ScriptControlled)controls; + if (scriptedcontrols.ContainsKey(Script_item_UUID)) + scriptedcontrols.Remove(Script_item_UUID); + } + else + { + scriptedcontrols[Script_item_UUID] = obj; + } + } + ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); + } + + public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID) + { + IgnoredControls = ScriptControlled.CONTROL_ZERO; + lock (scriptedcontrols) + { + scriptedcontrols.Clear(); + } + ControllingClient.SendTakeControls(int.MaxValue, false, false); + } + + public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) + { + ScriptControllers takecontrols; + + lock (scriptedcontrols) + { + if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols)) + { + ScriptControlled sctc = takecontrols.eventControls; + + ControllingClient.SendTakeControls((int)sctc, false, false); + ControllingClient.SendTakeControls((int)sctc, true, false); + + scriptedcontrols.Remove(Script_item_UUID); + IgnoredControls = ScriptControlled.CONTROL_ZERO; + foreach (ScriptControllers scData in scriptedcontrols.Values) + { + IgnoredControls |= scData.ignoreControls; + } + } + } + } + + internal void SendControlToScripts(uint flags) + { + ScriptControlled allflags = ScriptControlled.CONTROL_ZERO; + + if (MouseDown) + { + allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0) + { + allflags = ScriptControlled.CONTROL_ZERO; + MouseDown = true; + } + } + + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0) + { + allflags |= ScriptControlled.CONTROL_ML_LBUTTON; + MouseDown = true; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0) + { + allflags |= ScriptControlled.CONTROL_LBUTTON; + MouseDown = true; + } + + // find all activated controls, whether the scripts are interested in them or not + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0) + { + allflags |= ScriptControlled.CONTROL_FWD; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0) + { + allflags |= ScriptControlled.CONTROL_BACK; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0) + { + allflags |= ScriptControlled.CONTROL_UP; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0) + { + allflags |= ScriptControlled.CONTROL_DOWN; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0) + { + allflags |= ScriptControlled.CONTROL_LEFT; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0) + { + allflags |= ScriptControlled.CONTROL_RIGHT; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) + { + allflags |= ScriptControlled.CONTROL_ROT_RIGHT; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) + { + allflags |= ScriptControlled.CONTROL_ROT_LEFT; + } + // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that + if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands) + { + lock (scriptedcontrols) + { + foreach (KeyValuePair kvp in scriptedcontrols) + { + UUID scriptUUID = kvp.Key; + ScriptControllers scriptControlData = kvp.Value; + + ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us + ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle + ScriptControlled localChange = localHeld ^ localLast; // the changed bits + if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO) + { + // only send if still pressed or just changed + m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange); + } + } + } + } + + LastCommands = allflags; + } + + internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored) + { + if (ignored == ScriptControlled.CONTROL_ZERO) + return flags; + + if ((ignored & ScriptControlled.CONTROL_BACK) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); + if ((ignored & ScriptControlled.CONTROL_FWD) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS); + if ((ignored & ScriptControlled.CONTROL_DOWN) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG); + if ((ignored & ScriptControlled.CONTROL_UP) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS); + if ((ignored & ScriptControlled.CONTROL_LEFT) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); + if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG); + if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG); + if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS); + if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN); + if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN); + + //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, + //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, + //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, + //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, + //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, + //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, + //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG + + return flags; + } + + /// + /// RezAttachments. This should only be called upon login on the first region. + /// Attachment rezzings on crossings and TPs are done in a different way. + /// + public void RezAttachments() + { + if (null == m_appearance) + { + m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID); + return; + } + + XmlDocument doc = new XmlDocument(); + string stateData = String.Empty; + + IAttachmentsService attServ = m_scene.RequestModuleInterface(); + if (attServ != null) + { + m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service"); + stateData = attServ.Get(ControllingClient.AgentId.ToString()); + if (stateData != String.Empty) + { + try + { + doc.LoadXml(stateData); + } + catch { } + } + } + + Dictionary itemData = new Dictionary(); + + XmlNodeList nodes = doc.GetElementsByTagName("Attachment"); + if (nodes.Count > 0) + { + foreach (XmlNode n in nodes) + { + XmlElement elem = (XmlElement)n; + string itemID = elem.GetAttribute("ItemID"); + string xml = elem.InnerXml; + + itemData[new UUID(itemID)] = xml; + } + } + + List attPoints = m_appearance.GetAttachedPoints(); + foreach (int p in attPoints) + { + if (m_isDeleted) + return; + + UUID itemID = m_appearance.GetAttachedItem(p); + UUID assetID = m_appearance.GetAttachedAsset(p); + + // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down + // But they're not used anyway, the item is being looked up for now, so let's proceed. + //if (UUID.Zero == assetID) + //{ + // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); + // continue; + //} + + try + { + string xmlData; + XmlDocument d = new XmlDocument(); + UUID asset; + if (itemData.TryGetValue(itemID, out xmlData)) + { + d.LoadXml(xmlData); + m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID); + + // Rez from inventory + asset + = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d); + + } + else + { + // Rez from inventory (with a null doc to let + // CHANGED_OWNER happen) + asset + = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null); + } + + m_log.InfoFormat( + "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", + p, itemID, assetID, asset); + } + catch (Exception e) + { + m_log.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}", e.ToString()); + } + } + } + + private void ReprioritizeUpdates() + { + if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time) + { + lock (m_reprioritization_timer) + { + if (!m_reprioritizing) + m_reprioritization_timer.Enabled = m_reprioritizing = true; + else + m_reprioritization_called = true; + } + } + } + + private void Reprioritize(object sender, ElapsedEventArgs e) + { + m_controllingClient.ReprioritizeUpdates(); + + lock (m_reprioritization_timer) + { + m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called; + m_reprioritization_called = false; + } + } + + private Vector3 Quat2Euler(Quaternion rot){ + float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) , + (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z))); + float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W))); + float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) , + (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z))); + return(new Vector3(x,y,z)); + } + + + } +} -- cgit v1.1 From 97f8175090837ef4399975d6674aaa542fbf408c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 7 Aug 2010 18:34:11 +0200 Subject: Delete some files from bin that should not have been committed --- bin/ICSharpCode.SharpZipLib.xml | 9055 --------------------------------------- bin/hdfsdll.dll.config | 3 - bin/hdfsdll.so | Bin 6557 -> 0 bytes bin/xmrhelpers.so | Bin 18357 -> 0 bytes 4 files changed, 9058 deletions(-) delete mode 100644 bin/ICSharpCode.SharpZipLib.xml delete mode 100644 bin/hdfsdll.dll.config delete mode 100755 bin/hdfsdll.so delete mode 100755 bin/xmrhelpers.so diff --git a/bin/ICSharpCode.SharpZipLib.xml b/bin/ICSharpCode.SharpZipLib.xml deleted file mode 100644 index 98cb51e..0000000 --- a/bin/ICSharpCode.SharpZipLib.xml +++ /dev/null @@ -1,9055 +0,0 @@ - - - - ICSharpCode.SharpZipLib - - - - - FastZipEvents supports all events applicable to FastZip operations. - - - - - Delegate to invoke when processing directories. - - - - - Delegate to invoke when processing files. - - - - - Delegate to invoke during processing of files. - - - - - Delegate to invoke when processing for a file has been completed. - - - - - Delegate to invoke when processing directory failures. - - - - - Delegate to invoke when processing file failures. - - - - - Raise the directory failure event. - - The directory causing the failure. - The exception for this event. - A boolean indicating if execution should continue or not. - - - - Raises the file failure delegate. - - The file causing the failure. - The exception for this failure. - A boolean indicating if execution should continue or not. - - - - Fires the Process File delegate. - - The file being processed. - A boolean indicating if execution should continue or not. - - - - Fires the CompletedFile delegate - - The file whose processing has been completed. - A boolean indicating if execution should continue or not. - - - - Fires the process directory delegate. - - The directory being processed. - Flag indicating if the directory has matching files as determined by the current filter. - A of true if the operation should continue; false otherwise. - - - - The minimum timespan between events. - - The minimum period of time between events. - - - - - FastZip provides facilities for creating and extracting zip files. - - - - - Initialise a default instance of . - - - - - Initialise a new instance of - - The events to use during operations. - - - - Create a zip file. - - The name of the zip file to create. - The directory to source files from. - True to recurse directories, false for no recursion. - The file filter to apply. - The directory filter to apply. - - - - Create a zip file/archive. - - The name of the zip file to create. - The directory to obtain files and directories from. - True to recurse directories, false for no recursion. - The file filter to apply. - - - - Create a zip archive sending output to the passed. - - The stream to write archive data to. - The directory to source files from. - True to recurse directories, false for no recursion. - The file filter to apply. - The directory filter to apply. - - - - Extract the contents of a zip file. - - The zip file to extract from. - The directory to save extracted information in. - A filter to apply to files. - - - - Extract the contents of a zip file. - - The zip file to extract from. - The directory to save extracted information in. - The style of overwriting to apply. - A delegate to invoke when confirming overwriting. - A filter to apply to files. - A filter to apply to directories. - Flag indicating wether to restore the date and time for extracted files. - - - - Get/set a value indicating wether empty directories should be created. - - - - - Get / set the password value. - - - - - Get or set the active when creating Zip files. - - - - - - Get or set the active when creating Zip files. - - - - - Get/set a value indicating wether file dates and times should - be restored when extracting files from an archive. - - The default value is false. - - - - Get/set a value indicating wether file attributes should - be restored during extract operations - - - - - Defines the desired handling when overwriting files during extraction. - - - - - Prompt the user to confirm overwriting - - - - - Never overwrite files. - - - - - Always overwrite files. - - - - - Delegate called when confirming overwriting of files. - - - - - NameFilter is a string matching class which allows for both positive and negative - matching. - A filter is a sequence of independant regular expressions separated by semi-colons ';' - Each expression can be prefixed by a plus '+' sign or a minus '-' sign to denote the expression - is intended to include or exclude names. If neither a plus or minus sign is found include is the default - A given name is tested for inclusion before checking exclusions. Only names matching an include spec - and not matching an exclude spec are deemed to match the filter. - An empty filter matches any name. - - The following expression includes all name ending in '.dat' with the exception of 'dummy.dat' - "+\.dat$;-^dummy\.dat$" - - - - - Scanning filters support filtering of names. - - - - - Test a name to see if it 'matches' the filter. - - The name to test. - Returns true if the name matches the filter, false if it does not match. - - - - Construct an instance based on the filter expression passed - - The filter expression. - - - - Test a string to see if it is a valid regular expression. - - The expression to test. - True if expression is a valid false otherwise. - - - - Test an expression to see if it is valid as a filter. - - The filter expression to test. - True if the expression is valid, false otherwise. - - - - Convert this filter to its string equivalent. - - The string equivalent for this filter. - - - - Test a value to see if it is included by the filter. - - The value to test. - True if the value is included, false otherwise. - - - - Test a value to see if it is excluded by the filter. - - The value to test. - True if the value is excluded, false otherwise. - - - - Test a value to see if it matches the filter. - - The value to test. - True if the value matches, false otherwise. - - - - Compile this filter. - - - - - Huffman tree used for inflation - - - - - Literal length tree - - - - - Distance tree - - - - - Constructs a Huffman tree from the array of code lengths. - - - the array of code lengths - - - - - Reads the next symbol from input. The symbol is encoded using the - huffman tree. - - - input the input source. - - - the next symbol, or -1 if not enough input is available. - - - - - This class is general purpose class for writing data to a buffer. - - It allows you to write bits as well as bytes - Based on DeflaterPending.java - - author of the original java version : Jochen Hoenicke - - - - - Internal work buffer - - - - - construct instance using default buffer size of 4096 - - - - - construct instance using specified buffer size - - - size to use for internal buffer - - - - - Clear internal state/buffers - - - - - Write a byte to buffer - - - The value to write - - - - - Write a short value to buffer LSB first - - - The value to write. - - - - - write an integer LSB first - - The value to write. - - - - Write a block of data to buffer - - data to write - offset of first byte to write - number of bytes to write - - - - Align internal buffer on a byte boundary - - - - - Write bits to internal buffer - - source of bits - number of bits to write - - - - Write a short value to internal buffer most significant byte first - - value to write - - - - Flushes the pending buffer into the given output array. If the - output array is to small, only a partial flush is done. - - The output array. - The offset into output array. - The maximum number of bytes to store. - The number of bytes flushed. - - - - Convert internal buffer to byte array. - Buffer is empty on completion - - - The internal buffer contents converted to a byte array. - - - - - The number of bits written to the buffer - - - - - Indicates if buffer has been flushed - - - - - Used to advise clients of 'events' while processing archives - - - - - The TarArchive class implements the concept of a - 'Tape Archive'. A tar archive is a series of entries, each of - which represents a file system object. Each entry in - the archive consists of a header block followed by 0 or more data blocks. - Directory entries consist only of the header block, and are followed by entries - for the directory's contents. File entries consist of a - header followed by the number of blocks needed to - contain the file's contents. All entries are written on - block boundaries. Blocks are 512 bytes long. - - TarArchives are instantiated in either read or write mode, - based upon whether they are instantiated with an InputStream - or an OutputStream. Once instantiated TarArchives read/write - mode can not be changed. - - There is currently no support for random access to tar archives. - However, it seems that subclassing TarArchive, and using the - TarBuffer.CurrentRecord and TarBuffer.CurrentBlock - properties, this would be rather trivial. - - - - - Raises the ProgressMessage event - - The TarEntry for this event - message for this event. Null is no message - - - - Constructor for a default . - - - - - Initalise a TarArchive for input. - - The to use for input. - - - - Initialise a TarArchive for output. - - The to use for output. - - - - The InputStream based constructors create a TarArchive for the - purposes of extracting or listing a tar archive. Thus, use - these constructors when you wish to extract files from or list - the contents of an existing tar archive. - - The stream to retrieve archive data from. - Returns a new suitable for reading from. - - - - Create TarArchive for reading setting block factor - - Stream for tar archive contents - The blocking factor to apply - Returns a suitable for reading. - - - - Create a TarArchive for writing to, using the default blocking factor - - The to write to - Returns a suitable for writing. - - - - Create a TarArchive for writing to - - The stream to write to - The blocking factor to use for buffering. - Returns a suitable for writing. - - - - Set the flag that determines whether existing files are - kept, or overwritten during extraction. - - - If true, do not overwrite existing files. - - - - - Set the ascii file translation flag. - - - If true, translate ascii text files. - - - - - Set user and group information that will be used to fill in the - tar archive's entry headers. This information based on that available - for the linux operating system, which is not always available on other - operating systems. TarArchive allows the programmer to specify values - to be used in their place. - is set to true by this call. - - - The user id to use in the headers. - - - The user name to use in the headers. - - - The group id to use in the headers. - - - The group name to use in the headers. - - - - - Close the archive. - - - - - Perform the "list" command for the archive contents. - - NOTE That this method uses the progress event to actually list - the contents. If the progress display event is not set, nothing will be listed! - - - - - Perform the "extract" command and extract the contents of the archive. - - - The destination directory into which to extract. - - - - - Extract an entry from the archive. This method assumes that the - tarIn stream has been properly set with a call to GetNextEntry(). - - - The destination directory into which to extract. - - - The TarEntry returned by tarIn.GetNextEntry(). - - - - - Write an entry to the archive. This method will call the putNextEntry - and then write the contents of the entry, and finally call closeEntry() - for entries that are files. For directories, it will call putNextEntry(), - and then, if the recurse flag is true, process each entry that is a - child of the directory. - - - The TarEntry representing the entry to write to the archive. - - - If true, process the children of directory entries. - - - - - Write an entry to the archive. This method will call the putNextEntry - and then write the contents of the entry, and finally call closeEntry() - for entries that are files. For directories, it will call putNextEntry(), - and then, if the recurse flag is true, process each entry that is a - child of the directory. - - - The TarEntry representing the entry to write to the archive. - - - If true, process the children of directory entries. - - - - - Releases the unmanaged resources used by the FileStream and optionally releases the managed resources. - - true to release both managed and unmanaged resources; - false to release only unmanaged resources. - - - - Closes the archive and releases any associated resources. - - - - - Ensures that resources are freed and other cleanup operations are performed - when the garbage collector reclaims the . - - - - - Client hook allowing detailed information to be reported during processing - - - - - Get/set the ascii file translation flag. If ascii file translation - is true, then the file is checked to see if it a binary file or not. - If the flag is true and the test indicates it is ascii text - file, it will be translated. The translation converts the local - operating system's concept of line ends into the UNIX line end, - '\n', which is the defacto standard for a TAR archive. This makes - text files compatible with UNIX. - - - - - PathPrefix is added to entry names as they are written if the value is not null. - A slash character is appended after PathPrefix - - - - - RootPath is removed from entry names if it is found at the - beginning of the name. - - - - - Get or set a value indicating if overrides defined by SetUserInfo should be applied. - - If overrides are not applied then the values as set in each header will be used. - - - - Get the archive user id. - See ApplyUserInfoOverrides for detail - on how to allow setting values on a per entry basis. - - - The current user id. - - - - - Get the archive user name. - See ApplyUserInfoOverrides for detail - on how to allow setting values on a per entry basis. - - - The current user name. - - - - - Get the archive group id. - See ApplyUserInfoOverrides for detail - on how to allow setting values on a per entry basis. - - - The current group id. - - - - - Get the archive group name. - See ApplyUserInfoOverrides for detail - on how to allow setting values on a per entry basis. - - - The current group name. - - - - - Get the archive's record size. Tar archives are composed of - a series of RECORDS each containing a number of BLOCKS. - This allowed tar archives to match the IO characteristics of - the physical device being used. Archives are expected - to be properly "blocked". - - - The record size this archive is using. - - - - - An output stream that compresses into the BZip2 format - including file header chars into another stream. - - - - - Construct a default output stream with maximum block size - - The stream to write BZip data onto. - - - - Initialise a new instance of the - for the specified stream, using the given blocksize. - - The stream to write compressed data to. - The block size to use. - - Valid block sizes are in the range 1..9, with 1 giving - the lowest compression and 9 the highest. - - - - - Ensures that resources are freed and other cleanup operations - are performed when the garbage collector reclaims the BZip2OutputStream. - - - - - Sets the current position of this stream to the given value. - - The point relative to the offset from which to being seeking. - The reference point from which to begin seeking. - The new position in the stream. - - - - Sets the length of this stream to the given value. - - The new stream length. - - - - Read a byte from the stream advancing the position. - - The byte read cast to an int; -1 if end of stream. - - - - Read a block of bytes - - The buffer to read into. - The offset in the buffer to start storing data at. - The maximum number of bytes to read. - The total number of bytes read. This might be less than the number of bytes - requested if that number of bytes are not currently available, or zero - if the end of the stream is reached. - - - - Write a block of bytes to the stream - - The buffer containing data to write. - The offset of the first byte to write. - The number of bytes to write. - - - - Write a byte to the stream. - - The byte to write to the stream. - - - - End the current block and end compression. - Close the stream and free any resources - - - - - Get the number of bytes written to output. - - - - - Releases the unmanaged resources used by the and optionally releases the managed resources. - - true to release both managed and unmanaged resources; false to release only unmanaged resources. - - - - Flush output buffers - - - - - Get/set flag indicating ownership of underlying stream. - When the flag is true will close the underlying stream also. - - - - - Gets a value indicating whether the current stream supports reading - - - - - Gets a value indicating whether the current stream supports seeking - - - - - Gets a value indicating whether the current stream supports writing - - - - - Gets the length in bytes of the stream - - - - - Gets or sets the current position of this stream. - - - - - Get the number of bytes written to the output. - - - - - Represents exception conditions specific to Zip archive handling - - - - - SharpZipBaseException is the base exception class for the SharpZipLibrary. - All library exceptions are derived from this. - - NOTE: Not all exceptions thrown will be derived from this class. - A variety of other exceptions are possible for example - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initializes a new instance of the SharpZipBaseException class. - - - - - Initializes a new instance of the SharpZipBaseException class with a specified error message. - - A message describing the exception. - - - - Initializes a new instance of the SharpZipBaseException class with a specified - error message and a reference to the inner exception that is the cause of this exception. - - A message describing the exception. - The inner exception - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initializes a new instance of the ZipException class. - - - - - Initializes a new instance of the ZipException class with a specified error message. - - The error message that explains the reason for the exception. - - - - Initialise a new instance of ZipException. - - A message describing the error. - The exception that is the cause of the current exception. - - - - A helper class to simplify compressing and decompressing streams. - - - - - Decompress input writing - decompressed data to the output stream - - The stream containing data to decompress. - The stream to write decompressed data to. - Both streams are closed on completion - - - - Compress input stream sending - result to output stream - - The stream to compress. - The stream to write compressed data to. - The block size to use. - Both streams are closed on completion - - - - Initialise a default instance of this class. - - - - - Determines how entries are tested to see if they should use Zip64 extensions or not. - - - - - Zip64 will not be forced on entries during processing. - - An entry can have this overridden if required - - - - Zip64 should always be used. - - - - - #ZipLib will determine use based on entry values when added to archive. - - - - - The kind of compression used for an entry in an archive - - - - - A direct copy of the file contents is held in the archive - - - - - Common Zip compression method using a sliding dictionary - of up to 32KB and secondary compression from Huffman/Shannon-Fano trees - - - - - An extension to deflate with a 64KB window. Not supported by #Zip currently - - - - - Not supported by #Zip currently - - - - - WinZip special for AES encryption, Not supported by #Zip - - - - - Identifies the encryption algorithm used for an entry - - - - - No encryption has been used. - - - - - Encrypted using PKZIP 2.0 or 'classic' encryption. - - - - - DES encryption has been used. - - - - - RCS encryption has been used for encryption. - - - - - Triple DES encryption with 168 bit keys has been used for this entry. - - - - - Triple DES with 112 bit keys has been used for this entry. - - - - - AES 128 has been used for encryption. - - - - - AES 192 has been used for encryption. - - - - - AES 256 has been used for encryption. - - - - - RC2 corrected has been used for encryption. - - - - - Blowfish has been used for encryption. - - - - - Twofish has been used for encryption. - - - - - RCS has been used for encryption. - - - - - An unknown algorithm has been used for encryption. - - - - - Defines the contents of the general bit flags field for an archive entry. - - - - - Bit 0 if set indicates that the file is encrypted - - - - - Bits 1 and 2 - Two bits defining the compression method (only for Method 6 Imploding and 8,9 Deflating) - - - - - Bit 3 if set indicates a trailing data desciptor is appended to the entry data - - - - - Bit 4 is reserved for use with method 8 for enhanced deflation - - - - - Bit 5 if set indicates the file contains Pkzip compressed patched data. - Requires version 2.7 or greater. - - - - - Bit 6 if set strong encryption has been used for this entry. - - - - - Bit 7 is currently unused - - - - - Bit 8 is currently unused - - - - - Bit 9 is currently unused - - - - - Bit 10 is currently unused - - - - - Bit 11 if set indicates the filename and - comment fields for this file must be encoded using UTF-8. - - - - - Bit 12 is documented as being reserved by PKware for enhanced compression. - - - - - Bit 13 if set indicates that values in the local header are masked to hide - their actual values, and the central directory is encrypted. - - - Used when encrypting the central directory contents. - - - - - Bit 14 is documented as being reserved for use by PKware - - - - - Bit 15 is documented as being reserved for use by PKware - - - - - This class contains constants used for Zip format files - - - - - The version made by field for entries in the central header when created by this library - - - This is also the Zip version for the library when comparing against the version required to extract - for an entry. See . - - - - - The version made by field for entries in the central header when created by this library - - - This is also the Zip version for the library when comparing against the version required to extract - for an entry. See ZipInputStream.CanDecompressEntry. - - - - - The minimum version required to support strong encryption - - - - - The minimum version required to support strong encryption - - - - - The version required for Zip64 extensions - - - - - Size of local entry header (excluding variable length fields at end) - - - - - Size of local entry header (excluding variable length fields at end) - - - - - Size of Zip64 data descriptor - - - - - Size of data descriptor - - - - - Size of data descriptor - - - - - Size of central header entry (excluding variable fields) - - - - - Size of central header entry - - - - - Size of end of central record (excluding variable fields) - - - - - Size of end of central record (excluding variable fields) - - - - - Size of 'classic' cryptographic header stored before any entry data - - - - - Size of cryptographic header stored before entry data - - - - - Signature for local entry header - - - - - Signature for local entry header - - - - - Signature for spanning entry - - - - - Signature for spanning entry - - - - - Signature for temporary spanning entry - - - - - Signature for temporary spanning entry - - - - - Signature for data descriptor - - - This is only used where the length, Crc, or compressed size isnt known when the - entry is created and the output stream doesnt support seeking. - The local entry cannot be 'patched' with the correct values in this case - so the values are recorded after the data prefixed by this header, as well as in the central directory. - - - - - Signature for data descriptor - - - This is only used where the length, Crc, or compressed size isnt known when the - entry is created and the output stream doesnt support seeking. - The local entry cannot be 'patched' with the correct values in this case - so the values are recorded after the data prefixed by this header, as well as in the central directory. - - - - - Signature for central header - - - - - Signature for central header - - - - - Signature for Zip64 central file header - - - - - Signature for Zip64 central file header - - - - - Signature for Zip64 central directory locator - - - - - Signature for archive extra data signature (were headers are encrypted). - - - - - Central header digitial signature - - - - - Central header digitial signature - - - - - End of central directory record signature - - - - - End of central directory record signature - - - - - Convert a portion of a byte array to a string. - - - Data to convert to string - - - Number of bytes to convert starting from index 0 - - - data[0]..data[length - 1] converted to a string - - - - - Convert a byte array to string - - - Byte array to convert - - - dataconverted to a string - - - - - Convert a byte array to string - - The applicable general purpose bits flags - - Byte array to convert - - The number of bytes to convert. - - dataconverted to a string - - - - - Convert a byte array to string - - - Byte array to convert - - The applicable general purpose bits flags - - dataconverted to a string - - - - - Convert a string to a byte array - - - String to convert to an array - - Converted array - - - - Convert a string to a byte array - - The applicable general purpose bits flags - - String to convert to an array - - Converted array - - - - Initialise default instance of ZipConstants - - - Private to prevent instances being created. - - - - - Default encoding used for string conversion. 0 gives the default system OEM code page. - Dont use unicode encodings if you want to be Zip compatible! - Using the default code page isnt the full solution neccessarily - there are many variable factors, codepage 850 is often a good choice for - European users, however be careful about compatability. - - - - - This is a DeflaterOutputStream that writes the files into a zip - archive one after another. It has a special method to start a new - zip entry. The zip entries contains information about the file name - size, compressed size, CRC, etc. - - It includes support for Stored and Deflated entries. - This class is not thread safe. -
-
Author of the original java version : Jochen Hoenicke -
- This sample shows how to create a zip file - - using System; - using System.IO; - - using ICSharpCode.SharpZipLib.Core; - using ICSharpCode.SharpZipLib.Zip; - - class MainClass - { - public static void Main(string[] args) - { - string[] filenames = Directory.GetFiles(args[0]); - byte[] buffer = new byte[4096]; - - using ( ZipOutputStream s = new ZipOutputStream(File.Create(args[1])) ) { - - s.SetLevel(9); // 0 - store only to 9 - means best compression - - foreach (string file in filenames) { - ZipEntry entry = new ZipEntry(file); - s.PutNextEntry(entry); - - using (FileStream fs = File.OpenRead(file)) { - StreamUtils.Copy(fs, s, buffer); - } - } - } - } - } - - -
- - - A special stream deflating or compressing the bytes that are - written to it. It uses a Deflater to perform actual deflating.
- Authors of the original java version : Tom Tromey, Jochen Hoenicke -
-
- - - Creates a new DeflaterOutputStream with a default Deflater and default buffer size. - - - the output stream where deflated output should be written. - - - - - Creates a new DeflaterOutputStream with the given Deflater and - default buffer size. - - - the output stream where deflated output should be written. - - - the underlying deflater. - - - - - Creates a new DeflaterOutputStream with the given Deflater and - buffer size. - - - The output stream where deflated output is written. - - - The underlying deflater to use - - - The buffer size to use when deflating - - - bufsize is less than or equal to zero. - - - baseOutputStream does not support writing - - - deflater instance is null - - - - - Finishes the stream by calling finish() on the deflater. - - - Not all input is deflated - - - - - Encrypt a block of data - - - Data to encrypt. NOTE the original contents of the buffer are lost - - - Offset of first byte in buffer to encrypt - - - Number of bytes in buffer to encrypt - - - - - Initializes encryption keys based on given password - - The password. - - - - Deflates everything in the input buffers. This will call - def.deflate() until all bytes from the input buffers - are processed. - - - - - Sets the current position of this stream to the given value. Not supported by this class! - - The offset relative to the to seek. - The to seek from. - The new position in the stream. - Any access - - - - Sets the length of this stream to the given value. Not supported by this class! - - The new stream length. - Any access - - - - Read a byte from stream advancing position by one - - The byte read cast to an int. THe value is -1 if at the end of the stream. - Any access - - - - Read a block of bytes from stream - - The buffer to store read data in. - The offset to start storing at. - The maximum number of bytes to read. - The actual number of bytes read. Zero if end of stream is detected. - Any access - - - - Asynchronous reads are not supported a NotSupportedException is always thrown - - The buffer to read into. - The offset to start storing data at. - The number of bytes to read - The async callback to use. - The state to use. - Returns an - Any access - - - - Asynchronous writes arent supported, a NotSupportedException is always thrown - - The buffer to write. - The offset to begin writing at. - The number of bytes to write. - The to use. - The state object. - Returns an IAsyncResult. - Any access - - - - Flushes the stream by calling Flush on the deflater and then - on the underlying stream. This ensures that all bytes are flushed. - - - - - Calls and closes the underlying - stream when is true. - - - - - Writes a single byte to the compressed output stream. - - - The byte value. - - - - - Writes bytes from an array to the compressed stream. - - - The byte array - - - The offset into the byte array where to start. - - - The number of bytes to write. - - - - - This buffer is used temporarily to retrieve the bytes from the - deflater and write them to the underlying output stream. - - - - - The deflater which is used to deflate the stream. - - - - - Base stream the deflater depends on. - - - - - Get/set flag indicating ownership of the underlying stream. - When the flag is true will close the underlying stream also. - - - - - Allows client to determine if an entry can be patched after its added - - - - - Get/set the password used for encryption. - - When set to null or if the password is empty no encryption is performed - - - - Gets value indicating stream can be read from - - - - - Gets a value indicating if seeking is supported for this stream - This property always returns false - - - - - Get value indicating if this stream supports writing - - - - - Get current length of stream - - - - - Gets the current position within the stream. - - Any attempt to set position - - - - Creates a new Zip output stream, writing a zip archive. - - - The output stream to which the archive contents are written. - - - - - Set the zip file comment. - - - The comment text for the entire archive. - - - The converted comment is longer than 0xffff bytes. - - - - - Sets the compression level. The new level will be activated - immediately. - - The new compression level (1 to 9). - - Level specified is not supported. - - - - - - Get the current deflater compression level - - The current compression level - - - - Write an unsigned short in little endian byte order. - - - - - Write an int in little endian byte order. - - - - - Write an int in little endian byte order. - - - - - Starts a new Zip entry. It automatically closes the previous - entry if present. - All entry elements bar name are optional, but must be correct if present. - If the compression method is stored and the output is not patchable - the compression for that entry is automatically changed to deflate level 0 - - - the entry. - - - if entry passed is null. - - - if an I/O error occured. - - - if stream was finished - - - Too many entries in the Zip file
- Entry name is too long
- Finish has already been called
-
-
- - - Closes the current entry, updating header and footer information as required - - - An I/O error occurs. - - - No entry is active. - - - - - Writes the given buffer to the current entry. - - The buffer containing data to write. - The offset of the first byte to write. - The number of bytes to write. - Archive size is invalid - No entry is active. - - - - Finishes the stream. This will write the central directory at the - end of the zip file and flush the stream. - - - This is automatically called when the stream is closed. - - - An I/O error occurs. - - - Comment exceeds the maximum length
- Entry name exceeds the maximum length -
-
- - - The entries for the archive. - - - - - Used to track the crc of data added to entries. - - - - - The current entry being added. - - - - - Used to track the size of data for an entry during writing. - - - - - Offset to be recorded for each entry in the central header. - - - - - Comment for the entire archive recorded in central header. - - - - - Flag indicating that header patching is required for the current entry. - - - - - Position to patch crc - - - - - Position to patch size. - - - - - Gets a flag value of true if the central header has been added for this archive; false if it has not been added. - - No further entries can be added once this has been done. - - - - Get / set a value indicating how Zip64 Extension usage is determined when adding entries. - - Older archivers may not understand Zip64 extensions. - If backwards compatability is an issue be careful when adding entries to an archive. - Setting this property to off is workable but less desirable as in those circumstances adding a file - larger then 4GB will fail. - - - - INameTransform defines how file system names are transformed for use with archives. - - - - - Given a file name determine the transformed value. - - The name to transform. - The transformed file name. - - - - Given a directory name determine the transformed value. - - The name to transform. - The transformed directory name - - - - This class contains constants used for deflation. - - - - - Set to true to enable debugging - - - - - Written to Zip file to identify a stored block - - - - - Identifies static tree in Zip file - - - - - Identifies dynamic tree in Zip file - - - - - Header flag indicating a preset dictionary for deflation - - - - - Sets internal buffer sizes for Huffman encoding - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - Internal compression engine constant - - - - - This class stores the pending output of the Deflater. - - author of the original java version : Jochen Hoenicke - - - - - Construct instance with default buffer size - - - - - PathFilter filters directories and files using a form of regular expressions - by full path name. - See NameFilter for more detail on filtering. - - - - - Initialise a new instance of . - - The filter expression to apply. - - - - Test a name to see if it matches the filter. - - The name to test. - True if the name matches, false otherwise. - - - - ExtendedPathFilter filters based on name, file size, and the last write time of the file. - - Provides an example of how to customise filtering. - - - - Initialise a new instance of ExtendedPathFilter. - - The filter to apply. - The minimum file size to include. - The maximum file size to include. - - - - Initialise a new instance of ExtendedPathFilter. - - The filter to apply. - The minimum to include. - The maximum to include. - - - - Initialise a new instance of ExtendedPathFilter. - - The filter to apply. - The minimum file size to include. - The maximum file size to include. - The minimum to include. - The maximum to include. - - - - Test a filename to see if it matches the filter. - - The filename to test. - True if the filter matches, false otherwise. - - - - Get/set the minimum size for a file that will match this filter. - - - - - Get/set the maximum size for a file that will match this filter. - - - - - Get/set the minimum value that will match for this filter. - - Files with a LastWrite time less than this value are excluded by the filter. - - - - Get/set the maximum value that will match for this filter. - - Files with a LastWrite time greater than this value are excluded by the filter. - - - - NameAndSizeFilter filters based on name and file size. - - A sample showing how filters might be extended. - - - - Initialise a new instance of NameAndSizeFilter. - - The filter to apply. - The minimum file size to include. - The maximum file size to include. - - - - Test a filename to see if it matches the filter. - - The filename to test. - True if the filter matches, false otherwise. - - - - Get/set the minimum size for a file that will match this filter. - - - - - Get/set the maximum size for a file that will match this filter. - - - - - BZip2Exception represents exceptions specific to Bzip2 algorithm - - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initialise a new instance of BZip2Exception. - - - - - Initialise a new instance of BZip2Exception with its message set to message. - - The message describing the error. - - - - Initialise an instance of BZip2Exception - - A message describing the error. - The exception that is the cause of the current exception. - - - - GZipException represents a Gzip specific exception - - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initialise a new instance of GZipException - - - - - Initialise a new instance of GZipException with its message string. - - A that describes the error. - - - - Initialise a new instance of . - - A that describes the error. - The that caused this exception. - - - - Contains the output from the Inflation process. - We need to have a window so that we can refer backwards into the output stream - to repeat stuff.
- Author of the original java version : John Leuner -
-
- - - Write a byte to this output window - - value to write - - if window is full - - - - - Append a byte pattern already in the window itself - - length of pattern to copy - distance from end of window pattern occurs - - If the repeated data overflows the window - - - - - Copy from input manipulator to internal window - - source of data - length of data to copy - the number of bytes copied - - - - Copy dictionary to window - - source dictionary - offset of start in source dictionary - length of dictionary - - If window isnt empty - - - - - Get remaining unfilled space in window - - Number of bytes left in window - - - - Get bytes available for output in window - - Number of bytes filled - - - - Copy contents of window to output - - buffer to copy to - offset to start at - number of bytes to count - The number of bytes copied - - If a window underflow occurs - - - - - Reset by clearing window so GetAvailable returns 0 - - - - - Defines internal values for both compression and decompression - - - - - When multiplied by compression parameter (1-9) gives the block size for compression - 9 gives the best compresssion but uses the most memory. - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Backend constant - - - - - Random numbers used to randomise repetitive blocks - - - - - This filter stream is used to compress a stream into a "GZIP" stream. - The "GZIP" format is described in RFC 1952. - - author of the original java version : John Leuner - - This sample shows how to gzip a file - - using System; - using System.IO; - - using ICSharpCode.SharpZipLib.GZip; - using ICSharpCode.SharpZipLib.Core; - - class MainClass - { - public static void Main(string[] args) - { - using (Stream s = new GZipOutputStream(File.Create(args[0] + ".gz"))) - using (FileStream fs = File.OpenRead(args[0])) { - byte[] writeData = new byte[4096]; - Streamutils.Copy(s, fs, writeData); - } - } - } - } - - - - - - CRC-32 value for uncompressed data - - - - - Creates a GzipOutputStream with the default buffer size - - - The stream to read data (to be compressed) from - - - - - Creates a GZipOutputStream with the specified buffer size - - - The stream to read data (to be compressed) from - - - Size of the buffer to use - - - - - Sets the active compression level (1-9). The new level will be activated - immediately. - - The compression level to set. - - Level specified is not supported. - - - - - - Get the current compression level. - - The current compression level. - - - - Write given buffer to output updating crc - - Buffer to write - Offset of first byte in buf to write - Number of bytes to write - - - - Writes remaining compressed output data to the output stream - and closes it. - - - - - Finish compression and write any footer information required to stream - - - - - Arguments used with KeysRequiredEvent - - - - - Initialise a new instance of - - The name of the file for which keys are required. - - - - Initialise a new instance of - - The name of the file for which keys are required. - The current key value. - - - - Get the name of the file for which keys are required. - - - - - Get/set the key value - - - - - The strategy to apply to testing. - - - - - Find the first error only. - - - - - Find all possible errors. - - - - - The operation in progress reported by a during testing. - - TestArchive - - - - Setting up testing. - - - - - Testing an individual entries header - - - - - Testing an individual entries data - - - - - Testing an individual entry has completed. - - - - - Running miscellaneous tests - - - - - Testing is complete - - - - - Status returned returned by during testing. - - TestArchive - - - - Initialise a new instance of - - The this status applies to. - - - - Get the current in progress. - - - - - Get the this status is applicable to. - - - - - Get the current/last entry tested. - - - - - Get the number of errors detected so far. - - - - - Get the number of bytes tested so far for the current entry. - - - - - Get a value indicating wether the last entry test was valid. - - - - - Delegate invoked during testing if supplied indicating current progress and status. - - If the message is non-null an error has occured. If the message is null - the operation as found in status has started. - - - - The possible ways of applying updates to an archive. - - - - - Perform all updates on temporary files ensuring that the original file is saved. - - - - - Update the archive directly, which is faster but less safe. - - - - - This class represents a Zip archive. You can ask for the contained - entries, or get an input stream for a file entry. The entry is - automatically decompressed. - - You can also update the archive adding or deleting entries. - - This class is thread safe for input: You can open input streams for arbitrary - entries in different threads. -
-
Author of the original java version : Jochen Hoenicke -
- - - using System; - using System.Text; - using System.Collections; - using System.IO; - - using ICSharpCode.SharpZipLib.Zip; - - class MainClass - { - static public void Main(string[] args) - { - using (ZipFile zFile = new ZipFile(args[0])) { - Console.WriteLine("Listing of : " + zFile.Name); - Console.WriteLine(""); - Console.WriteLine("Raw Size Size Date Time Name"); - Console.WriteLine("-------- -------- -------- ------ ---------"); - foreach (ZipEntry e in zFile) { - if ( e.IsFile ) { - DateTime d = e.DateTime; - Console.WriteLine("{0, -10}{1, -10}{2} {3} {4}", e.Size, e.CompressedSize, - d.ToString("dd-MM-yy"), d.ToString("HH:mm"), - e.Name); - } - } - } - } - } - - -
- - - Event handler for handling encryption keys. - - - - - Handles getting of encryption keys when required. - - The file for which encryption keys are required. - - - - Opens a Zip file with the given name for reading. - - The name of the file to open. - - An i/o error occurs - - - The file doesn't contain a valid zip archive. - - - - - Opens a Zip file reading the given . - - The to read archive data from. - - An i/o error occurs. - - - The file doesn't contain a valid zip archive. - - - - - Opens a Zip file reading the given . - - The to read archive data from. - - An i/o error occurs - - - The file doesn't contain a valid zip archive.
- The stream provided cannot seek -
-
- - - Initialises a default instance with no entries and no file storage. - - - - - Finalize this instance. - - - - - Closes the ZipFile. If the stream is owned then this also closes the underlying input stream. - Once closed, no further instance methods should be called. - - - An i/o error occurs. - - - - - Create a new whose data will be stored in a file. - - The name of the archive to create. - Returns the newly created - - - - Create a new whose data will be stored on a stream. - - The stream providing data storage. - Returns the newly created - - - - Gets an enumerator for the Zip entries in this Zip file. - - Returns an for this archive. - - The Zip file has been closed. - - - - - Return the index of the entry with a matching name - - Entry name to find - If true the comparison is case insensitive - The index position of the matching entry or -1 if not found - - The Zip file has been closed. - - - - - Searches for a zip entry in this archive with the given name. - String comparisons are case insensitive - - - The name to find. May contain directory components separated by slashes ('/'). - - - A clone of the zip entry, or null if no entry with that name exists. - - - The Zip file has been closed. - - - - - Gets an input stream for reading the given zip entry data in an uncompressed form. - Normally the should be an entry returned by GetEntry(). - - The to obtain a data for - An input containing data for this - - The ZipFile has already been closed - - - The compression method for the entry is unknown - - - The entry is not found in the ZipFile - - - - - Creates an input stream reading a zip entry - - The index of the entry to obtain an input stream for. - - An input containing data for this - - - The ZipFile has already been closed - - - The compression method for the entry is unknown - - - The entry is not found in the ZipFile - - - - - Test an archive for integrity/validity - - Perform low level data Crc check - true if all tests pass, false otherwise - Testing will terminate on the first error found. - - - - Test an archive for integrity/validity - - Perform low level data Crc check - The to apply. - The handler to call during testing. - true if all tests pass, false otherwise - - - - Test a local header against that provided from the central directory - - - The entry to test against - - The type of tests to carry out. - The offset of the entries data in the file - - - - Begin updating this archive. - - The archive storage for use during the update. - The data source to utilise during updating. - - - - Begin updating to this archive. - - The storage to use during the update. - - - - Begin updating this archive. - - - - - - - - Commit current updates, updating this archive. - - - - - - - Abort updating leaving the archive unchanged. - - - - - - - Set the file comment to be recorded when the current update is commited. - - The comment to record. - - - - Add a new entry to the archive. - - The name of the file to add. - The compression method to use. - Ensure Unicode text is used for name and comment for this entry. - - - - Add a new entry to the archive. - - The name of the file to add. - The compression method to use. - - - - Add a file to the archive. - - The name of the file to add. - - - - Add a file entry with data. - - The source of the data for this entry. - The name to give to the entry. - - - - Add a file entry with data. - - The source of the data for this entry. - The name to give to the entry. - The compression method to use. - - - - Add a file entry with data. - - The source of the data for this entry. - The name to give to the entry. - The compression method to use. - Ensure Unicode text is used for name and comments for this entry. - - - - Add a that contains no data. - - The entry to add. - This can be used to add directories, volume labels, or empty file entries. - - - - Add a directory entry to the archive. - - The directory to add. - - - - Delete an entry by name - - The filename to delete - True if the entry was found and deleted; false otherwise. - - - - Delete a from the archive. - - The entry to delete. - - - - Write an unsigned short in little endian byte order. - - - - - Write an int in little endian byte order. - - - - - Write an unsigned int in little endian byte order. - - - - - Write a long in little endian byte order. - - - - - Get a raw memory buffer. - - Returns a raw memory buffer. - - - - Get the size of the source descriptor for a . - - The update to get the size for. - The descriptor size, zero if there isnt one. - - - - Get an output stream for the specified - - The entry to get an output stream for. - The output stream obtained for the entry. - - - - Releases the unmanaged resources used by the this instance and optionally releases the managed resources. - - true to release both managed and unmanaged resources; - false to release only unmanaged resources. - - - - Read an unsigned short in little endian byte order. - - Returns the value read. - - The stream ends prematurely - - - - - Read a uint in little endian byte order. - - Returns the value read. - - An i/o error occurs. - - - The file ends prematurely - - - - - Search for and read the central directory of a zip file filling the entries array. - - - An i/o error occurs. - - - The central directory is malformed or cannot be found - - - - - Locate the data for a given entry. - - - The start offset of the data. - - - The stream ends prematurely - - - The local header signature is invalid, the entry and central header file name lengths are different - or the local and entry compression methods dont match - - - - - Get/set the encryption key value. - - - - - Password to be used for encrypting/decrypting files. - - Set to null if no password is required. - - - - Get a value indicating wether encryption keys are currently available. - - - - - Get/set a flag indicating if the underlying stream is owned by the ZipFile instance. - If the flag is true then the stream will be closed when Close is called. - - - The default value is true in all cases. - - - - - Get a value indicating wether - this archive is embedded in another file or not. - - - - - Get a value indicating that this archive is a new one. - - - - - Gets the comment for the zip file. - - - - - Gets the name of this zip file. - - - - - Gets the number of entries in this zip file. - - - The Zip file has been closed. - - - - - Get the number of entries contained in this . - - - - - Indexer property for ZipEntries - - - - - Get / set the to apply to names when updating. - - - - - Get/set the used to generate values - during updates. - - - - - Get /set the buffer size to be used when updating this zip file. - - - - - Get a value indicating an update has been started. - - - - - Get / set a value indicating how Zip64 Extension usage is determined when adding entries. - - - - - Delegate for handling keys/password setting during compresion/decompression. - - - - - The kind of update to apply. - - - - - Class used to sort updates. - - - - - Compares two objects and returns a value indicating whether one is - less than, equal to or greater than the other. - - First object to compare - Second object to compare. - Compare result. - - - - Represents a pending update to a Zip file. - - - - - Copy an existing entry. - - The existing entry to copy. - - - - Get the for this update. - - This is the source or original entry. - - - - Get the that will be written to the updated/new file. - - - - - Get the command for this update. - - - - - Get the filename if any for this update. Null if none exists. - - - - - Get/set the location of the size patch for this update. - - - - - Get /set the location of the crc patch for this update. - - - - - Represents a string from a which is stored as an array of bytes. - - - - - Initialise a with a string. - - The textual string form. - - - - Initialise a using a string in its binary 'raw' form. - - - - - - Reset the comment to its initial state. - - - - - Implicit conversion of comment to a string. - - The to convert to a string. - The textual equivalent for the input value. - - - - Get a value indicating the original source of data for this instance. - True if the source was a string; false if the source was binary data. - - - - - Get the length of the comment when represented as raw bytes. - - - - - Get the comment in its 'raw' form as plain bytes. - - - - - An enumerator for Zip entries - - - - - An is a stream that you can write uncompressed data - to and flush, but cannot read, seek or do anything else to. - - - - - Close this stream instance. - - - - - Write any buffered data to underlying storage. - - - - - Gets a value indicating whether the current stream supports reading. - - - - - Gets a value indicating whether the current stream supports writing. - - - - - Gets a value indicating whether the current stream supports seeking. - - - - - Get the length in bytes of the stream. - - - - - Gets or sets the position within the current stream. - - - - - A is an - whose data is only a part or subsection of a file. - - - - - This filter stream is used to decompress data compressed using the "deflate" - format. The "deflate" format is described in RFC 1951. - - This stream may form the basis for other decompression filters, such - as the GZipInputStream. - - Author of the original java version : John Leuner. - - - - - Create an InflaterInputStream with the default decompressor - and a default buffer size of 4KB. - - - The InputStream to read bytes from - - - - - Create an InflaterInputStream with the specified decompressor - and a default buffer size of 4KB. - - - The source of input data - - - The decompressor used to decompress data read from baseInputStream - - - - - Create an InflaterInputStream with the specified decompressor - and the specified buffer size. - - - The InputStream to read bytes from - - - The decompressor to use - - - Size of the buffer to use - - - - - Skip specified number of bytes of uncompressed data - - - Number of bytes to skip - - - The number of bytes skipped, zero if the end of - stream has been reached - - - Number of bytes to skip is less than zero - - - - - Clear any cryptographic state. - - - - - Fills the buffer with more data to decompress. - - - Stream ends early - - - - - Flushes the baseInputStream - - - - - Sets the position within the current stream - Always throws a NotSupportedException - - The relative offset to seek to. - The defining where to seek from. - The new position in the stream. - Any access - - - - Set the length of the current stream - Always throws a NotSupportedException - - The new length value for the stream. - Any access - - - - Writes a sequence of bytes to stream and advances the current position - This method always throws a NotSupportedException - - Thew buffer containing data to write. - The offset of the first byte to write. - The number of bytes to write. - Any access - - - - Writes one byte to the current stream and advances the current position - Always throws a NotSupportedException - - The byte to write. - Any access - - - - Entry point to begin an asynchronous write. Always throws a NotSupportedException. - - The buffer to write data from - Offset of first byte to write - The maximum number of bytes to write - The method to be called when the asynchronous write operation is completed - A user-provided object that distinguishes this particular asynchronous write request from other requests - An IAsyncResult that references the asynchronous write - Any access - - - - Closes the input stream. When - is true the underlying stream is also closed. - - - - - Reads decompressed data into the provided buffer byte array - - - The array to read and decompress data into - - - The offset indicating where the data should be placed - - - The number of bytes to decompress - - The number of bytes read. Zero signals the end of stream - - Inflater needs a dictionary - - - - - Decompressor for this stream - - - - - Input buffer for this stream. - - - - - Base stream the inflater reads from. - - - - - The compressed size - - - - - Flag indicating wether this instance has been closed or not. - - - - - Flag indicating wether this instance is designated the stream owner. - When closing if this flag is true the underlying stream is closed. - - - - - Get/set flag indicating ownership of underlying stream. - When the flag is true will close the underlying stream also. - - - The default value is true. - - - - - Returns 0 once the end of the stream (EOF) has been reached. - Otherwise returns 1. - - - - - Gets a value indicating whether the current stream supports reading - - - - - Gets a value of false indicating seeking is not supported for this stream. - - - - - Gets a value of false indicating that this stream is not writeable. - - - - - A value representing the length of the stream in bytes. - - - - - The current position within the stream. - Throws a NotSupportedException when attempting to set the position - - Attempting to set the position - - - - Initialise a new instance of the class. - - The underlying stream to use for IO. - The start of the partial data. - The length of the partial data. - - - - Skip the specified number of input bytes. - - The maximum number of input bytes to skip. - The actuial number of input bytes skipped. - - - - Read a byte from this stream. - - Returns the byte read or -1 on end of stream. - - - - Close this partial input stream. - - - The underlying stream is not closed. Close the parent ZipFile class to do that. - - - - - Provides a static way to obtain a source of data for an entry. - - - - - Get a source of data by creating a new stream. - - Returns a to use for compression input. - Ideally a new stream is created and opened to achieve this, to avoid locking problems. - - - - Represents a source of data that can dynamically provide - multiple data sources based on the parameters passed. - - - - - Get a data source. - - The to get a source for. - The name for data if known. - Returns a to use for compression input. - Ideally a new stream is created and opened to achieve this, to avoid locking problems. - - - - Default implementation of a for use with files stored on disk. - - - - - Initialise a new instnace of - - The name of the file to obtain data from. - - - - Get a providing data. - - Returns a provising data. - - - - Default implementation of for files stored on disk. - - - - - Initialise a default instance of . - - - - - Get a providing data for an entry. - - The entry to provide data for. - The file name for data if known. - Returns a stream providing data; or null if not available - - - - Defines facilities for data storage when updating Zip Archives. - - - - - Get an empty that can be used for temporary output. - - Returns a temporary output - - - - - Convert a temporary output stream to a final stream. - - The resulting final - - - - - Make a temporary copy of the original stream. - - The to copy. - Returns a temporary output that is a copy of the input. - - - - Return a stream suitable for performing direct updates on the original source. - - The current stream. - Returns a stream suitable for direct updating. - This may be the current stream passed. - - - - Dispose of this instance. - - - - - Get the to apply during updates. - - - - - An abstract suitable for extension by inheritance. - - - - - Initializes a new instance of the class. - - The update mode. - - - - Gets a temporary output - - Returns the temporary output stream. - - - - - Converts the temporary to its final form. - - Returns a that can be used to read - the final storage for the archive. - - - - - Make a temporary copy of a . - - The to make a copy of. - Returns a temporary output that is a copy of the input. - - - - Return a stream suitable for performing direct updates on the original source. - - The to open for direct update. - Returns a stream suitable for direct updating. - - - - Disposes this instance. - - - - - Gets the update mode applicable. - - The update mode. - - - - An implementation suitable for hard disks. - - - - - Initializes a new instance of the class. - - The file. - The update mode. - - - - Initializes a new instance of the class. - - The file. - - - - Gets a temporary output for performing updates on. - - Returns the temporary output stream. - - - - Converts a temporary to its final form. - - Returns a that can be used to read - the final storage for the archive. - - - - Make a temporary copy of a stream. - - The to copy. - Returns a temporary output that is a copy of the input. - - - - Return a stream suitable for performing direct updates on the original source. - - The current stream. - Returns a stream suitable for direct updating. - If the stream is not null this is used as is. - - - - Disposes this instance. - - - - - An implementation suitable for in memory streams. - - - - - Initializes a new instance of the class. - - - - - Initializes a new instance of the class. - - The to use - This constructor is for testing as memory streams dont really require safe mode. - - - - Gets the temporary output - - Returns the temporary output stream. - - - - Converts the temporary to its final form. - - Returns a that can be used to read - the final storage for the archive. - - - - Make a temporary copy of the original stream. - - The to copy. - Returns a temporary output that is a copy of the input. - - - - Return a stream suitable for performing direct updates on the original source. - - The original source stream - Returns a stream suitable for direct updating. - If the passed is not null this is used; - otherwise a new is returned. - - - - Disposes this instance. - - - - - Get the stream returned by if this was in fact called. - - - - - Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: - x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. - - Polynomials over GF(2) are represented in binary, one bit per coefficient, - with the lowest powers in the most significant bit. Then adding polynomials - is just exclusive-or, and multiplying a polynomial by x is a right shift by - one. If we call the above polynomial p, and represent a byte as the - polynomial q, also with the lowest power in the most significant bit (so the - byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, - where a mod b means the remainder after dividing a by b. - - This calculation is done using the shift-register method of multiplying and - taking the remainder. The register is initialized to zero, and for each - incoming bit, x^32 is added mod p to the register if the bit is a one (where - x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by - x (which is shifting right by one and adding x^32 mod p if the bit shifted - out is a one). We start with the highest power (least significant bit) of - q and repeat for all eight bits of q. - - The table is simply the CRC of all possible eight bit values. This is all - the information needed to generate CRC's on data a byte at a time for all - combinations of CRC register values and incoming bytes. - - - - - Interface to compute a data checksum used by checked input/output streams. - A data checksum can be updated by one byte or with a byte array. After each - update the value of the current checksum can be returned by calling - getValue. The complete checksum object can also be reset - so it can be used again with new data. - - - - - Resets the data checksum as if no update was ever called. - - - - - Adds one byte to the data checksum. - - - the data value to add. The high byte of the int is ignored. - - - - - Updates the data checksum with the bytes taken from the array. - - - buffer an array of bytes - - - - - Adds the byte array to the data checksum. - - - The buffer which contains the data - - - The offset in the buffer where the data starts - - - the number of data bytes to add. - - - - - Returns the data checksum computed so far. - - - - - The crc data checksum so far. - - - - - Resets the CRC32 data checksum as if no update was ever called. - - - - - Updates the checksum with the int bval. - - - the byte is taken as the lower 8 bits of value - - - - - Updates the checksum with the bytes taken from the array. - - - buffer an array of bytes - - - - - Adds the byte array to the data checksum. - - - The buffer which contains the data - - - The offset in the buffer where the data starts - - - The number of data bytes to update the CRC with. - - - - - Returns the CRC32 data checksum computed so far. - - - - - Basic implementation of - - - - - Defines factory methods for creating new values. - - - - - Create a for a file given its name - - The name of the file to create an entry for. - Returns a file entry based on the passed. - - - - Create a for a file given its name - - The name of the file to create an entry for. - If true get details from the file system if the file exists. - Returns a file entry based on the passed. - - - - Create a for a directory given its name - - The name of the directory to create an entry for. - Returns a directory entry based on the passed. - - - - Create a for a directory given its name - - The name of the directory to create an entry for. - If true get details from the file system for this directory if it exists. - Returns a directory entry based on the passed. - - - - Get/set the applicable. - - - - - Initialise a new instance of the class. - - A default , and the LastWriteTime for files is used. - - - - Initialise a new instance of using the specified - - The time setting to use when creating Zip entries. - - - - Initialise a new instance of using the specified - - The time to set all values to. - - - - Make a new for a file. - - The name of the file to create a new entry for. - Returns a new based on the . - - - - Make a new from a name. - - The name of the file to create a new entry for. - If true entry detail is retrieved from the file system if the file exists. - Returns a new based on the . - - - - Make a new for a directory. - - The raw untransformed name for the new directory - Returns a new representing a directory. - - - - Make a new for a directory. - - The raw untransformed name for the new directory - If true entry detail is retrieved from the file system if the file exists. - Returns a new representing a directory. - - - - Get / set the to be used when creating new values. - - - Setting this property to null will cause a default name transform to be used. - - - - - Get / set the in use. - - - - - Get / set the value to use when is set to - - - - - A bitmask defining the attributes to be retrieved from the actual file. - - The default is to get all possible attributes from the actual file. - - - - A bitmask defining which attributes are to be set on. - - By default no attributes are set on. - - - - Get set a value indicating wether unidoce text should be set on. - - - - - Defines the possible values to be used for the . - - - - - Use the recorded LastWriteTime value for the file. - - - - - Use the recorded LastWriteTimeUtc value for the file - - - - - Use the recorded CreateTime value for the file. - - - - - Use the recorded CreateTimeUtc value for the file. - - - - - Use the recorded LastAccessTime value for the file. - - - - - Use the recorded LastAccessTimeUtc value for the file. - - - - - Use a fixed value. - - The actual value used can be - specified via the constructor or - using the with the setting set - to which will use the when this class was constructed. - The property can also be used to set this value. - - - - PkzipClassic embodies the classic or original encryption facilities used in Pkzip archives. - While it has been superceded by more recent and more powerful algorithms, its still in use and - is viable for preventing casual snooping - - - - - Generates new encryption keys based on given seed - - The seed value to initialise keys with. - A new key value. - - - - PkzipClassicCryptoBase provides the low level facilities for encryption - and decryption using the PkzipClassic algorithm. - - - - - Transform a single byte - - - The transformed value - - - - - Set the key schedule for encryption/decryption. - - The data use to set the keys from. - - - - Update encryption keys - - - - - Reset the internal state. - - - - - PkzipClassic CryptoTransform for encryption. - - - - - Initialise a new instance of - - The key block to use. - - - - Transforms the specified region of the specified byte array. - - The input for which to compute the transform. - The offset into the byte array from which to begin using data. - The number of bytes in the byte array to use as data. - The computed transform. - - - - Transforms the specified region of the input byte array and copies - the resulting transform to the specified region of the output byte array. - - The input for which to compute the transform. - The offset into the input byte array from which to begin using data. - The number of bytes in the input byte array to use as data. - The output to which to write the transform. - The offset into the output byte array from which to begin writing data. - The number of bytes written. - - - - Cleanup internal state. - - - - - Gets a value indicating whether the current transform can be reused. - - - - - Gets the size of the input data blocks in bytes. - - - - - Gets the size of the output data blocks in bytes. - - - - - Gets a value indicating whether multiple blocks can be transformed. - - - - - PkzipClassic CryptoTransform for decryption. - - - - - Initialise a new instance of . - - The key block to decrypt with. - - - - Transforms the specified region of the specified byte array. - - The input for which to compute the transform. - The offset into the byte array from which to begin using data. - The number of bytes in the byte array to use as data. - The computed transform. - - - - Transforms the specified region of the input byte array and copies - the resulting transform to the specified region of the output byte array. - - The input for which to compute the transform. - The offset into the input byte array from which to begin using data. - The number of bytes in the input byte array to use as data. - The output to which to write the transform. - The offset into the output byte array from which to begin writing data. - The number of bytes written. - - - - Cleanup internal state. - - - - - Gets a value indicating whether the current transform can be reused. - - - - - Gets the size of the input data blocks in bytes. - - - - - Gets the size of the output data blocks in bytes. - - - - - Gets a value indicating whether multiple blocks can be transformed. - - - - - Defines a wrapper object to access the Pkzip algorithm. - This class cannot be inherited. - - - - - Generate an initial vector. - - - - - Generate a new random key. - - - - - Create an encryptor. - - The key to use for this encryptor. - Initialisation vector for the new encryptor. - Returns a new PkzipClassic encryptor - - - - Create a decryptor. - - Keys to use for this new decryptor. - Initialisation vector for the new decryptor. - Returns a new decryptor. - - - - Get / set the applicable block size in bits. - - The only valid block size is 8. - - - - Get an array of legal key sizes. - - - - - Get an array of legal block sizes. - - - - - Get / set the key value applicable. - - - - - This class represents an entry in a Tar archive. It consists - of the entry's header, as well as the entry's File. Entries - can be instantiated in one of three ways, depending on how - they are to be used. -

- TarEntries that are created from the header bytes read from - an archive are instantiated with the TarEntry( byte[] ) - constructor. These entries will be used when extracting from - or listing the contents of an archive. These entries have their - header filled in using the header bytes. They also set the File - to null, since they reference an archive entry not a file.

-

- TarEntries that are created from files that are to be written - into an archive are instantiated with the CreateEntryFromFile(string) - pseudo constructor. These entries have their header filled in using - the File's information. They also keep a reference to the File - for convenience when writing entries.

-

- Finally, TarEntries can be constructed from nothing but a name. - This allows the programmer to construct the entry by hand, for - instance when only an InputStream is available for writing to - the archive, and the header information is constructed from - other information. In this case the header fields are set to - defaults and the File is set to null.

- -
-
- - - Initialise a default instance of . - - - - - Construct an entry from an archive's header bytes. File is set - to null. - - - The header bytes from a tar archive entry. - - - - - Construct a TarEntry using the header provided - - Header details for entry - - - - Clone this tar entry. - - Returns a clone of this entry. - - - - Construct an entry with only a name. - This allows the programmer to construct the entry's header "by hand". - - The name to use for the entry - Returns the newly created - - - - Construct an entry for a file. File is set to file, and the - header is constructed from information from the file. - - The file name that the entry represents. - Returns the newly created - - - - Determine if the two entries are equal. Equality is determined - by the header names being equal. - - The to compare with the current Object. - - True if the entries are equal; false if not. - - - - - Derive a Hash value for the current - - A Hash code for the current - - - - Determine if the given entry is a descendant of this entry. - Descendancy is determined by the name of the descendant - starting with this entry's name. - - - Entry to be checked as a descendent of this. - - - True if entry is a descendant of this. - - - - - Convenience method to set this entry's group and user ids. - - - This entry's new user id. - - - This entry's new group id. - - - - - Convenience method to set this entry's group and user names. - - - This entry's new user name. - - - This entry's new group name. - - - - - Fill in a TarHeader with information from a File. - - - The TarHeader to fill in. - - - The file from which to get the header information. - - - - - Get entries for all files present in this entries directory. - If this entry doesnt represent a directory zero entries are returned. - - - An array of TarEntry's for this entry's children. - - - - - Write an entry's header information to a header buffer. - - - The tar entry header buffer to fill in. - - - - - Convenience method that will modify an entry's name directly - in place in an entry header buffer byte array. - - - The buffer containing the entry header to modify. - - - The new name to place into the header buffer. - - - - - Fill in a TarHeader given only the entry's name. - - - The TarHeader to fill in. - - - The tar entry name. - - - - - The name of the file this entry represents or null if the entry is not based on a file. - - - - - The entry's header information. - - - - - Get this entry's header. - - - This entry's TarHeader. - - - - - Get/Set this entry's name. - - - - - Get/set this entry's user id. - - - - - Get/set this entry's group id. - - - - - Get/set this entry's user name. - - - - - Get/set this entry's group name. - - - - - Get/Set the modification time for this entry - - - - - Get this entry's file. - - - This entry's file. - - - - - Get/set this entry's recorded file size. - - - - - Return true if this entry represents a directory, false otherwise - - - True if this entry is a directory. - - - - - This filter stream is used to decompress a "GZIP" format stream. - The "GZIP" format is described baseInputStream RFC 1952. - - author of the original java version : John Leuner - - This sample shows how to unzip a gzipped file - - using System; - using System.IO; - - using ICSharpCode.SharpZipLib.Core; - using ICSharpCode.SharpZipLib.GZip; - - class MainClass - { - public static void Main(string[] args) - { - using (Stream inStream = new GZipInputStream(File.OpenRead(args[0]))) - using (FileStream outStream = File.Create(Path.GetFileNameWithoutExtension(args[0]))) { - byte[] buffer = new byte[4096]; - StreamUtils.Copy(inStream, outStream, buffer); - } - } - } - - - - - - CRC-32 value for uncompressed data - - - - - Indicates end of stream - - - - - Creates a GZipInputStream with the default buffer size - - - The stream to read compressed data from (baseInputStream GZIP format) - - - - - Creates a GZIPInputStream with the specified buffer size - - - The stream to read compressed data from (baseInputStream GZIP format) - - - Size of the buffer to use - - - - - Reads uncompressed data into an array of bytes - - - The buffer to read uncompressed data into - - - The offset indicating where the data should be placed - - - The number of uncompressed bytes to be read - - Returns the number of bytes actually read. - - - - Provides simple " utilities. - - - - - Read from a ensuring all the required data is read. - - The stream to read. - The buffer to fill. - - - - Read from a " ensuring all the required data is read. - - The stream to read data from. - The buffer to store data in. - The offset at which to begin storing data. - The number of bytes of data to store. - - - - Copy the contents of one to another. - - The stream to source data from. - The stream to write data to. - The buffer to use during copying. - The progress handler delegate to use. - The minimum between progress updates. - The source for this event. - The name to use with the event. - - - - Copy the contents of one to another. - - The stream to source data from. - The stream to write data to. - The buffer to use during copying. - - - - Initialise an instance of - - - - - This is the DeflaterHuffman class. - - This class is not thread safe. This is inherent in the API, due - to the split of Deflate and SetInput. - - author of the original java version : Jochen Hoenicke - - - - - Pending buffer to use - - - - - Construct instance with pending buffer - - Pending buffer to use - - - - Reset internal state - - - - - Write all trees to pending buffer - - The number/rank of treecodes to send. - - - - Compress current buffer writing data to pending buffer - - - - - Flush block to output with no compression - - Data to write - Index of first byte to write - Count of bytes to write - True if this is the last block - - - - Flush block to output with compression - - Data to flush - Index of first byte to flush - Count of bytes to flush - True if this is the last block - - - - Get value indicating if internal buffer is full - - true if buffer is full - - - - Add literal to buffer - - Literal value to add to buffer. - Value indicating internal buffer is full - - - - Add distance code and length to literal and distance trees - - Distance code - Length - Value indicating if internal buffer is full - - - - Reverse the bits of a 16 bit value. - - Value to reverse bits - Value with bits reversed - - - - Resets the internal state of the tree - - - - - Check that all frequencies are zero - - - At least one frequency is non-zero - - - - - Set static codes and length - - new codes - length for new codes - - - - Build dynamic codes and lengths - - - - - Get encoded length - - Encoded length, the sum of frequencies * lengths - - - - Scan a literal or distance tree to determine the frequencies of the codes - in the bit length tree. - - - - - Write tree values - - Tree to write - - - - This class contains constants used for gzip. - - - - - Magic number found at start of GZIP header - - - - - Flag bit mask for text - - - - - Flag bitmask for Crc - - - - - Flag bit mask for extra - - - - - flag bitmask for name - - - - - flag bit mask indicating comment is present - - - - - Initialise default instance. - - Constructor is private to prevent instances being created. - - - - TarExceptions are used for exceptions specific to tar classes and code. - - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initialises a new instance of the TarException class. - - - - - Initialises a new instance of the TarException class with a specified message. - - The message that describes the error. - - - - - - A message describing the error. - The exception that is the cause of the current exception. - - - - Bzip2 checksum algorithm - - - - - Initialise a default instance of - - - - - Reset the state of Crc. - - - - - Update the Crc value. - - data update is based on - - - - Update Crc based on a block of data - - The buffer containing data to update the crc with. - - - - Update Crc based on a portion of a block of data - - block of data - index of first byte to use - number of bytes to use - - - - Get the current Crc value. - - - - - This is an InflaterInputStream that reads the files baseInputStream an zip archive - one after another. It has a special method to get the zip entry of - the next file. The zip entry contains information about the file name - size, compressed size, Crc, etc. - It includes support for Stored and Deflated entries. -
-
Author of the original java version : Jochen Hoenicke -
- - This sample shows how to read a zip file - - using System; - using System.Text; - using System.IO; - - using ICSharpCode.SharpZipLib.Zip; - - class MainClass - { - public static void Main(string[] args) - { - using ( ZipInputStream s = new ZipInputStream(File.OpenRead(args[0]))) { - - ZipEntry theEntry; - while ((theEntry = s.GetNextEntry()) != null) { - int size = 2048; - byte[] data = new byte[2048]; - - Console.Write("Show contents (y/n) ?"); - if (Console.ReadLine() == "y") { - while (true) { - size = s.Read(data, 0, data.Length); - if (size > 0) { - Console.Write(new ASCIIEncoding().GetString(data, 0, size)); - } else { - break; - } - } - } - } - } - } - } - - -
- - - The current reader this instance. - - - - - Creates a new Zip input stream, for reading a zip archive. - - The underlying providing data. - - - - Advances to the next entry in the archive - - - The next entry in the archive or null if there are no more entries. - - - If the previous entry is still open CloseEntry is called. - - - Input stream is closed - - - Password is not set, password is invalid, compression method is invalid, - version required to extract is not supported - - - - - Read data descriptor at the end of compressed data. - - - - - Complete cleanup as the final part of closing. - - True if the crc value should be tested - - - - Closes the current zip entry and moves to the next one. - - - The stream is closed - - - The Zip stream ends early - - - - - Reads a byte from the current zip entry. - - - The byte or -1 if end of stream is reached. - - - - - Handle attempts to read by throwing an . - - The destination array to store data in. - The offset at which data read should be stored. - The maximum number of bytes to read. - Returns the number of bytes actually read. - - - - Handle attempts to read from this entry by throwing an exception - - - - - Perform the initial read on an entry which may include - reading encryption headers and setting up inflation. - - The destination to fill with data read. - The offset to start reading at. - The maximum number of bytes to read. - The actual number of bytes read. - - - - Read a block of bytes from the stream. - - The destination for the bytes. - The index to start storing data. - The number of bytes to attempt to read. - Returns the number of bytes read. - Zero bytes read means end of stream. - - - - Reads a block of bytes from the current zip entry. - - - The number of bytes read (this may be less than the length requested, even before the end of stream), or 0 on end of stream. - - - An i/o error occured. - - - The deflated stream is corrupted. - - - The stream is not open. - - - - - Closes the zip input stream - - - - - Optional password used for encryption when non-null - - A password for all encrypted entries in this - - - - Gets a value indicating if there is a current entry and it can be decompressed - - - The entry can only be decompressed if the library supports the zip features required to extract it. - See the ZipEntry Version property for more details. - - - - - Returns 1 if there is an entry available - Otherwise returns 0. - - - - - Returns the current size that can be read from the current entry if available - - Thrown if the entry size is not known. - Thrown if no entry is currently available. - - - - ZipNameTransform transforms names as per the Zip file naming convention. - - The use of absolute names is supported although its use is not valid - according to Zip naming conventions, and should not be used if maximum compatability is desired. - - - - Initialize a new instance of - - - - - Initialize a new instance of - - The string to trim from front of paths if found. - - - - Static constructor. - - - - - Transform a directory name according to the Zip file naming conventions. - - The directory name to transform. - The transformed name. - - - - Transform a windows file name according to the Zip file naming conventions. - - The file name to transform. - The transformed name. - - - - Force a name to be valid by replacing invalid characters with a fixed value - - The name to force valid - The replacement character to use. - Returns a valid name - - - - Test a name to see if it is a valid name for a zip entry. - - The name to test. - If true checking is relaxed about windows file names and absolute paths. - Returns true if the name is a valid zip name; false otherwise. - Zip path names are actually in Unix format, and should only contain relative paths. - This means that any path stored should not contain a drive or - device letter, or a leading slash. All slashes should forward slashes '/'. - An empty name is valid for a file where the input comes from standard input. - A null name is not considered valid. - - - - - Test a name to see if it is a valid name for a zip entry. - - The name to test. - Returns true if the name is a valid zip name; false otherwise. - Zip path names are actually in unix format, - and should only contain relative paths if a path is present. - This means that the path stored should not contain a drive or - device letter, or a leading slash. All slashes should forward slashes '/'. - An empty name is valid where the input comes from standard input. - A null name is not considered valid. - - - - - Get/set the path prefix to be trimmed from paths if present. - - The prefix is trimmed before any conversion from - a windows path is done. - - - - This exception is used to indicate that there is a problem - with a TAR archive header. - - - - - Deserialization constructor - - for this constructor - for this constructor - - - - Initialise a new instance of the InvalidHeaderException class. - - - - - Initialises a new instance of the InvalidHeaderException class with a specified message. - - Message describing the exception cause. - - - - Initialise a new instance of InvalidHeaderException - - Message describing the problem. - The exception that is the cause of the current exception. - - - - This class allows us to retrieve a specified number of bits from - the input buffer, as well as copy big byte blocks. - - It uses an int buffer to store up to 31 bits for direct - manipulation. This guarantees that we can get at least 16 bits, - but we only need at most 15, so this is all safe. - - There are some optimizations in this class, for example, you must - never peek more than 8 bits more than needed, and you must first - peek bits before you may drop them. This is not a general purpose - class but optimized for the behaviour of the Inflater. - - authors of the original java version : John Leuner, Jochen Hoenicke - - - - - Constructs a default StreamManipulator with all buffers empty - - - - - Get the next sequence of bits but don't increase input pointer. bitCount must be - less or equal 16 and if this call succeeds, you must drop - at least n - 8 bits in the next call. - - The number of bits to peek. - - the value of the bits, or -1 if not enough bits available. */ - - - - - Drops the next n bits from the input. You should have called PeekBits - with a bigger or equal n before, to make sure that enough bits are in - the bit buffer. - - The number of bits to drop. - - - - Gets the next n bits and increases input pointer. This is equivalent - to followed by , except for correct error handling. - - The number of bits to retrieve. - - the value of the bits, or -1 if not enough bits available. - - - - - Skips to the next byte boundary. - - - - - Copies bytes from input buffer to output buffer starting - at output[offset]. You have to make sure, that the buffer is - byte aligned. If not enough bytes are available, copies fewer - bytes. - - - The buffer to copy bytes to. - - - The offset in the buffer at which copying starts - - - The length to copy, 0 is allowed. - - - The number of bytes copied, 0 if no bytes were available. - - - Length is less than zero - - - Bit buffer isnt byte aligned - - - - - Resets state and empties internal buffers - - - - - Add more input for consumption. - Only call when IsNeedingInput returns true - - data to be input - offset of first byte of input - number of bytes of input to add. - - - - Gets the number of bits available in the bit buffer. This must be - only called when a previous PeekBits() returned -1. - - - the number of bits available. - - - - - Gets the number of bytes available. - - - The number of bytes available. - - - - - Returns true when SetInput can be called - - - - - Strategies for deflater - - - - - The default strategy - - - - - This strategy will only allow longer string repetitions. It is - useful for random data with a small character set. - - - - - This strategy will not look for string repetitions at all. It - only encodes with Huffman trees (which means, that more common - characters get a smaller encoding. - - - - - Low level compression engine for deflate algorithm which uses a 32K sliding window - with secondary compression from Huffman/Shannon-Fano codes. - - - - - Construct instance with pending buffer - - - Pending buffer to use - > - - - - Deflate drives actual compression of data - - True to flush input buffers - Finish deflation with the current input. - Returns true if progress has been made. - - - - Sets input data to be deflated. Should only be called when NeedsInput() - returns true - - The buffer containing input data. - The offset of the first byte of data. - The number of bytes of data to use as input. - - - - Determines if more input is needed. - - Return true if input is needed via SetInput - - - - Set compression dictionary - - The buffer containing the dictionary data - The offset in the buffer for the first byte of data - The length of the dictionary data. - - - - Reset internal state - - - - - Reset Adler checksum - - - - - Set the deflate level (0-9) - - The value to set the level to. - - - - Fill the window - - - - - Inserts the current string in the head hash and returns the previous - value for this hash. - - The previous hash value - - - - Find the best (longest) string in the window matching the - string starting at strstart. - - Preconditions: - - strstart + MAX_MATCH <= window.length. - - - True if a match greater than the minimum length is found - - - - Hashtable, hashing three characters to an index for window, so - that window[index]..window[index+2] have this hash code. - Note that the array should really be unsigned short, so you need - to and the values with 0xffff. - - - - - prev[index & WMASK] points to the previous index that has the - same hash code as the string starting at index. This way - entries with the same hash code are in a linked list. - Note that the array should really be unsigned short, so you need - to and the values with 0xffff. - - - - - Points to the current character in the window. - - - - - lookahead is the number of characters starting at strstart in - window that are valid. - So window[strstart] until window[strstart+lookahead-1] are valid - characters. - - - - - This array contains the part of the uncompressed stream that - is of relevance. The current character is indexed by strstart. - - - - - The current compression function. - - - - - The input data for compression. - - - - - The total bytes of input read. - - - - - The offset into inputBuf, where input data starts. - - - - - The end offset of the input data. - - - - - The adler checksum - - - - - Get current value of Adler checksum - - - - - Total data processed - - - - - Get/set the deflate strategy - - - - - The TarBuffer class implements the tar archive concept - of a buffered input stream. This concept goes back to the - days of blocked tape drives and special io devices. In the - C# universe, the only real function that this class - performs is to ensure that files have the correct "record" - size, or other tars will complain. -

- You should never have a need to access this class directly. - TarBuffers are created by Tar IO Streams. -

-
-
- - - The size of a block in a tar archive in bytes. - - This is 512 bytes. - - - - The number of blocks in a default record. - - - The default value is 20 blocks per record. - - - - - The size in bytes of a default record. - - - The default size is 10KB. - - - - - Get the TAR Buffer's record size. - - The record size in bytes. - This is equal to the multiplied by the - - - - Get the TAR Buffer's block factor - - The block factor; the number of blocks per record. - - - - Construct a default TarBuffer - - - - - Create TarBuffer for reading with default BlockFactor - - Stream to buffer - A new suitable for input. - - - - Construct TarBuffer for reading inputStream setting BlockFactor - - Stream to buffer - Blocking factor to apply - A new suitable for input. - - - - Construct TarBuffer for writing with default BlockFactor - - output stream for buffer - A new suitable for output. - - - - Construct TarBuffer for writing Tar output to streams. - - Output stream to write to. - Blocking factor to apply - A new suitable for output. - - - - Initialization common to all constructors. - - - - - Determine if an archive block indicates End of Archive. End of - archive is indicated by a block that consists entirely of null bytes. - All remaining blocks for the record should also be null's - However some older tars only do a couple of null blocks (Old GNU tar for one) - and also partial records - - The data block to check. - Returns true if the block is an EOF block; false otherwise. - - - - Skip over a block on the input stream. - - - - - Read a block from the input stream. - - - The block of data read. - - - - - Read a record from data stream. - - - false if End-Of-File, else true. - - - - - Get the current block number, within the current record, zero based. - - - The current zero based block number. - - - The absolute block number = (record number * block factor) + block number. - - - - - Get the current record number. - - - The current zero based record number. - - - - - Write a block of data to the archive. - - - The data to write to the archive. - - - - - Write an archive record to the archive, where the record may be - inside of a larger array buffer. The buffer must be "offset plus - record size" long. - - - The buffer containing the record data to write. - - - The offset of the record data within buffer. - - - - - Write a TarBuffer record to the archive. - - - - - Flush the current record if it has any data in it. - - - - - Close the TarBuffer. If this is an output buffer, also flush the - current block before closing. - - - - - Get the record size for this buffer - - The record size in bytes. - This is equal to the multiplied by the - - - - Get the Blocking factor for the buffer - - This is the number of block in each record. - - - - Get the current block number, within the current record, zero based. - - - - - Get the current record number. - - - The current zero based record number. - - - - - This class encapsulates the Tar Entry Header used in Tar Archives. - The class also holds a number of tar constants, used mostly in headers. - - - - - The length of the name field in a header buffer. - - - - - The length of the mode field in a header buffer. - - - - - The length of the user id field in a header buffer. - - - - - The length of the group id field in a header buffer. - - - - - The length of the checksum field in a header buffer. - - - - - Offset of checksum in a header buffer. - - - - - The length of the size field in a header buffer. - - - - - The length of the magic field in a header buffer. - - - - - The length of the version field in a header buffer. - - - - - The length of the modification time field in a header buffer. - - - - - The length of the user name field in a header buffer. - - - - - The length of the group name field in a header buffer. - - - - - The length of the devices field in a header buffer. - - - - - The "old way" of indicating a normal file. - - - - - Normal file type. - - - - - Link file type. - - - - - Symbolic link file type. - - - - - Character device file type. - - - - - Block device file type. - - - - - Directory file type. - - - - - FIFO (pipe) file type. - - - - - Contiguous file type. - - - - - Posix.1 2001 global extended header - - - - - Posix.1 2001 extended header - - - - - Solaris access control list file type - - - - - GNU dir dump file type - This is a dir entry that contains the names of files that were in the - dir at the time the dump was made - - - - - Solaris Extended Attribute File - - - - - Inode (metadata only) no file content - - - - - Identifies the next file on the tape as having a long link name - - - - - Identifies the next file on the tape as having a long name - - - - - Continuation of a file that began on another volume - - - - - For storing filenames that dont fit in the main header (old GNU) - - - - - GNU Sparse file - - - - - GNU Tape/volume header ignore on extraction - - - - - The magic tag representing a POSIX tar archive. (includes trailing NULL) - - - - - The magic tag representing an old GNU tar archive where version is included in magic and overwrites it - - - - - Initialise a default TarHeader instance - - - - - Get the name of this entry. - - The entry's name. - - - - Create a new that is a copy of the current instance. - - A new that is a copy of the current instance. - - - - Parse TarHeader information from a header buffer. - - - The tar entry header buffer to get information from. - - - - - 'Write' header information to buffer provided, updating the check sum. - - output buffer for header information - - - - Get a hash code for the current object. - - A hash code for the current object. - - - - Determines if this instance is equal to the specified object. - - The object to compare with. - true if the objects are equal, false otherwise. - - - - Set defaults for values used when constructing a TarHeader instance. - - Value to apply as a default for userId. - Value to apply as a default for userName. - Value to apply as a default for groupId. - Value to apply as a default for groupName. - - - - Parse an octal string from a header buffer. - - The header buffer from which to parse. - The offset into the buffer from which to parse. - The number of header bytes to parse. - The long equivalent of the octal string. - - - - Parse a name from a header buffer. - - - The header buffer from which to parse. - - - The offset into the buffer from which to parse. - - - The number of header bytes to parse. - - - The name parsed. - - - - - Add name to the buffer as a collection of bytes - - The name to add - The offset of the first character - The buffer to add to - The index of the first byte to add - The number of characters/bytes to add - The next free index in the buffer - - - - Add name to the buffer as a collection of bytes - - The name to add - The offset of the first character - The buffer to add to - The index of the first byte to add - The number of characters/bytes to add - The next free index in the buffer - - - - Add an entry name to the buffer - - - The name to add - - - The buffer to add to - - - The offset into the buffer from which to start adding - - - The number of header bytes to add - - - The index of the next free byte in the buffer - - - - - Add an entry name to the buffer - - The name to add - The buffer to add to - The offset into the buffer from which to start adding - The number of header bytes to add - The index of the next free byte in the buffer - - - - Add a string to a buffer as a collection of ascii bytes. - - The string to add - The offset of the first character to add. - The buffer to add to. - The offset to start adding at. - The number of ascii characters to add. - The next free index in the buffer. - - - - Put an octal representation of a value into a buffer - - - the value to be converted to octal - - - buffer to store the octal string - - - The offset into the buffer where the value starts - - - The length of the octal string to create - - - The offset of the character next byte after the octal string - - - - - Put an octal representation of a value into a buffer - - Value to be convert to octal - The buffer to update - The offset into the buffer to store the value - The length of the octal string - Index of next byte - - - - Add the checksum integer to header buffer. - - - The header buffer to set the checksum for - The offset into the buffer for the checksum - The number of header bytes to update. - It's formatted differently from the other fields: it has 6 digits, a - null, then a space -- rather than digits, a space, then a null. - The final space is already there, from checksumming - - The modified buffer offset - - - - Compute the checksum for a tar entry header. - The checksum field must be all spaces prior to this happening - - The tar entry's header buffer. - The computed checksum. - - - - Make a checksum for a tar entry ignoring the checksum contents. - - The tar entry's header buffer. - The checksum for the buffer - - - - Get/set the name for this tar entry. - - Thrown when attempting to set the property to null. - - - - Get/set the entry's Unix style permission mode. - - - - - The entry's user id. - - - This is only directly relevant to unix systems. - The default is zero. - - - - - Get/set the entry's group id. - - - This is only directly relevant to linux/unix systems. - The default value is zero. - - - - - Get/set the entry's size. - - Thrown when setting the size to less than zero. - - - - Get/set the entry's modification time. - - - The modification time is only accurate to within a second. - - Thrown when setting the date time to less than 1/1/1970. - - - - Get the entry's checksum. This is only valid/updated after writing or reading an entry. - - - - - Get value of true if the header checksum is valid, false otherwise. - - - - - Get/set the entry's type flag. - - - - - The entry's link name. - - Thrown when attempting to set LinkName to null. - - - - Get/set the entry's magic tag. - - Thrown when attempting to set Magic to null. - - - - The entry's version. - - Thrown when attempting to set Version to null. - - - - The entry's user name. - - - - - Get/set the entry's group name. - - - This is only directly relevant to unix systems. - - - - - Get/set the entry's major device number. - - - - - Get/set the entry's minor device number. - - - - - Event arguments for scanning. - - - - - Initialise a new instance of - - The file or directory name. - - - - The fie or directory name for this event. - - - - - Get set a value indicating if scanning should continue or not. - - - - - Event arguments during processing of a single file or directory. - - - - - Initialise a new instance of - - The file or directory name if known. - The number of bytes processed so far - The total number of bytes to process, 0 if not known - - - - The name for this event if known. - - - - - Get set a value indicating wether scanning should continue or not. - - - - - Get a percentage representing how much of the has been processed - - 0.0 to 100.0 percent; 0 if target is not known. - - - - The number of bytes processed so far - - - - - The number of bytes to process. - - Target may be 0 or negative if the value isnt known. - - - - Event arguments for directories. - - - - - Initialize an instance of . - - The name for this directory. - Flag value indicating if any matching files are contained in this directory. - - - - Get a value indicating if the directory contains any matching files or not. - - - - - Arguments passed when scan failures are detected. - - - - - Initialise a new instance of - - The name to apply. - The exception to use. - - - - The applicable name. - - - - - The applicable exception. - - - - - Get / set a value indicating wether scanning should continue. - - - - - Delegate invoked before starting to process a directory. - - - - - Delegate invoked before starting to process a file. - - The source of the event - The event arguments. - - - - Delegate invoked during processing of a file or directory - - The source of the event - The event arguments. - - - - Delegate invoked when a file has been completely processed. - - The source of the event - The event arguments. - - - - Delegate invoked when a directory failure is detected. - - The source of the event - The event arguments. - - - - Delegate invoked when a file failure is detected. - - The source of the event - The event arguments. - - - - FileSystemScanner provides facilities scanning of files and directories. - - - - - Initialise a new instance of - - The file filter to apply when scanning. - - - - Initialise a new instance of - - The file filter to apply. - The directory filter to apply. - - - - Initialise a new instance of - - The file filter to apply. - - - - Initialise a new instance of - - The file filter to apply. - The directory filter to apply. - - - - Delegate to invoke when a directory is processed. - - - - - Delegate to invoke when a file is processed. - - - - - Delegate to invoke when processing for a file has finished. - - - - - Delegate to invoke when a directory failure is detected. - - - - - Delegate to invoke when a file failure is detected. - - - - - Raise the DirectoryFailure event. - - The directory name. - The exception detected. - - - - Raise the FileFailure event. - - The file name. - The exception detected. - - - - Raise the ProcessFile event. - - The file name. - - - - Raise the complete file event - - The file name - - - - Raise the ProcessDirectory event. - - The directory name. - Flag indicating if the directory has matching files. - - - - Scan a directory. - - The base directory to scan. - True to recurse subdirectories, false to scan a single directory. - - - - The file filter currently in use. - - - - - The directory filter currently in use. - - - - - Flag indicating if scanning should continue running. - - - - - An input buffer customised for use by - - - The buffer supports decryption of incoming data. - - - - - Initialise a new instance of with a default buffer size - - The stream to buffer. - - - - Initialise a new instance of - - The stream to buffer. - The size to use for the buffer - A minimum buffer size of 1KB is permitted. Lower sizes are treated as 1KB. - - - - Call passing the current clear text buffer contents. - - The inflater to set input for. - - - - Fill the buffer from the underlying input stream. - - - - - Read a buffer directly from the input stream - - The buffer to fill - Returns the number of bytes read. - - - - Read a buffer directly from the input stream - - The buffer to read into - The offset to start reading data into. - The number of bytes to read. - Returns the number of bytes read. - - - - Read clear text data from the input stream. - - The buffer to add data to. - The offset to start adding data at. - The number of bytes to read. - Returns the number of bytes actually read. - - - - Read a from the input stream. - - Returns the byte read. - - - - Read an in little endian byte order. - - The short value read case to an int. - - - - Read an in little endian byte order. - - The int value read. - - - - Read a in little endian byte order. - - The long value read. - - - - Get the length of bytes bytes in the - - - - - Get the contents of the raw data buffer. - - This may contain encrypted data. - - - - Get the number of useable bytes in - - - - - Get the contents of the clear text buffer. - - - - - Get/set the number of bytes available - - - - - Get/set the to apply to any data. - - Set this value to null to have no transform applied. - - - - The TarOutputStream writes a UNIX tar archive as an OutputStream. - Methods are provided to put entries, and then write their contents - by writing to this stream using write(). - - public - - - - Construct TarOutputStream using default block factor - - stream to write to - - - - Construct TarOutputStream with user specified block factor - - stream to write to - blocking factor - - - - set the position within the current stream - - The offset relative to the to seek to - The to seek from. - The new position in the stream. - - - - Set the length of the current stream - - The new stream length. - - - - Read a byte from the stream and advance the position within the stream - by one byte or returns -1 if at the end of the stream. - - The byte value or -1 if at end of stream - - - - read bytes from the current stream and advance the position within the - stream by the number of bytes read. - - The buffer to store read bytes in. - The index into the buffer to being storing bytes at. - The desired number of bytes to read. - The total number of bytes read, or zero if at the end of the stream. - The number of bytes may be less than the count - requested if data is not avialable. - - - - All buffered data is written to destination - - - - - Ends the TAR archive without closing the underlying OutputStream. - The result is that the EOF block of nulls is written. - - - - - Ends the TAR archive and closes the underlying OutputStream. - - This means that Finish() is called followed by calling the - TarBuffer's Close(). - - - - Get the record size being used by this stream's TarBuffer. - - - The TarBuffer record size. - - - - - Put an entry on the output stream. This writes the entry's - header and positions the output stream for writing - the contents of the entry. Once this method is called, the - stream is ready for calls to write() to write the entry's - contents. Once the contents are written, closeEntry() - MUST be called to ensure that all buffered data - is completely written to the output stream. - - - The TarEntry to be written to the archive. - - - - - Close an entry. This method MUST be called for all file - entries that contain data. The reason is that we must - buffer data written to the stream in order to satisfy - the buffer's block based writes. Thus, there may be - data fragments still being assembled that must be written - to the output stream before this entry is closed and the - next entry written. - - - - - Writes a byte to the current tar archive entry. - This method simply calls Write(byte[], int, int). - - - The byte to be written. - - - - - Writes bytes to the current tar archive entry. This method - is aware of the current entry and will throw an exception if - you attempt to write bytes past the length specified for the - current entry. The method is also (painfully) aware of the - record buffering required by TarBuffer, and manages buffers - that are not a multiple of recordsize in length, including - assembling records from small buffers. - - - The buffer to write to the archive. - - - The offset in the buffer from which to get bytes. - - - The number of bytes to write. - - - - - Write an EOF (end of archive) block to the tar archive. - An EOF block consists of all zeros. - - - - - bytes written for this entry so far - - - - - current 'Assembly' buffer length - - - - - Flag indicating wether this instance has been closed or not. - - - - - Size for the current entry - - - - - single block working buffer - - - - - 'Assembly' buffer used to assemble data before writing - - - - - TarBuffer used to provide correct blocking factor - - - - - the destination stream for the archive contents - - - - - true if the stream supports reading; otherwise, false. - - - - - true if the stream supports seeking; otherwise, false. - - - - - true if stream supports writing; otherwise, false. - - - - - length of stream in bytes - - - - - gets or sets the position within the current stream. - - - - - Get the record size being used by this stream's TarBuffer. - - - - - Get a value indicating wether an entry is open, requiring more data to be written. - - - - - This is the Deflater class. The deflater class compresses input - with the deflate algorithm described in RFC 1951. It has several - compression levels and three different strategies described below. - - This class is not thread safe. This is inherent in the API, due - to the split of deflate and setInput. - - author of the original java version : Jochen Hoenicke - - - - - The best and slowest compression level. This tries to find very - long and distant string repetitions. - - - - - The worst but fastest compression level. - - - - - The default compression level. - - - - - This level won't compress at all but output uncompressed blocks. - - - - - The compression method. This is the only method supported so far. - There is no need to use this constant at all. - - - - - Creates a new deflater with default compression level. - - - - - Creates a new deflater with given compression level. - - - the compression level, a value between NO_COMPRESSION - and BEST_COMPRESSION, or DEFAULT_COMPRESSION. - - if lvl is out of range. - - - - Creates a new deflater with given compression level. - - - the compression level, a value between NO_COMPRESSION - and BEST_COMPRESSION. - - - true, if we should suppress the Zlib/RFC1950 header at the - beginning and the adler checksum at the end of the output. This is - useful for the GZIP/PKZIP formats. - - if lvl is out of range. - - - - Resets the deflater. The deflater acts afterwards as if it was - just created with the same compression level and strategy as it - had before. - - - - - Flushes the current input block. Further calls to deflate() will - produce enough output to inflate everything in the current input - block. This is not part of Sun's JDK so I have made it package - private. It is used by DeflaterOutputStream to implement - flush(). - - - - - Finishes the deflater with the current input block. It is an error - to give more input after this method was called. This method must - be called to force all bytes to be flushed. - - - - - Sets the data which should be compressed next. This should be only - called when needsInput indicates that more input is needed. - If you call setInput when needsInput() returns false, the - previous input that is still pending will be thrown away. - The given byte array should not be changed, before needsInput() returns - true again. - This call is equivalent to setInput(input, 0, input.length). - - - the buffer containing the input data. - - - if the buffer was finished() or ended(). - - - - - Sets the data which should be compressed next. This should be - only called when needsInput indicates that more input is needed. - The given byte array should not be changed, before needsInput() returns - true again. - - - the buffer containing the input data. - - - the start of the data. - - - the number of data bytes of input. - - - if the buffer was Finish()ed or if previous input is still pending. - - - - - Sets the compression level. There is no guarantee of the exact - position of the change, but if you call this when needsInput is - true the change of compression level will occur somewhere near - before the end of the so far given input. - - - the new compression level. - - - - - Get current compression level - - Returns the current compression level - - - - Sets the compression strategy. Strategy is one of - DEFAULT_STRATEGY, HUFFMAN_ONLY and FILTERED. For the exact - position where the strategy is changed, the same as for - SetLevel() applies. - - - The new compression strategy. - - - - - Deflates the current input block with to the given array. - - - The buffer where compressed data is stored - - - The number of compressed bytes added to the output, or 0 if either - IsNeedingInput() or IsFinished returns true or length is zero. - - - - - Deflates the current input block to the given array. - - - Buffer to store the compressed data. - - - Offset into the output array. - - - The maximum number of bytes that may be stored. - - - The number of compressed bytes added to the output, or 0 if either - needsInput() or finished() returns true or length is zero. - - - If Finish() was previously called. - - - If offset or length don't match the array length. - - - - - Sets the dictionary which should be used in the deflate process. - This call is equivalent to setDictionary(dict, 0, dict.Length). - - - the dictionary. - - - if SetInput () or Deflate () were already called or another dictionary was already set. - - - - - Sets the dictionary which should be used in the deflate process. - The dictionary is a byte array containing strings that are - likely to occur in the data which should be compressed. The - dictionary is not stored in the compressed output, only a - checksum. To decompress the output you need to supply the same - dictionary again. - - - The dictionary data - - - The index where dictionary information commences. - - - The number of bytes in the dictionary. - - - If SetInput () or Deflate() were already called or another dictionary was already set. - - - - - Compression level. - - - - - If true no Zlib/RFC1950 headers or footers are generated - - - - - The current state. - - - - - The total bytes of output written. - - - - - The pending output. - - - - - The deflater engine. - - - - - Gets the current adler checksum of the data that was processed so far. - - - - - Gets the number of input bytes processed so far. - - - - - Gets the number of output bytes so far. - - - - - Returns true if the stream was finished and no more output bytes - are available. - - - - - Returns true, if the input buffer is empty. - You should then call setInput(). - NOTE: This method can also return true when the stream - was finished. - - - - - The TarInputStream reads a UNIX tar archive as an InputStream. - methods are provided to position at each successive entry in - the archive, and the read each entry as a normal input stream - using read(). - - - - - Construct a TarInputStream with default block factor - - stream to source data from - - - - Construct a TarInputStream with user specified block factor - - stream to source data from - block factor to apply to archive - - - - Flushes the baseInputStream - - - - - Set the streams position. This operation is not supported and will throw a NotSupportedException - - The offset relative to the origin to seek to. - The to start seeking from. - The new position in the stream. - Any access - - - - Sets the length of the stream - This operation is not supported and will throw a NotSupportedException - - The new stream length. - Any access - - - - Writes a block of bytes to this stream using data from a buffer. - This operation is not supported and will throw a NotSupportedException - - The buffer containing bytes to write. - The offset in the buffer of the frist byte to write. - The number of bytes to write. - Any access - - - - Writes a byte to the current position in the file stream. - This operation is not supported and will throw a NotSupportedException - - The byte value to write. - Any access - - - - Reads a byte from the current tar archive entry. - - A byte cast to an int; -1 if the at the end of the stream. - - - - Reads bytes from the current tar archive entry. - - This method is aware of the boundaries of the current - entry in the archive and will deal with them appropriately - - - The buffer into which to place bytes read. - - - The offset at which to place bytes read. - - - The number of bytes to read. - - - The number of bytes read, or 0 at end of stream/EOF. - - - - - Closes this stream. Calls the TarBuffer's close() method. - The underlying stream is closed by the TarBuffer. - - - - - Set the entry factory for this instance. - - The factory for creating new entries - - - - Get the record size being used by this stream's TarBuffer. - - - TarBuffer record size. - - - - - Skip bytes in the input buffer. This skips bytes in the - current entry's data, not the entire archive, and will - stop at the end of the current entry's data if the number - to skip extends beyond that point. - - - The number of bytes to skip. - - - - - Since we do not support marking just yet, we do nothing. - - - The limit to mark. - - - - - Since we do not support marking just yet, we do nothing. - - - - - Get the next entry in this tar archive. This will skip - over any remaining data in the current entry, if there - is one, and place the input stream at the header of the - next entry, and read the header and instantiate a new - TarEntry from the header bytes and return that entry. - If there are no more entries in the archive, null will - be returned to indicate that the end of the archive has - been reached. - - - The next TarEntry in the archive, or null. - - - - - Copies the contents of the current tar archive entry directly into - an output stream. - - - The OutputStream into which to write the entry's data. - - - - - Flag set when last block has been read - - - - - Size of this entry as recorded in header - - - - - Number of bytes read for this entry so far - - - - - Buffer used with calls to Read() - - - - - Working buffer - - - - - Current entry being read - - - - - Factory used to create TarEntry or descendant class instance - - - - - Stream used as the source of input data. - - - - - Gets a value indicating whether the current stream supports reading - - - - - Gets a value indicating whether the current stream supports seeking - This property always returns false. - - - - - Gets a value indicating if the stream supports writing. - This property always returns false. - - - - - The length in bytes of the stream - - - - - Gets or sets the position within the stream. - Setting the Position is not supported and throws a NotSupportedExceptionNotSupportedException - - Any attempt to set position - - - - Get the record size being used by this stream's TarBuffer. - - - - - Get the available data that can be read from the current - entry in the archive. This does not indicate how much data - is left in the entire archive, only in the current entry. - This value is determined from the entry's size header field - and the amount of data already read from the current entry. - - - The number of available bytes for the current entry. - - - - - Return a value of true if marking is supported; false otherwise. - - Currently marking is not supported, the return value is always false. - - - - This interface is provided, along with the method , to allow - the programmer to have their own subclass instantiated for the - entries return from . - - - - - Create an entry based on name alone - - - Name of the new EntryPointNotFoundException to create - - created TarEntry or descendant class - - - - Create an instance based on an actual file - - - Name of file to represent in the entry - - - Created TarEntry or descendant class - - - - - Create a tar entry based on the header information passed - - - Buffer containing header information to base entry on - - - Created TarEntry or descendant class - - - - - Standard entry factory class creating instances of the class TarEntry - - - - - Create a based on named - - The name to use for the entry - A new - - - - Create a tar entry with details obtained from file - - The name of the file to retrieve details from. - A new - - - - Create an entry based on details in header - - The buffer containing entry details. - A new - - - - Defines known values for the property. - - - - - Host system = MSDOS - - - - - Host system = Amiga - - - - - Host system = Open VMS - - - - - Host system = Unix - - - - - Host system = VMCms - - - - - Host system = Atari ST - - - - - Host system = OS2 - - - - - Host system = Macintosh - - - - - Host system = ZSystem - - - - - Host system = Cpm - - - - - Host system = Windows NT - - - - - Host system = MVS - - - - - Host system = VSE - - - - - Host system = Acorn RISC - - - - - Host system = VFAT - - - - - Host system = Alternate MVS - - - - - Host system = BEOS - - - - - Host system = Tandem - - - - - Host system = OS400 - - - - - Host system = OSX - - - - - Host system = WinZIP AES - - - - - This class represents an entry in a zip archive. This can be a file - or a directory - ZipFile and ZipInputStream will give you instances of this class as - information about the members in an archive. ZipOutputStream - uses an instance of this class when creating an entry in a Zip file. -
-
Author of the original java version : Jochen Hoenicke -
-
- - - Creates a zip entry with the given name. - - - The name for this entry. Can include directory components. - The convention for names is 'unix' style paths with relative names only. - There are with no device names and path elements are separated by '/' characters. - - - The name passed is null - - - - - Creates a zip entry with the given name and version required to extract - - - The name for this entry. Can include directory components. - The convention for names is 'unix' style paths with no device names and - path elements separated by '/' characters. This is not enforced see CleanName - on how to ensure names are valid if this is desired. - - - The minimum 'feature version' required this entry - - - The name passed is null - - - - - Initializes an entry with the given name and made by information - - Name for this entry - Version and HostSystem Information - Minimum required zip feature version required to extract this entry - Compression method for this entry. - - The name passed is null - - - versionRequiredToExtract should be 0 (auto-calculate) or > 10 - - - This constructor is used by the ZipFile class when reading from the central header - It is not generally useful, use the constructor specifying the name only. - - - - - Creates a deep copy of the given zip entry. - - - The entry to copy. - - - - - Test the external attributes for this to - see if the external attributes are Dos based (including WINNT and variants) - and match the values - - The attributes to test. - Returns true if the external attributes are known to be DOS/Windows - based and have the same attributes set as the value passed. - - - - Force this entry to be recorded using Zip64 extensions. - - - - - Get a value indicating wether Zip64 extensions were forced. - - A value of true if Zip64 extensions have been forced on; false if not. - - - - Process extra data fields updating the entry based on the contents. - - True if the extra data fields should be handled - for a local header, rather than for a central header. - - - - - Test entry to see if data can be extracted. - - Returns true if data can be extracted for this entry; false otherwise. - - - - Creates a copy of this zip entry. - - An that is a copy of the current instance. - - - - Gets a string representation of this ZipEntry. - - A readable textual representation of this - - - - Test a compression method to see if this library - supports extracting data compressed with that method - - The compression method to test. - Returns true if the compression method is supported; false otherwise - - - - Cleans a name making it conform to Zip file conventions. - Devices names ('c:\') and UNC share names ('\\server\share') are removed - and forward slashes ('\') are converted to back slashes ('/'). - Names are made relative by trimming leading slashes which is compatible - with the ZIP naming convention. - - The name to clean - The 'cleaned' name. - - The Zip name transform class is more flexible. - - - - - Get a value indicating wether the entry has a CRC value available. - - - - - Get/Set flag indicating if entry is encrypted. - A simple helper routine to aid interpretation of flags - - This is an assistant that interprets the flags property. - - - - Get / set a flag indicating wether entry name and comment text are - encoded in unicode UTF8. - - This is an assistant that interprets the flags property. - - - - Value used during password checking for PKZIP 2.0 / 'classic' encryption. - - - - - Get/Set general purpose bit flag for entry - - - General purpose bit flag
-
- Bit 0: If set, indicates the file is encrypted
- Bit 1-2 Only used for compression type 6 Imploding, and 8, 9 deflating
- Imploding:
- Bit 1 if set indicates an 8K sliding dictionary was used. If clear a 4k dictionary was used
- Bit 2 if set indicates 3 Shannon-Fanno trees were used to encode the sliding dictionary, 2 otherwise
-
- Deflating:
- Bit 2 Bit 1
- 0 0 Normal compression was used
- 0 1 Maximum compression was used
- 1 0 Fast compression was used
- 1 1 Super fast compression was used
-
- Bit 3: If set, the fields crc-32, compressed size - and uncompressed size are were not able to be written during zip file creation - The correct values are held in a data descriptor immediately following the compressed data.
- Bit 4: Reserved for use by PKZIP for enhanced deflating
- Bit 5: If set indicates the file contains compressed patch data
- Bit 6: If set indicates strong encryption was used.
- Bit 7-10: Unused or reserved
- Bit 11: If set the name and comments for this entry are in unicode.
- Bit 12-15: Unused or reserved
-
- - -
- - - Get/Set index of this entry in Zip file - - This is only valid when the entry is part of a - - - - Get/set offset for use in central header - - - - - Get/Set external file attributes as an integer. - The values of this are operating system dependant see - HostSystem for details - - - - - Get the version made by for this entry or zero if unknown. - The value / 10 indicates the major version number, and - the value mod 10 is the minor version number - - - - - Get a value indicating this entry is for a DOS/Windows system. - - - - - Gets the compatability information for the external file attribute - If the external file attributes are compatible with MS-DOS and can be read - by PKZIP for DOS version 2.04g then this value will be zero. Otherwise the value - will be non-zero and identify the host system on which the attributes are compatible. - - - - The values for this as defined in the Zip File format and by others are shown below. The values are somewhat - misleading in some cases as they are not all used as shown. You should consult the relevant documentation - to obtain up to date and correct information. The modified appnote by the infozip group is - particularly helpful as it documents a lot of peculiarities. The document is however a little dated. - - 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) - 1 - Amiga - 2 - OpenVMS - 3 - Unix - 4 - VM/CMS - 5 - Atari ST - 6 - OS/2 HPFS - 7 - Macintosh - 8 - Z-System - 9 - CP/M - 10 - Windows NTFS - 11 - MVS (OS/390 - Z/OS) - 12 - VSE - 13 - Acorn Risc - 14 - VFAT - 15 - Alternate MVS - 16 - BeOS - 17 - Tandem - 18 - OS/400 - 19 - OS/X (Darwin) - 99 - WinZip AES - remainder - unused - - - - - - Get minimum Zip feature version required to extract this entry - - - Minimum features are defined as:
- 1.0 - Default value
- 1.1 - File is a volume label
- 2.0 - File is a folder/directory
- 2.0 - File is compressed using Deflate compression
- 2.0 - File is encrypted using traditional encryption
- 2.1 - File is compressed using Deflate64
- 2.5 - File is compressed using PKWARE DCL Implode
- 2.7 - File is a patch data set
- 4.5 - File uses Zip64 format extensions
- 4.6 - File is compressed using BZIP2 compression
- 5.0 - File is encrypted using DES
- 5.0 - File is encrypted using 3DES
- 5.0 - File is encrypted using original RC2 encryption
- 5.0 - File is encrypted using RC4 encryption
- 5.1 - File is encrypted using AES encryption
- 5.1 - File is encrypted using corrected RC2 encryption
- 5.1 - File is encrypted using corrected RC2-64 encryption
- 6.1 - File is encrypted using non-OAEP key wrapping
- 6.2 - Central directory encryption (not confirmed yet)
- 6.3 - File is compressed using LZMA
- 6.3 - File is compressed using PPMD+
- 6.3 - File is encrypted using Blowfish
- 6.3 - File is encrypted using Twofish
-
- -
- - - Get a value indicating wether this entry can be decompressed by the library. - - This is based on the and - wether the compression method is supported. - - - - Gets a value indicating if the entry requires Zip64 extensions - to store the full entry values. - - A value of true if a local header requires Zip64 extensions; false if not. - - - - Get a value indicating wether the central directory entry requires Zip64 extensions to be stored. - - - - - Get/Set DosTime value. - - - The MS-DOS date format can only represent dates between 1/1/1980 and 12/31/2107. - - - - - Gets/Sets the time of last modification of the entry. - - - The property is updated to match this as far as possible. - - - - - Returns the entry name. - - - The unix naming convention is followed. - Path components in the entry should always separated by forward slashes ('/'). - Dos device names like C: should also be removed. - See the class, or - - - - - Gets/Sets the size of the uncompressed data. - - - The size or -1 if unknown. - - Setting the size before adding an entry to an archive can help - avoid compatability problems with some archivers which dont understand Zip64 extensions. - - - - Gets/Sets the size of the compressed data. - - - The compressed entry size or -1 if unknown. - - - - - Gets/Sets the crc of the uncompressed data. - - - Crc is not in the range 0..0xffffffffL - - - The crc value or -1 if unknown. - - - - - Gets/Sets the compression method. Only Deflated and Stored are supported. - - - The compression method for this entry - - - - - - - Gets/Sets the extra data. - - - Extra data is longer than 64KB (0xffff) bytes. - - - Extra data or null if not set. - - - - - Gets/Sets the entry comment. - - - If comment is longer than 0xffff. - - - The comment or null if not set. - - - A comment is only available for entries when read via the class. - The class doesnt have the comment data available. - - - - - Gets a value indicating if the entry is a directory. - however. - - - A directory is determined by an entry name with a trailing slash '/'. - The external file attributes can also indicate an entry is for a directory. - Currently only dos/windows attributes are tested in this manner. - The trailing slash convention should always be followed. - - - - - Get a value of true if the entry appears to be a file; false otherwise - - - This only takes account of DOS/Windows attributes. Other operating systems are ignored. - For linux and others the result may be incorrect. - - - - - ExtraData tagged value interface. - - - - - Set the contents of this instance from the data passed. - - The data to extract contents from. - The offset to begin extracting data from. - The number of bytes to extract. - - - - Get the data representing this instance. - - Returns the data for this instance. - - - - Get the ID for this tagged data value. - - - - - A raw binary tagged value - - - - - Initialise a new instance. - - The tag ID. - - - - Set the data from the raw values provided. - - The raw data to extract values from. - The index to start extracting values from. - The number of bytes available. - - - - Get the binary data representing this instance. - - The raw binary data representing this instance. - - - - The tag ID for this instance. - - - - - Get the ID for this tagged data value. - - - - - Get /set the binary data representing this instance. - - The raw binary data representing this instance. - - - - Class representing extended unix date time values. - - - - - Set the data from the raw values provided. - - The raw data to extract values from. - The index to start extracting values from. - The number of bytes available. - - - - Get the binary data representing this instance. - - The raw binary data representing this instance. - - - - Test a value to see if is valid and can be represented here. - - The value to test. - Returns true if the value is valid and can be represented; false if not. - The standard Unix time is a signed integer data type, directly encoding the Unix time number, - which is the number of seconds since 1970-01-01. - Being 32 bits means the values here cover a range of about 136 years. - The minimum representable time is 1901-12-13 20:45:52, - and the maximum representable time is 2038-01-19 03:14:07. - - - - - Get the ID - - - - - Get /set the Modification Time - - - - - - - Get / set the Access Time - - - - - - - Get / Set the Create Time - - - - - - - Get/set the values to include. - - - - - Flags indicate which values are included in this instance. - - - - - The modification time is included - - - - - The access time is included - - - - - The create time is included. - - - - - Class handling NT date time values. - - - - - Set the data from the raw values provided. - - The raw data to extract values from. - The index to start extracting values from. - The number of bytes available. - - - - Get the binary data representing this instance. - - The raw binary data representing this instance. - - - - Test a valuie to see if is valid and can be represented here. - - The value to test. - Returns true if the value is valid and can be represented; false if not. - - NTFS filetimes are 64-bit unsigned integers, stored in Intel - (least significant byte first) byte order. They determine the - number of 1.0E-07 seconds (1/10th microseconds!) past WinNT "epoch", - which is "01-Jan-1601 00:00:00 UTC". 28 May 60056 is the upper limit - - - - - Get the ID for this tagged data value. - - - - - Get/set the last modification time. - - - - - Get /set the create time - - - - - Get /set the last access time. - - - - - A factory that creates tagged data instances. - - - - - Get data for a specific tag value. - - The tag ID to find. - The data to search. - The offset to begin extracting data from. - The number of bytes to extract. - The located value found, or null if not found. - - - - - A class to handle the extra data field for Zip entries - - - Extra data contains 0 or more values each prefixed by a header tag and length. - They contain zero or more bytes of actual data. - The data is held internally using a copy on write strategy. This is more efficient but - means that for extra data created by passing in data can have the values modified by the caller - in some circumstances. - - - - - Initialise a default instance. - - - - - Initialise with known extra data. - - The extra data. - - - - Get the raw extra data value - - Returns the raw byte[] extra data this instance represents. - - - - Clear the stored data. - - - - - Get a read-only for the associated tag. - - The tag to locate data for. - Returns a containing tag data or null if no tag was found. - - - - Get the tagged data for a tag. - - The tag to search for. - Returns a tagged value or null if none found. - - - - Find an extra data value - - The identifier for the value to find. - Returns true if the value was found; false otherwise. - - - - Add a new entry to extra data. - - The value to add. - - - - Add a new entry to extra data - - The ID for this entry. - The data to add. - If the ID already exists its contents are replaced. - - - - Start adding a new entry. - - Add data using , , , or . - The new entry is completed and actually added by calling - - - - - Add entry data added since using the ID passed. - - The identifier to use for this entry. - - - - Add a byte of data to the pending new entry. - - The byte to add. - - - - - Add data to a pending new entry. - - The data to add. - - - - - Add a short value in little endian order to the pending new entry. - - The data to add. - - - - - Add an integer value in little endian order to the pending new entry. - - The data to add. - - - - - Add a long value in little endian order to the pending new entry. - - The data to add. - - - - - Delete an extra data field. - - The identifier of the field to delete. - Returns true if the field was found and deleted. - - - - Read a long in little endian form from the last found data value - - Returns the long value read. - - - - Read an integer in little endian form from the last found data value. - - Returns the integer read. - - - - Read a short value in little endian form from the last found data value. - - Returns the short value read. - - - - Read a byte from an extra data - - The byte value read or -1 if the end of data has been reached. - - - - Skip data during reading. - - The number of bytes to skip. - - - - Internal form of that reads data at any location. - - Returns the short value read. - - - - Dispose of this instance. - - - - - Gets the current extra data length. - - - - - Get the length of the last value found by - - This is only value if has previsouly returned true. - - - - Get the index for the current read value. - - This is only valid if has previously returned true. - Initially it will be the index of the first byte of actual data. The value is updated after calls to - , and . - - - - Get the number of bytes remaining to be read for the current value; - - - - - Holds data pertinent to a data descriptor. - - - - - Get /set the compressed size of data. - - - - - Get / set the uncompressed size of data - - - - - Get /set the crc value. - - - - - This class assists with writing/reading from Zip files. - - - - - Initialise an instance of this class. - - The name of the file to open. - - - - Initialise a new instance of . - - The stream to use. - - - - Close the stream. - - - The underlying stream is closed only if is true. - - - - - Locates a block with the desired . - - The signature to find. - Location, marking the end of block. - Minimum size of the block. - The maximum variable data. - Eeturns the offset of the first byte after the signature; -1 if not found - - - - Write Zip64 end of central directory records (File header and locator). - - The number of entries in the central directory. - The size of entries in the central directory. - The offset of the dentral directory. - - - - Write the required records to end the central directory. - - The number of entries in the directory. - The size of the entries in the directory. - The start of the central directory. - The archive comment. (This can be null). - - - - Read an unsigned short in little endian byte order. - - Returns the value read. - - An i/o error occurs. - - - The file ends prematurely - - - - - Read an int in little endian byte order. - - Returns the value read. - - An i/o error occurs. - - - The file ends prematurely - - - - - Read a long in little endian byte order. - - The value read. - - - - Write an unsigned short in little endian byte order. - - The value to write. - - - - Write a ushort in little endian byte order. - - The value to write. - - - - Write an int in little endian byte order. - - The value to write. - - - - Write a uint in little endian byte order. - - The value to write. - - - - Write a long in little endian byte order. - - The value to write. - - - - Write a ulong in little endian byte order. - - The value to write. - - - - Write a data descriptor. - - The entry to write a descriptor for. - Returns the number of descriptor bytes written. - - - - Read data descriptor at the end of compressed data. - - if set to true [zip64]. - The data to fill in. - Returns the number of bytes read in the descriptor. - - - - Get / set a value indicating wether the the underlying stream is owned or not. - - If the stream is owned it is closed when this instance is closed. - - - - Inflater is used to decompress data that has been compressed according - to the "deflate" standard described in rfc1951. - - By default Zlib (rfc1950) headers and footers are expected in the input. - You can use constructor public Inflater(bool noHeader) passing true - if there is no Zlib header information - - The usage is as following. First you have to set some input with - SetInput(), then Inflate() it. If inflate doesn't - inflate any bytes there may be three reasons: -
    -
  • IsNeedingInput() returns true because the input buffer is empty. - You have to provide more input with SetInput(). - NOTE: IsNeedingInput() also returns true when, the stream is finished. -
  • -
  • IsNeedingDictionary() returns true, you have to provide a preset - dictionary with SetDictionary().
  • -
  • IsFinished returns true, the inflater has finished.
  • -
- Once the first output byte is produced, a dictionary will not be - needed at a later stage. - - author of the original java version : John Leuner, Jochen Hoenicke -
-
- - - These are the possible states for an inflater - - - - - Copy lengths for literal codes 257..285 - - - - - Extra bits for literal codes 257..285 - - - - - Copy offsets for distance codes 0..29 - - - - - Extra bits for distance codes - - - - - This variable contains the current state. - - - - - The adler checksum of the dictionary or of the decompressed - stream, as it is written in the header resp. footer of the - compressed stream. - Only valid if mode is DECODE_DICT or DECODE_CHKSUM. - - - - - The number of bits needed to complete the current state. This - is valid, if mode is DECODE_DICT, DECODE_CHKSUM, - DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS. - - - - - True, if the last block flag was set in the last block of the - inflated stream. This means that the stream ends after the - current block. - - - - - The total number of inflated bytes. - - - - - The total number of bytes set with setInput(). This is not the - value returned by the TotalIn property, since this also includes the - unprocessed input. - - - - - This variable stores the noHeader flag that was given to the constructor. - True means, that the inflated stream doesn't contain a Zlib header or - footer. - - - - - Creates a new inflater or RFC1951 decompressor - RFC1950/Zlib headers and footers will be expected in the input data - - - - - Creates a new inflater. - - - True if no RFC1950/Zlib header and footer fields are expected in the input data - - This is used for GZIPed/Zipped input. - - For compatibility with - Sun JDK you should provide one byte of input more than needed in - this case. - - - - - Resets the inflater so that a new stream can be decompressed. All - pending input and output will be discarded. - - - - - Decodes a zlib/RFC1950 header. - - - False if more input is needed. - - - The header is invalid. - - - - - Decodes the dictionary checksum after the deflate header. - - - False if more input is needed. - - - - - Decodes the huffman encoded symbols in the input stream. - - - false if more input is needed, true if output window is - full or the current block ends. - - - if deflated stream is invalid. - - - - - Decodes the adler checksum after the deflate stream. - - - false if more input is needed. - - - If checksum doesn't match. - - - - - Decodes the deflated stream. - - - false if more input is needed, or if finished. - - - if deflated stream is invalid. - - - - - Sets the preset dictionary. This should only be called, if - needsDictionary() returns true and it should set the same - dictionary, that was used for deflating. The getAdler() - function returns the checksum of the dictionary needed. - - - The dictionary. - - - - - Sets the preset dictionary. This should only be called, if - needsDictionary() returns true and it should set the same - dictionary, that was used for deflating. The getAdler() - function returns the checksum of the dictionary needed. - - - The dictionary. - - - The index into buffer where the dictionary starts. - - - The number of bytes in the dictionary. - - - No dictionary is needed. - - - The adler checksum for the buffer is invalid - - - - - Sets the input. This should only be called, if needsInput() - returns true. - - - the input. - - - - - Sets the input. This should only be called, if needsInput() - returns true. - - - The source of input data - - - The index into buffer where the input starts. - - - The number of bytes of input to use. - - - No input is needed. - - - The index and/or count are wrong. - - - - - Inflates the compressed stream to the output buffer. If this - returns 0, you should check, whether IsNeedingDictionary(), - IsNeedingInput() or IsFinished() returns true, to determine why no - further output is produced. - - - the output buffer. - - - The number of bytes written to the buffer, 0 if no further - output can be produced. - - - if buffer has length 0. - - - if deflated stream is invalid. - - - - - Inflates the compressed stream to the output buffer. If this - returns 0, you should check, whether needsDictionary(), - needsInput() or finished() returns true, to determine why no - further output is produced. - - - the output buffer. - - - the offset in buffer where storing starts. - - - the maximum number of bytes to output. - - - the number of bytes written to the buffer, 0 if no further output can be produced. - - - if count is less than 0. - - - if the index and / or count are wrong. - - - if deflated stream is invalid. - - - - - Returns true, if the input buffer is empty. - You should then call setInput(). - NOTE: This method also returns true when the stream is finished. - - - - - Returns true, if a preset dictionary is needed to inflate the input. - - - - - Returns true, if the inflater has finished. This means, that no - input is needed and no output can be produced. - - - - - Gets the adler checksum. This is either the checksum of all - uncompressed bytes returned by inflate(), or if needsDictionary() - returns true (and thus no output was yet produced) this is the - adler checksum of the expected dictionary. - - - the adler checksum. - - - - - Gets the total number of output bytes returned by Inflate(). - - - the total number of output bytes. - - - - - Gets the total number of processed compressed input bytes. - - - The total number of bytes of processed input bytes. - - - - - Gets the number of unprocessed input bytes. Useful, if the end of the - stream is reached and you want to further process the bytes after - the deflate stream. - - - The number of bytes of the input which have not been processed. - - - - - An input stream that decompresses files in the BZip2 format - - - - - Construct instance for reading from stream - - Data source - - - - Flushes the stream. - - - - - Set the streams position. This operation is not supported and will throw a NotSupportedException - - A byte offset relative to the parameter. - A value of type indicating the reference point used to obtain the new position. - The new position of the stream. - Any access - - - - Sets the length of this stream to the given value. - This operation is not supported and will throw a NotSupportedExceptionortedException - - The new length for the stream. - Any access - - - - Writes a block of bytes to this stream using data from a buffer. - This operation is not supported and will throw a NotSupportedException - - The buffer to source data from. - The offset to start obtaining data from. - The number of bytes of data to write. - Any access - - - - Writes a byte to the current position in the file stream. - This operation is not supported and will throw a NotSupportedException - - The value to write. - Any access - - - - Read a sequence of bytes and advances the read position by one byte. - - Array of bytes to store values in - Offset in array to begin storing data - The maximum number of bytes to read - The total number of bytes read into the buffer. This might be less - than the number of bytes requested if that number of bytes are not - currently available or zero if the end of the stream is reached. - - - - - Closes the stream, releasing any associated resources. - - - - - Read a byte from stream advancing position - - byte read or -1 on end of stream - - - - Get/set flag indicating ownership of underlying stream. - When the flag is true will close the underlying stream also. - - - - - Gets a value indicating if the stream supports reading - - - - - Gets a value indicating whether the current stream supports seeking. - - - - - Gets a value indicating whether the current stream supports writing. - This property always returns false - - - - - Gets the length in bytes of the stream. - - - - - Gets or sets the streams position. - Setting the position is not supported and will throw a NotSupportException - - Any attempt to set the position - - - - Computes Adler32 checksum for a stream of data. An Adler32 - checksum is not as reliable as a CRC32 checksum, but a lot faster to - compute. - - The specification for Adler32 may be found in RFC 1950. - ZLIB Compressed Data Format Specification version 3.3) - - - From that document: - - "ADLER32 (Adler-32 checksum) - This contains a checksum value of the uncompressed data - (excluding any dictionary data) computed according to Adler-32 - algorithm. This algorithm is a 32-bit extension and improvement - of the Fletcher algorithm, used in the ITU-T X.224 / ISO 8073 - standard. - - Adler-32 is composed of two sums accumulated per byte: s1 is - the sum of all bytes, s2 is the sum of all s1 values. Both sums - are done modulo 65521. s1 is initialized to 1, s2 to zero. The - Adler-32 checksum is stored as s2*65536 + s1 in most- - significant-byte first (network) order." - - "8.2. The Adler-32 algorithm - - The Adler-32 algorithm is much faster than the CRC32 algorithm yet - still provides an extremely low probability of undetected errors. - - The modulo on unsigned long accumulators can be delayed for 5552 - bytes, so the modulo operation time is negligible. If the bytes - are a, b, c, the second sum is 3a + 2b + c + 3, and so is position - and order sensitive, unlike the first sum, which is just a - checksum. That 65521 is prime is important to avoid a possible - large class of two-byte errors that leave the check unchanged. - (The Fletcher checksum uses 255, which is not prime and which also - makes the Fletcher check insensitive to single byte changes 0 - - 255.) - - The sum s1 is initialized to 1 instead of zero to make the length - of the sequence part of s2, so that the length does not have to be - checked separately. (Any sequence of zeroes has a Fletcher - checksum of zero.)" - - - - - - - largest prime smaller than 65536 - - - - - Creates a new instance of the Adler32 class. - The checksum starts off with a value of 1. - - - - - Resets the Adler32 checksum to the initial value. - - - - - Updates the checksum with a byte value. - - - The data value to add. The high byte of the int is ignored. - - - - - Updates the checksum with an array of bytes. - - - The source of the data to update with. - - - - - Updates the checksum with the bytes taken from the array. - - - an array of bytes - - - the start of the data used for this update - - - the number of bytes to use for this update - - - - - Returns the Adler32 data checksum computed so far. - - -
-
diff --git a/bin/hdfsdll.dll.config b/bin/hdfsdll.dll.config deleted file mode 100644 index f1805fd..0000000 --- a/bin/hdfsdll.dll.config +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/bin/hdfsdll.so b/bin/hdfsdll.so deleted file mode 100755 index cf79ffc..0000000 Binary files a/bin/hdfsdll.so and /dev/null differ diff --git a/bin/xmrhelpers.so b/bin/xmrhelpers.so deleted file mode 100755 index 6074da2..0000000 Binary files a/bin/xmrhelpers.so and /dev/null differ -- cgit v1.1 From cabbd187e7945329c2f0700180f400b11096d33c Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 11:13:05 -0700 Subject: Fix the distance from which autopilot is negated when sitting on an unscripted prim - and also add some more Velocity code to ensure it gets set to zero in all cases --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 882f4a7..56e7e93 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2007,13 +2007,14 @@ namespace OpenSim.Region.Framework.Scenes if (autopilot) { // its not a scripted sit // if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) - if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) ) + if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 10.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 10.0f) ) { autopilot = false; // close enough m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup. Not using the part's position because returning the AV to the last known standing position is likely to be more friendly, isn't it? */ RemoveFromPhysicalScene(); + Velocity = Vector3.Zero; AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target } // else the autopilot will get us close } @@ -2023,6 +2024,7 @@ namespace OpenSim.Region.Framework.Scenes I *am* using the part's position this time because we have no real idea how far away the avatar is from the sit target. */ RemoveFromPhysicalScene(); + Velocity = Vector3.Zero; } } else return; // physactor is null! -- cgit v1.1 From 7bac069976b31ecb39c2d667b51aaa555f8207e3 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 7 Aug 2010 22:10:46 +0200 Subject: Mantis #229. Fix Global sim ccordinates --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a711ebf..9c630ef 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9145,8 +9145,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return UUID.Zero.ToString(); } reply = new LSL_Vector( - info.RegionLocX / Constants.RegionSize, - info.RegionLocY / Constants.RegionSize, + info.RegionLocX; + info.RegionLocY; 0).ToString(); break; case 6: // DATA_SIM_STATUS -- cgit v1.1 From 478d83539244157992b1849648e5e4cf758543e0 Mon Sep 17 00:00:00 2001 From: sacha Date: Sat, 7 Aug 2010 21:04:16 +0000 Subject: removing more stains ... --- OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index a9ecde8..59e4037 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -168,7 +168,7 @@ namespace OpenSim.Region.Framework.Scenes if (neighbour != null) { - m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); + // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); m_scene.EventManager.TriggerOnRegionUp(neighbour); } else @@ -183,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); List neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); - m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); + //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); foreach (GridRegion n in neighbours) { InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; @@ -267,7 +267,7 @@ namespace OpenSim.Region.Framework.Scenes protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) { - m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); + //m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); // let's do our best, but there's not much we can do if the neighbour doesn't accept. //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); -- cgit v1.1 From 68e4b1115a5545a40e7a410855e39724d45b958c Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 7 Aug 2010 22:23:51 +0100 Subject: Dumb error in fix --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 9c630ef..68b645e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9145,8 +9145,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return UUID.Zero.ToString(); } reply = new LSL_Vector( - info.RegionLocX; - info.RegionLocY; + info.RegionLocX, + info.RegionLocY, 0).ToString(); break; case 6: // DATA_SIM_STATUS -- cgit v1.1 From 4c5788c4c0975dbf3af58e2184a90965fcf0e893 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 7 Aug 2010 22:24:17 +0100 Subject: Add search URL to Login Service --- OpenSim/Services/LLLoginService/LLLoginResponse.cs | 18 +++++++++++++++++- OpenSim/Services/LLLoginService/LLLoginService.cs | 4 +++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index 240f5b1..c1da463 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -178,6 +178,8 @@ namespace OpenSim.Services.LLLoginService // Web map private string mapTileURL; + private string searchURL; + // Error Flags private string errorReason; private string errorMessage; @@ -226,7 +228,7 @@ namespace OpenSim.Services.LLLoginService public LLLoginResponse(UserAccount account, AgentCircuitData aCircuit, GridUserInfo pinfo, GridRegion destination, List invSkel, FriendInfo[] friendsList, ILibraryService libService, string where, string startlocation, Vector3 position, Vector3 lookAt, List gestures, string message, - GridRegion home, IPEndPoint clientIP, string mapTileURL) + GridRegion home, IPEndPoint clientIP, string mapTileURL, string searchURL) : this() { FillOutInventoryData(invSkel, libService); @@ -243,6 +245,7 @@ namespace OpenSim.Services.LLLoginService BuddList = ConvertFriendListItem(friendsList); StartLocation = where; MapTileURL = mapTileURL; + SearchURL = searchURL; FillOutHomeData(pinfo, home); LookAt = String.Format("[r{0},r{1},r{2}]", lookAt.X, lookAt.Y, lookAt.Z); @@ -416,6 +419,7 @@ namespace OpenSim.Services.LLLoginService InitialOutfitHash["gender"] = "female"; initialOutfit.Add(InitialOutfitHash); mapTileURL = String.Empty; + searchURL = String.Empty; } @@ -479,6 +483,9 @@ namespace OpenSim.Services.LLLoginService responseData["region_x"] = (Int32)(RegionX); responseData["region_y"] = (Int32)(RegionY); + if (searchURL != String.Empty) + responseData["search"] = searchURL; + if (mapTileURL != String.Empty) responseData["map-server-url"] = mapTileURL; @@ -581,6 +588,9 @@ namespace OpenSim.Services.LLLoginService if (mapTileURL != String.Empty) map["map-server-url"] = OSD.FromString(mapTileURL); + if (searchURL != String.Empty) + map["search"] = OSD.FromString(searchURL); + if (m_buddyList != null) { map["buddy-list"] = ArrayListToOSDArray(m_buddyList.ToArray()); @@ -938,6 +948,12 @@ namespace OpenSim.Services.LLLoginService set { mapTileURL = value; } } + public string SearchURL + { + get { return searchURL; } + set { searchURL = value; } + } + public string Message { get { return welcomeMessage; } diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 9446126..f9fe7f0 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -74,6 +74,7 @@ namespace OpenSim.Services.LLLoginService protected string m_GatekeeperURL; protected bool m_AllowRemoteSetLoginLevel; protected string m_MapTileURL; + protected string m_SearchURL; IConfig m_LoginServerConfig; @@ -102,6 +103,7 @@ namespace OpenSim.Services.LLLoginService m_MinLoginLevel = m_LoginServerConfig.GetInt("MinLoginLevel", 0); m_GatekeeperURL = m_LoginServerConfig.GetString("GatekeeperURI", string.Empty); m_MapTileURL = m_LoginServerConfig.GetString("MapTileURL", string.Empty); + m_SearchURL = m_LoginServerConfig.GetString("SearchURL", string.Empty); // These are required; the others aren't if (accountService == string.Empty || authService == string.Empty) @@ -364,7 +366,7 @@ namespace OpenSim.Services.LLLoginService // Finally, fill out the response and return it // LLLoginResponse response = new LLLoginResponse(account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService, - where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP, m_MapTileURL); + where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP, m_MapTileURL, m_SearchURL); m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to client."); return response; -- cgit v1.1 From a6048518b7afb27cb523c0074d38c849ea0b6884 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 16:18:44 -0700 Subject: Repair lsGetWindlightScene, the constant was added to the list as a uint, which is bad - convert to LSL_Integer first. --- .../Shared/Api/Implementation/LS_Api.cs | 1014 ++++++++++---------- 1 file changed, 507 insertions(+), 507 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index fffe65c..f0384f8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -1,507 +1,507 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.Remoting.Lifetime; -using OpenMetaverse; -using Nini.Config; -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.World.LightShare; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Region.ScriptEngine.Interfaces; -using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; - -using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; -using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; -using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; - -namespace OpenSim.Region.ScriptEngine.Shared.Api -{ - [Serializable] - public class LS_Api : MarshalByRefObject, ILS_Api, IScriptApi - { - internal IScriptEngine m_ScriptEngine; - internal SceneObjectPart m_host; - internal uint m_localID; - internal UUID m_itemID; - internal bool m_LSFunctionsEnabled = false; - internal IScriptModuleComms m_comms = null; - - public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) - { - m_ScriptEngine = ScriptEngine; - m_host = host; - m_localID = localID; - m_itemID = itemID; - - if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) - m_LSFunctionsEnabled = true; - - if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false)) - m_LSFunctionsEnabled = true; - - m_comms = m_ScriptEngine.World.RequestModuleInterface(); - if (m_comms == null) - m_LSFunctionsEnabled = false; - } - - public override Object InitializeLifetimeService() - { - ILease lease = (ILease)base.InitializeLifetimeService(); - - if (lease.CurrentState == LeaseState.Initial) - { - lease.InitialLeaseTime = TimeSpan.FromMinutes(0); - // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); - // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); - } - return lease; - } - - public Scene World - { - get { return m_ScriptEngine.World; } - } - - // - //Dumps an error message on the debug console. - // - - internal void LSShoutError(string message) - { - if (message.Length > 1023) - message = message.Substring(0, 1023); - - World.SimChat(Utils.StringToBytes(message), - ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); - - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); - } - - /// - /// Get the current Windlight scene - /// - /// List of windlight parameters - public LSL_List lsGetWindlightScene(LSL_List rules) - { - if (!m_LSFunctionsEnabled) - { - LSShoutError("LightShare functions are not enabled."); - return new LSL_List(); - } - m_host.AddScriptLPS(1); - RegionLightShareData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; - - LSL_List values = new LSL_List(); - int idx = 0; - while (idx < rules.Length) - { - uint rule = (uint)rules.GetLSLIntegerItem(idx); - LSL_List toadd = new LSL_List(); - - switch (rule) - { - case (int)ScriptBaseClass.WL_AMBIENT: - toadd.Add(new LSL_Rotation(wl.ambient.X, wl.ambient.Y, wl.ambient.Z, wl.ambient.W)); - break; - case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: - toadd.Add(new LSL_Vector(wl.bigWaveDirection.X, wl.bigWaveDirection.Y, 0.0f)); - break; - case (int)ScriptBaseClass.WL_BLUE_DENSITY: - toadd.Add(new LSL_Rotation(wl.blueDensity.X, wl.blueDensity.Y, wl.blueDensity.Z, wl.blueDensity.W)); - break; - case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: - toadd.Add(new LSL_Float(wl.blurMultiplier)); - break; - case (int)ScriptBaseClass.WL_CLOUD_COLOR: - toadd.Add(new LSL_Rotation(wl.cloudColor.X, wl.cloudColor.Y, wl.cloudColor.Z, wl.cloudColor.W)); - break; - case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: - toadd.Add(new LSL_Float(wl.cloudCoverage)); - break; - case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: - toadd.Add(new LSL_Vector(wl.cloudDetailXYDensity.X, wl.cloudDetailXYDensity.Y, wl.cloudDetailXYDensity.Z)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCALE: - toadd.Add(new LSL_Float(wl.cloudScale)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: - toadd.Add(new LSL_Float(wl.cloudScrollX)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: - toadd.Add(new LSL_Integer(wl.cloudScrollXLock ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: - toadd.Add(new LSL_Float(wl.cloudScrollY)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: - toadd.Add(new LSL_Integer(wl.cloudScrollYLock ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: - toadd.Add(new LSL_Vector(wl.cloudXYDensity.X, wl.cloudXYDensity.Y, wl.cloudXYDensity.Z)); - break; - case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: - toadd.Add(new LSL_Float(wl.densityMultiplier)); - break; - case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: - toadd.Add(new LSL_Float(wl.distanceMultiplier)); - break; - case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: - toadd.Add(new LSL_Integer(wl.drawClassicClouds ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_EAST_ANGLE: - toadd.Add(new LSL_Float(wl.eastAngle)); - break; - case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: - toadd.Add(new LSL_Float(wl.fresnelOffset)); - break; - case (int)ScriptBaseClass.WL_FRESNEL_SCALE: - toadd.Add(new LSL_Float(wl.fresnelScale)); - break; - case (int)ScriptBaseClass.WL_HAZE_DENSITY: - toadd.Add(new LSL_Float(wl.hazeDensity)); - break; - case (int)ScriptBaseClass.WL_HAZE_HORIZON: - toadd.Add(new LSL_Float(wl.hazeHorizon)); - break; - case (int)ScriptBaseClass.WL_HORIZON: - toadd.Add(new LSL_Rotation(wl.horizon.X, wl.horizon.Y, wl.horizon.Z, wl.horizon.W)); - break; - case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: - toadd.Add(new LSL_Vector(wl.littleWaveDirection.X, wl.littleWaveDirection.Y, 0.0f)); - break; - case (int)ScriptBaseClass.WL_MAX_ALTITUDE: - toadd.Add(new LSL_Integer(wl.maxAltitude)); - break; - case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: - toadd.Add(new LSL_Key(wl.normalMapTexture.ToString())); - break; - case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: - toadd.Add(new LSL_Vector(wl.reflectionWaveletScale.X, wl.reflectionWaveletScale.Y, wl.reflectionWaveletScale.Z)); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: - toadd.Add(new LSL_Float(wl.refractScaleAbove)); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: - toadd.Add(new LSL_Float(wl.refractScaleBelow)); - break; - case (int)ScriptBaseClass.WL_SCENE_GAMMA: - toadd.Add(new LSL_Float(wl.sceneGamma)); - break; - case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: - toadd.Add(new LSL_Float(wl.starBrightness)); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: - toadd.Add(new LSL_Float(wl.sunGlowFocus)); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: - toadd.Add(new LSL_Float(wl.sunGlowSize)); - break; - case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: - toadd.Add(new LSL_Rotation(wl.sunMoonColor.X, wl.sunMoonColor.Y, wl.sunMoonColor.Z, wl.sunMoonColor.W)); - break; - case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: - toadd.Add(new LSL_Float(wl.underwaterFogModifier)); - break; - case (int)ScriptBaseClass.WL_WATER_COLOR: - toadd.Add(new LSL_Vector(wl.waterColor.X, wl.waterColor.Y, wl.waterColor.Z)); - break; - case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: - toadd.Add(new LSL_Float(wl.waterFogDensityExponent)); - break; - } - - if (toadd.Length > 0) - { - values.Add(rule); - values.Add(toadd.Data[0]); - } - idx++; - } - - - return values; - - } - - private RegionLightShareData getWindlightProfileFromRules(LSL_List rules) - { - RegionLightShareData wl = (RegionLightShareData)m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.Clone(); - - LSL_List values = new LSL_List(); - int idx = 0; - while (idx < rules.Length) - { - uint rule = (uint)rules.GetLSLIntegerItem(idx); - LSL_Types.Quaternion iQ; - LSL_Types.Vector3 iV; - switch (rule) - { - case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: - idx++; - wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_AMBIENT: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_BLUE_DENSITY: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: - idx++; - wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: - idx++; - wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCALE: - idx++; - wl.cloudScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: - idx++; - wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: - idx++; - wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: - idx++; - wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: - idx++; - wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: - idx++; - wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: - idx++; - wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: - idx++; - wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_EAST_ANGLE: - idx++; - wl.eastAngle = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: - idx++; - wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_SCALE: - idx++; - wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_DENSITY: - idx++; - wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_HORIZON: - idx++; - wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HORIZON: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_MAX_ALTITUDE: - idx++; - wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; - break; - case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: - idx++; - wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); - break; - case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: - idx++; - iV = rules.GetVector3Item(idx); - wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: - idx++; - wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: - idx++; - wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SCENE_GAMMA: - idx++; - wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: - idx++; - wl.starBrightness = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: - idx++; - wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: - idx++; - wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: - idx++; - wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_WATER_COLOR: - idx++; - iV = rules.GetVector3Item(idx); - wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: - idx++; - wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); - break; - } - idx++; - } - return wl; - } - /// - /// Set the current Windlight scene - /// - /// - /// success: true or false - public int lsSetWindlightScene(LSL_List rules) - { - if (!m_LSFunctionsEnabled) - { - LSShoutError("LightShare functions are not enabled."); - return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); - return 0; - } - int success = 0; - m_host.AddScriptLPS(1); - if (LightShareModule.EnableWindlight) - { - RegionLightShareData wl = getWindlightProfileFromRules(rules); - m_host.ParentGroup.Scene.StoreWindlightProfile(wl); - success = 1; - } - else - { - LSShoutError("Windlight module is disabled"); - return 0; - } - return success; - } - /// - /// Set the current Windlight scene to a target avatar - /// - /// - /// success: true or false - public int lsSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) - { - if (!m_LSFunctionsEnabled) - { - LSShoutError("LightShare functions are not enabled."); - return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); - return 0; - } - int success = 0; - m_host.AddScriptLPS(1); - if (LightShareModule.EnableWindlight) - { - RegionLightShareData wl = getWindlightProfileFromRules(rules); - World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); - success = 1; - } - else - { - LSShoutError("Windlight module is disabled"); - return 0; - } - return success; - } - - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Reflection; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.Remoting.Lifetime; +using OpenMetaverse; +using Nini.Config; +using OpenSim; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.World.LightShare; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.ScriptEngine.Shared; +using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; +using OpenSim.Region.ScriptEngine.Shared.ScriptBase; +using OpenSim.Region.ScriptEngine.Interfaces; +using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; + +using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; +using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; +using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; +using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; +using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; + +namespace OpenSim.Region.ScriptEngine.Shared.Api +{ + [Serializable] + public class LS_Api : MarshalByRefObject, ILS_Api, IScriptApi + { + internal IScriptEngine m_ScriptEngine; + internal SceneObjectPart m_host; + internal uint m_localID; + internal UUID m_itemID; + internal bool m_LSFunctionsEnabled = false; + internal IScriptModuleComms m_comms = null; + + public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) + { + m_ScriptEngine = ScriptEngine; + m_host = host; + m_localID = localID; + m_itemID = itemID; + + if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) + m_LSFunctionsEnabled = true; + + if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false)) + m_LSFunctionsEnabled = true; + + m_comms = m_ScriptEngine.World.RequestModuleInterface(); + if (m_comms == null) + m_LSFunctionsEnabled = false; + } + + public override Object InitializeLifetimeService() + { + ILease lease = (ILease)base.InitializeLifetimeService(); + + if (lease.CurrentState == LeaseState.Initial) + { + lease.InitialLeaseTime = TimeSpan.FromMinutes(0); + // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); + // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); + } + return lease; + } + + public Scene World + { + get { return m_ScriptEngine.World; } + } + + // + //Dumps an error message on the debug console. + // + + internal void LSShoutError(string message) + { + if (message.Length > 1023) + message = message.Substring(0, 1023); + + World.SimChat(Utils.StringToBytes(message), + ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); + + IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); + wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); + } + + /// + /// Get the current Windlight scene + /// + /// List of windlight parameters + public LSL_List lsGetWindlightScene(LSL_List rules) + { + if (!m_LSFunctionsEnabled) + { + LSShoutError("LightShare functions are not enabled."); + return new LSL_List(); + } + m_host.AddScriptLPS(1); + RegionLightShareData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; + + LSL_List values = new LSL_List(); + int idx = 0; + while (idx < rules.Length) + { + uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_List toadd = new LSL_List(); + + switch (rule) + { + case (int)ScriptBaseClass.WL_AMBIENT: + toadd.Add(new LSL_Rotation(wl.ambient.X, wl.ambient.Y, wl.ambient.Z, wl.ambient.W)); + break; + case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: + toadd.Add(new LSL_Vector(wl.bigWaveDirection.X, wl.bigWaveDirection.Y, 0.0f)); + break; + case (int)ScriptBaseClass.WL_BLUE_DENSITY: + toadd.Add(new LSL_Rotation(wl.blueDensity.X, wl.blueDensity.Y, wl.blueDensity.Z, wl.blueDensity.W)); + break; + case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: + toadd.Add(new LSL_Float(wl.blurMultiplier)); + break; + case (int)ScriptBaseClass.WL_CLOUD_COLOR: + toadd.Add(new LSL_Rotation(wl.cloudColor.X, wl.cloudColor.Y, wl.cloudColor.Z, wl.cloudColor.W)); + break; + case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: + toadd.Add(new LSL_Float(wl.cloudCoverage)); + break; + case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: + toadd.Add(new LSL_Vector(wl.cloudDetailXYDensity.X, wl.cloudDetailXYDensity.Y, wl.cloudDetailXYDensity.Z)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCALE: + toadd.Add(new LSL_Float(wl.cloudScale)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: + toadd.Add(new LSL_Float(wl.cloudScrollX)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: + toadd.Add(new LSL_Integer(wl.cloudScrollXLock ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: + toadd.Add(new LSL_Float(wl.cloudScrollY)); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: + toadd.Add(new LSL_Integer(wl.cloudScrollYLock ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: + toadd.Add(new LSL_Vector(wl.cloudXYDensity.X, wl.cloudXYDensity.Y, wl.cloudXYDensity.Z)); + break; + case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: + toadd.Add(new LSL_Float(wl.densityMultiplier)); + break; + case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: + toadd.Add(new LSL_Float(wl.distanceMultiplier)); + break; + case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: + toadd.Add(new LSL_Integer(wl.drawClassicClouds ? 1 : 0)); + break; + case (int)ScriptBaseClass.WL_EAST_ANGLE: + toadd.Add(new LSL_Float(wl.eastAngle)); + break; + case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: + toadd.Add(new LSL_Float(wl.fresnelOffset)); + break; + case (int)ScriptBaseClass.WL_FRESNEL_SCALE: + toadd.Add(new LSL_Float(wl.fresnelScale)); + break; + case (int)ScriptBaseClass.WL_HAZE_DENSITY: + toadd.Add(new LSL_Float(wl.hazeDensity)); + break; + case (int)ScriptBaseClass.WL_HAZE_HORIZON: + toadd.Add(new LSL_Float(wl.hazeHorizon)); + break; + case (int)ScriptBaseClass.WL_HORIZON: + toadd.Add(new LSL_Rotation(wl.horizon.X, wl.horizon.Y, wl.horizon.Z, wl.horizon.W)); + break; + case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: + toadd.Add(new LSL_Vector(wl.littleWaveDirection.X, wl.littleWaveDirection.Y, 0.0f)); + break; + case (int)ScriptBaseClass.WL_MAX_ALTITUDE: + toadd.Add(new LSL_Integer(wl.maxAltitude)); + break; + case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: + toadd.Add(new LSL_Key(wl.normalMapTexture.ToString())); + break; + case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: + toadd.Add(new LSL_Vector(wl.reflectionWaveletScale.X, wl.reflectionWaveletScale.Y, wl.reflectionWaveletScale.Z)); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: + toadd.Add(new LSL_Float(wl.refractScaleAbove)); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: + toadd.Add(new LSL_Float(wl.refractScaleBelow)); + break; + case (int)ScriptBaseClass.WL_SCENE_GAMMA: + toadd.Add(new LSL_Float(wl.sceneGamma)); + break; + case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: + toadd.Add(new LSL_Float(wl.starBrightness)); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: + toadd.Add(new LSL_Float(wl.sunGlowFocus)); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: + toadd.Add(new LSL_Float(wl.sunGlowSize)); + break; + case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: + toadd.Add(new LSL_Rotation(wl.sunMoonColor.X, wl.sunMoonColor.Y, wl.sunMoonColor.Z, wl.sunMoonColor.W)); + break; + case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: + toadd.Add(new LSL_Float(wl.underwaterFogModifier)); + break; + case (int)ScriptBaseClass.WL_WATER_COLOR: + toadd.Add(new LSL_Vector(wl.waterColor.X, wl.waterColor.Y, wl.waterColor.Z)); + break; + case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: + toadd.Add(new LSL_Float(wl.waterFogDensityExponent)); + break; + } + + if (toadd.Length > 0) + { + values.Add(new LSL_Integer(rule)); + values.Add(toadd.Data[0]); + } + idx++; + } + + + return values; + + } + + private RegionLightShareData getWindlightProfileFromRules(LSL_List rules) + { + RegionLightShareData wl = (RegionLightShareData)m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.Clone(); + + LSL_List values = new LSL_List(); + int idx = 0; + while (idx < rules.Length) + { + uint rule = (uint)rules.GetLSLIntegerItem(idx); + LSL_Types.Quaternion iQ; + LSL_Types.Vector3 iV; + switch (rule) + { + case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: + idx++; + wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_AMBIENT: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_BLUE_DENSITY: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: + idx++; + wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: + idx++; + wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCALE: + idx++; + wl.cloudScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: + idx++; + wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: + idx++; + wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: + idx++; + wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: + idx++; + wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: + idx++; + iV = rules.GetVector3Item(idx); + wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: + idx++; + wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: + idx++; + wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: + idx++; + wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; + break; + case (int)ScriptBaseClass.WL_EAST_ANGLE: + idx++; + wl.eastAngle = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: + idx++; + wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_FRESNEL_SCALE: + idx++; + wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_DENSITY: + idx++; + wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HAZE_HORIZON: + idx++; + wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_HORIZON: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: + idx++; + iV = rules.GetVector3Item(idx); + wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); + break; + case (int)ScriptBaseClass.WL_MAX_ALTITUDE: + idx++; + wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; + break; + case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: + idx++; + wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); + break; + case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: + idx++; + iV = rules.GetVector3Item(idx); + wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: + idx++; + wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: + idx++; + wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SCENE_GAMMA: + idx++; + wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: + idx++; + wl.starBrightness = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: + idx++; + wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: + idx++; + wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: + idx++; + iQ = rules.GetQuaternionItem(idx); + wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); + break; + case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: + idx++; + wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); + break; + case (int)ScriptBaseClass.WL_WATER_COLOR: + idx++; + iV = rules.GetVector3Item(idx); + wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + break; + case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: + idx++; + wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); + break; + } + idx++; + } + return wl; + } + /// + /// Set the current Windlight scene + /// + /// + /// success: true or false + public int lsSetWindlightScene(LSL_List rules) + { + if (!m_LSFunctionsEnabled) + { + LSShoutError("LightShare functions are not enabled."); + return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); + return 0; + } + int success = 0; + m_host.AddScriptLPS(1); + if (LightShareModule.EnableWindlight) + { + RegionLightShareData wl = getWindlightProfileFromRules(rules); + m_host.ParentGroup.Scene.StoreWindlightProfile(wl); + success = 1; + } + else + { + LSShoutError("Windlight module is disabled"); + return 0; + } + return success; + } + /// + /// Set the current Windlight scene to a target avatar + /// + /// + /// success: true or false + public int lsSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) + { + if (!m_LSFunctionsEnabled) + { + LSShoutError("LightShare functions are not enabled."); + return 0; + } + if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) + { + LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); + return 0; + } + int success = 0; + m_host.AddScriptLPS(1); + if (LightShareModule.EnableWindlight) + { + RegionLightShareData wl = getWindlightProfileFromRules(rules); + World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); + success = 1; + } + else + { + LSShoutError("Windlight module is disabled"); + return 0; + } + return success; + } + + } +} -- cgit v1.1 From 19ab4c950880beb3ac88a172b775c3973782ec3d Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 16:52:03 -0700 Subject: Fix a rather nasty issue where the Backup() process causes objects and avatars sitting on them to be pushed to the corner of the sim. --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 199 +++++++++++---------- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 25 +-- 2 files changed, 120 insertions(+), 104 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a828127..0d15cb4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -317,8 +317,8 @@ namespace OpenSim.Region.Framework.Scenes private bool m_scriptListens_notAtTarget = false; private bool m_scriptListens_atRotTarget = false; - private bool m_scriptListens_notAtRotTarget = false; - + private bool m_scriptListens_notAtRotTarget = false; + public bool m_dupeInProgress = false; internal Dictionary m_savedScriptState = null; #region Properties @@ -475,16 +475,21 @@ namespace OpenSim.Region.Framework.Scenes { part.IgnoreUndoUpdate = false; part.StoreUndoState(UndoType.STATE_GROUP_POSITION); - part.GroupPosition = val; - part.TriggerScriptChangedEvent(Changed.POSITION); - } - - foreach (ScenePresence av in m_linkedAvatars) - { - Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; - av.AbsolutePosition += offset; - av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition - av.SendFullUpdateToAllClients(); + part.GroupPosition = val; + if (!m_dupeInProgress) + { + part.TriggerScriptChangedEvent(Changed.POSITION); + } + } + if (!m_dupeInProgress) + { + foreach (ScenePresence av in m_linkedAvatars) + { + Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; + av.AbsolutePosition += offset; + av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition + av.SendFullUpdateToAllClients(); + } } //if (m_rootPart.PhysActor != null) @@ -1800,88 +1805,96 @@ namespace OpenSim.Region.Framework.Scenes /// True if the duplicate will immediately be in the scene, false otherwise /// public SceneObjectGroup Copy(bool userExposed) - { - SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); - dupe.m_isBackedUp = false; - dupe.m_parts = new Dictionary(); - - // Warning, The following code related to previousAttachmentStatus is needed so that clones of - // attachments do not bordercross while they're being duplicated. This is hacktastic! - // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! - // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state - // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, - // then restore it's attachment state - - // This is only necessary when userExposed is false! - - bool previousAttachmentStatus = dupe.RootPart.IsAttachment; - - if (!userExposed) - dupe.RootPart.IsAttachment = true; - - dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); - - if (!userExposed) - { - dupe.RootPart.IsAttachment = previousAttachmentStatus; - } - - dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); - dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; - - if (userExposed) - dupe.m_rootPart.TrimPermissions(); - - /// may need to create a new Physics actor. - if (dupe.RootPart.PhysActor != null && userExposed) - { - PrimitiveBaseShape pbs = dupe.RootPart.Shape; - - dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( - dupe.RootPart.Name, - pbs, - dupe.RootPart.AbsolutePosition, - dupe.RootPart.Scale, - dupe.RootPart.RotationOffset, - dupe.RootPart.PhysActor.IsPhysical); - - dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; - dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); + { + SceneObjectGroup dupe; + try + { + m_dupeInProgress = true; + dupe = (SceneObjectGroup)MemberwiseClone(); + dupe.m_isBackedUp = false; + dupe.m_parts = new Dictionary(); + + // Warning, The following code related to previousAttachmentStatus is needed so that clones of + // attachments do not bordercross while they're being duplicated. This is hacktastic! + // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! + // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state + // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, + // then restore it's attachment state + + // This is only necessary when userExposed is false! + + bool previousAttachmentStatus = dupe.RootPart.IsAttachment; + + if (!userExposed) + dupe.RootPart.IsAttachment = true; + + dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); + + if (!userExposed) + { + dupe.RootPart.IsAttachment = previousAttachmentStatus; + } + + dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); + dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; + + if (userExposed) + dupe.m_rootPart.TrimPermissions(); + + /// may need to create a new Physics actor. + if (dupe.RootPart.PhysActor != null && userExposed) + { + PrimitiveBaseShape pbs = dupe.RootPart.Shape; + + dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( + dupe.RootPart.Name, + pbs, + dupe.RootPart.AbsolutePosition, + dupe.RootPart.Scale, + dupe.RootPart.RotationOffset, + dupe.RootPart.PhysActor.IsPhysical); + + dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; + dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); + } + + List partList; + + lockPartsForRead(true); + + partList = new List(m_parts.Values); + + lockPartsForRead(false); + + partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) + { + return p1.LinkNum.CompareTo(p2.LinkNum); + } + ); + + foreach (SceneObjectPart part in partList) + { + if (part.UUID != m_rootPart.UUID) + { + SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); + + newPart.LinkNum = part.LinkNum; + } + } + + if (userExposed) + { + dupe.UpdateParentIDs(); + dupe.HasGroupChanged = true; + dupe.AttachToBackup(); + + ScheduleGroupForFullUpdate(); + } + } + finally + { + m_dupeInProgress = false; } - - List partList; - - lockPartsForRead(true); - - partList = new List(m_parts.Values); - - lockPartsForRead(false); - - partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) - { - return p1.LinkNum.CompareTo(p2.LinkNum); - } - ); - - foreach (SceneObjectPart part in partList) - { - if (part.UUID != m_rootPart.UUID) - { - SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); - - newPart.LinkNum = part.LinkNum; - } - } - - if (userExposed) - { - dupe.UpdateParentIDs(); - dupe.HasGroupChanged = true; - dupe.AttachToBackup(); - - ScheduleGroupForFullUpdate(); - } - return dupe; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b0ce450..77581af 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -718,17 +718,20 @@ namespace OpenSim.Region.Framework.Scenes // Tell the physics engines that this prim changed. m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); - } - - List avs = ParentGroup.GetLinkedAvatars(); - foreach (ScenePresence av in avs) - { - if (av.LinkedPrim == m_uuid) - { - Vector3 offset = (m_offsetPosition - oldpos); - av.OffsetPosition += offset; - av.SendFullUpdateToAllClients(); - } + } + + if (!m_parentGroup.m_dupeInProgress) + { + List avs = ParentGroup.GetLinkedAvatars(); + foreach (ScenePresence av in avs) + { + if (av.LinkedPrim == m_uuid) + { + Vector3 offset = (m_offsetPosition - oldpos); + av.OffsetPosition += offset; + av.SendFullUpdateToAllClients(); + } + } } } TriggerScriptChangedEvent(Changed.POSITION); -- cgit v1.1 From 50ac61e17f4e164931dc26f01ffbe58dced9e772 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 8 Aug 2010 02:01:24 +0200 Subject: In my crusade against facelights, I am striking the killing blow. Add a DisableFacelights option to OpenSim.ini to finally kill those immersion- breaking, silly vanity lights that destroy nighttime RP. Girls, you look just fine without them. Guys, you too. Thank you. Melanie has left the building. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 16 ++++++++++++++++ OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs | 4 ++++ bin/OpenSim.ini.example | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index af2dd85..a0e5521 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -315,6 +315,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private int m_cachedTextureSerial; private PriorityQueue m_entityUpdates; private Prioritizer m_prioritizer; + private bool m_disableFacelights = false; /// /// List used in construction of data blocks for an object update packet. This is to stop us having to @@ -420,6 +421,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP set { m_IsLoggingOut = value; } } + public bool DisableFacelights + { + get { return m_disableFacelights; } + set { m_disableFacelights = value; } + } + public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } #endregion Properties @@ -3522,6 +3529,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP SceneObjectPart part = (SceneObjectPart)update.Entity; if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId)) continue; + + if (part.ParentGroup.IsAttachment && m_disableFacelights) + { + if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && + part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand) + { + part.Shape.LightEntry = false; + } + } } ++updatesThisCall; diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 3b63bcd..bbbf0be 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -153,6 +153,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP private int m_defaultRTO = 0; private int m_maxRTO = 0; + private bool m_disableFacelights = false; + public Socket Server { get { return null; } } public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) @@ -190,6 +192,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_defaultRTO = config.GetInt("DefaultRTO", 0); m_maxRTO = config.GetInt("MaxRTO", 0); + m_disableFacelights = config.GetBoolean("DisableFacelights", false); } else { @@ -907,6 +910,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP //this will prevent us from missing important messages //before the modules are bound client.DeliverPackets = false; + client.DisableFacelights = m_disableFacelights; Util.FireAndForget( delegate diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 074345d..466da93 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -390,6 +390,13 @@ ; ;TextureSendLimit = 20 + ; Quash and remove any light properties from attachments not on the + ; hands. This allows flashlights and lanterns to function, but kills + ; silly vanity "Facelights" dead. Sorry, head mounted miner's lamps + ; will also be affected. + ; + ;DisableFacelights = "false" + [Chat] ; Controls whether the chat module is enabled. Default is true. enabled = true; -- cgit v1.1 From acb1590cf063769802f35c99dd5fb6398172296f Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 17:32:36 -0700 Subject: Fix the unscripted sit rotation being incorrect (relative to the prim). Note that unscripted sit offset is still really poor but this is not something i'm prepared to spend time on fixing. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 56e7e93..5191236 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2053,9 +2053,13 @@ namespace OpenSim.Region.Framework.Scenes //Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child - ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); + Quaternion roffset = Quaternion.Identity; + if (SitTargetisSet) + { + roffset = part.RotationOffset; + } + ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * roffset) + part.OffsetPosition), sitOrientation / part.RotationOffset, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); - m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target // This calls HandleAgentSit twice, once from here, and the client calls // HandleAgentSit itself after it gets to the location // It doesn't get to the location until we've moved them there though @@ -2441,7 +2445,7 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos); } m_linkedPrim = part.UUID; - + m_offsetRotation = m_offsetRotation / part.RotationOffset; Velocity = Vector3.Zero; RemoveFromPhysicalScene(); Animator.TrySetMovementAnimation(sitAnimation); -- cgit v1.1 From b771965f287af0cb5d46e4f652e9912dfaa40682 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 17:33:27 -0700 Subject: Get rid of some debug chatter that someone who can't spell left behind. ;) --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 5191236..6f92a41 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2378,8 +2378,7 @@ namespace OpenSim.Region.Framework.Scenes m_bodyRot = sitTargetOrient; m_parentPosition = part.AbsolutePosition; part.IsOccupied = true; - part.ParentGroup.AddAvatar(agentID); -Console.WriteLine("Scripted Sit ofset {0}", m_pos); + part.ParentGroup.AddAvatar(agentID); } else { -- cgit v1.1 From aa54e8d95eb920869da5c885fc536cfb1ffca90b Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 17:35:16 -0700 Subject: Increase sit distance to 256 meters, but leave the initial autopilot process in the picture so sit position can still be raycast by the existing code. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 6f92a41..cca296e 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2007,7 +2007,7 @@ namespace OpenSim.Region.Framework.Scenes if (autopilot) { // its not a scripted sit // if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) - if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 10.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 10.0f) ) + if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) ) { autopilot = false; // close enough m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup. -- cgit v1.1 From 0794c6a941c9c98be32c05cd372ce53773a6e32f Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 20:13:45 -0700 Subject: Implement parcel group access control. This addresses mantis #158. --- .../Region/CoreModules/World/Land/LandObject.cs | 2058 ++++++++++---------- 1 file changed, 1045 insertions(+), 1013 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 6864629..fcd993c 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -1,1013 +1,1045 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.CoreModules.World.Land -{ - /// - /// Keeps track of a specific piece of land's information - /// - public class LandObject : ILandObject - { - #region Member Variables - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - #pragma warning disable 0429 - private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64; - #pragma warning restore 0429 - private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax]; - - private int m_lastSeqId = 0; - - protected LandData m_landData = new LandData(); - protected Scene m_scene; - protected List primsOverMe = new List(); - - public bool[,] LandBitmap - { - get { return m_landBitmap; } - set { m_landBitmap = value; } - } - - #endregion - - #region ILandObject Members - - public LandData LandData - { - get { return m_landData; } - - set { m_landData = value; } - } - - public UUID RegionUUID - { - get { return m_scene.RegionInfo.RegionID; } - } - - #region Constructors - - public LandObject(UUID owner_id, bool is_group_owned, Scene scene) - { - m_scene = scene; - LandData.OwnerID = owner_id; - if (is_group_owned) - LandData.GroupID = owner_id; - else - LandData.GroupID = UUID.Zero; - LandData.IsGroupOwned = is_group_owned; - } - - #endregion - - #region Member Functions - - #region General Functions - - /// - /// Checks to see if this land object contains a point - /// - /// - /// - /// Returns true if the piece of land contains the specified point - public bool ContainsPoint(int x, int y) - { - if (x >= 0 && y >= 0 && x <= Constants.RegionSize && y <= Constants.RegionSize) - { - return (LandBitmap[x / 4, y / 4] == true); - } - else - { - return false; - } - } - - public ILandObject Copy() - { - ILandObject newLand = new LandObject(LandData.OwnerID, LandData.IsGroupOwned, m_scene); - - //Place all new variables here! - newLand.LandBitmap = (bool[,]) (LandBitmap.Clone()); - newLand.LandData = LandData.Copy(); - - return newLand; - } - - static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount; - static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount; - - public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) - { - overrideParcelMaxPrimCount = overrideDel; - } - public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) - { - overrideSimulatorMaxPrimCount = overrideDel; - } - - public int GetParcelMaxPrimCount(ILandObject thisObject) - { - if (overrideParcelMaxPrimCount != null) - { - return overrideParcelMaxPrimCount(thisObject); - } - else - { - // Normal Calculations - return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); - } - } - public int GetSimulatorMaxPrimCount(ILandObject thisObject) - { - if (overrideSimulatorMaxPrimCount != null) - { - return overrideSimulatorMaxPrimCount(thisObject); - } - else - { - //Normal Calculations - return m_scene.RegionInfo.ObjectCapacity; - } - } - #endregion - - #region Packet Request Handling - - public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) - { - IEstateModule estateModule = m_scene.RequestModuleInterface(); - uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); - if (estateModule != null) - regionFlags = estateModule.GetRegionFlags(); - - // In a perfect world, this would have worked. - // -// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0) -// regionFlags |= (uint)RegionFlags.AllowLandmark; -// if (landData.OwnerID == remote_client.AgentId) -// regionFlags |= (uint)RegionFlags.AllowSetHome; - - int seq_id; - if (snap_selection && (sequence_id == 0)) - { - seq_id = m_lastSeqId; - } - else - { - seq_id = sequence_id; - m_lastSeqId = seq_id; - } - - remote_client.SendLandProperties(seq_id, - snap_selection, request_result, LandData, - (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, - GetParcelMaxPrimCount(this), - GetSimulatorMaxPrimCount(this), regionFlags); - } - - public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) - { - if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this)) - { - //Needs later group support - bool snap_selection = false; - LandData newData = LandData.Copy(); - - if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice) - { - if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this)) - { - newData.AuthBuyerID = args.AuthBuyerID; - newData.SalePrice = args.SalePrice; - snap_selection = true; - } - } - newData.Category = args.Category; - newData.Description = args.Desc; - newData.GroupID = args.GroupID; - newData.LandingType = args.LandingType; - newData.MediaAutoScale = args.MediaAutoScale; - newData.MediaID = args.MediaID; - newData.MediaURL = args.MediaURL; - newData.MusicURL = args.MusicURL; - newData.Name = args.Name; - newData.Flags = args.ParcelFlags; - newData.PassHours = args.PassHours; - newData.PassPrice = args.PassPrice; - newData.SnapshotID = args.SnapshotID; - newData.UserLocation = args.UserLocation; - newData.UserLookAt = args.UserLookAt; - - m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - - SendLandUpdateToAvatarsOverMe(snap_selection); - } - } - - public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) - { - LandData newData = LandData.Copy(); - newData.OwnerID = avatarID; - newData.GroupID = groupID; - newData.IsGroupOwned = groupOwned; - //newData.auctionID = AuctionID; - newData.ClaimDate = Util.UnixTimeSinceEpoch(); - newData.ClaimPrice = claimprice; - newData.SalePrice = 0; - newData.AuthBuyerID = UUID.Zero; - newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); - m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - - SendLandUpdateToAvatarsOverMe(true); - } - - public void DeedToGroup(UUID groupID) - { - LandData newData = LandData.Copy(); - newData.OwnerID = groupID; - newData.GroupID = groupID; - newData.IsGroupOwned = true; - - // Reset show in directory flag on deed - newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); - - m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - - SendLandUpdateToAvatarsOverMe(true); - } - - public bool IsEitherBannedOrRestricted(UUID avatar) - { - if (IsBannedFromLand(avatar)) - { - return true; - } - else if (IsRestrictedFromLand(avatar)) - { - return true; - } - return false; - } - - public bool IsBannedFromLand(UUID avatar) - { - if (m_scene.Permissions.IsAdministrator(avatar)) - return false; - - if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = avatar; - entry.Flags = AccessList.Ban; - entry.Time = new DateTime(); - //See if they are on the list, but make sure the owner isn't banned - if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) - { - //They are banned, so lets send them a notice about this parcel - return true; - } - } - return false; - } - - public bool IsRestrictedFromLand(UUID avatar) - { - if (m_scene.Permissions.IsAdministrator(avatar)) - return false; - - if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = avatar; - entry.Flags = AccessList.Access; - entry.Time = new DateTime(); - - //If they are not on the access list and are not the owner - if (!LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) - { - //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel - return true; - } - } - return false; - } - - public void SendLandUpdateToClient(IClientAPI remote_client) - { - SendLandProperties(0, false, 0, remote_client); - } - - public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client) - { - SendLandProperties(0, snap_selection, 0, remote_client); - } - - public void SendLandUpdateToAvatarsOverMe() - { - SendLandUpdateToAvatarsOverMe(false); - } - - public void SendLandUpdateToAvatarsOverMe(bool snap_selection) - { - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - if (avatar.IsChildAgent) - return; - - ILandObject over = null; - try - { - over = - m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)), - Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1))); - } - catch (Exception) - { - m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " + - Math.Round(avatar.AbsolutePosition.Y)); - } - - if (over != null) - { - if (over.LandData.LocalID == LandData.LocalID) - { - if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) && - m_scene.RegionInfo.RegionSettings.AllowDamage) - avatar.Invulnerable = false; - else - avatar.Invulnerable = true; - - SendLandUpdateToClient(snap_selection, avatar.ControllingClient); - } - } - }); - } - - #endregion - - #region AccessList Functions - - public List CreateAccessListArrayByFlag(AccessList flag) - { - List list = new List(); - foreach (ParcelManager.ParcelAccessEntry entry in LandData.ParcelAccessList) - { - if (entry.Flags == flag) - { - list.Add(entry.AgentID); - } - } - if (list.Count == 0) - { - list.Add(UUID.Zero); - } - - return list; - } - - public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID, - IClientAPI remote_client) - { - - if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both) - { - List avatars = CreateAccessListArrayByFlag(AccessList.Access); - remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,LandData.LocalID); - } - - if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both) - { - List avatars = CreateAccessListArrayByFlag(AccessList.Ban); - remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, LandData.LocalID); - } - } - - public void UpdateAccessList(uint flags, List entries, IClientAPI remote_client) - { - LandData newData = LandData.Copy(); - - if (entries.Count == 1 && entries[0].AgentID == UUID.Zero) - { - entries.Clear(); - } - - List toRemove = new List(); - foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList) - { - if (entry.Flags == (AccessList)flags) - { - toRemove.Add(entry); - } - } - - foreach (ParcelManager.ParcelAccessEntry entry in toRemove) - { - newData.ParcelAccessList.Remove(entry); - } - foreach (ParcelManager.ParcelAccessEntry entry in entries) - { - ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry(); - temp.AgentID = entry.AgentID; - temp.Time = new DateTime(); //Pointless? Yes. - temp.Flags = (AccessList)flags; - - if (!newData.ParcelAccessList.Contains(temp)) - { - newData.ParcelAccessList.Add(temp); - } - } - - m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - } - - #endregion - - #region Update Functions - - public void UpdateLandBitmapByteArray() - { - LandData.Bitmap = ConvertLandBitmapToBytes(); - } - - /// - /// Update all settings in land such as area, bitmap byte array, etc - /// - public void ForceUpdateLandInfo() - { - UpdateAABBAndAreaValues(); - UpdateLandBitmapByteArray(); - } - - public void SetLandBitmapFromByteArray() - { - LandBitmap = ConvertBytesToLandBitmap(); - } - - /// - /// Updates the AABBMin and AABBMax values after area/shape modification of the land object - /// - private void UpdateAABBAndAreaValues() - { - int min_x = 64; - int min_y = 64; - int max_x = 0; - int max_y = 0; - int tempArea = 0; - int x, y; - for (x = 0; x < 64; x++) - { - for (y = 0; y < 64; y++) - { - if (LandBitmap[x, y] == true) - { - if (min_x > x) min_x = x; - if (min_y > y) min_y = y; - if (max_x < x) max_x = x; - if (max_y < y) max_y = y; - tempArea += 16; //16sqm peice of land - } - } - } - int tx = min_x * 4; - if (tx > ((int)Constants.RegionSize - 1)) - tx = ((int)Constants.RegionSize - 1); - int ty = min_y * 4; - if (ty > ((int)Constants.RegionSize - 1)) - ty = ((int)Constants.RegionSize - 1); - LandData.AABBMin = - new Vector3((float) (min_x * 4), (float) (min_y * 4), - (float) m_scene.Heightmap[tx, ty]); - - tx = max_x * 4; - if (tx > ((int)Constants.RegionSize - 1)) - tx = ((int)Constants.RegionSize - 1); - ty = max_y * 4; - if (ty > ((int)Constants.RegionSize - 1)) - ty = ((int)Constants.RegionSize - 1); - LandData.AABBMax = - new Vector3((float) (max_x * 4), (float) (max_y * 4), - (float) m_scene.Heightmap[tx, ty]); - LandData.Area = tempArea; - } - - #endregion - - #region Land Bitmap Functions - - /// - /// Sets the land's bitmap manually - /// - /// 64x64 block representing where this land is on a map - public void SetLandBitmap(bool[,] bitmap) - { - if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - //throw new Exception("Error: Invalid Parcel Bitmap"); - } - else - { - //Valid: Lets set it - LandBitmap = bitmap; - ForceUpdateLandInfo(); - } - } - - /// - /// Gets the land's bitmap manually - /// - /// - public bool[,] GetLandBitmap() - { - return LandBitmap; - } - - /// - /// Full sim land object creation - /// - /// - public bool[,] BasicFullRegionLandBitmap() - { - return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); - } - - /// - /// Used to modify the bitmap between the x and y points. Points use 64 scale - /// - /// - /// - /// - /// - /// - public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) - { - bool[,] tempBitmap = new bool[64,64]; - tempBitmap.Initialize(); - - tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); - return tempBitmap; - } - - /// - /// Change a land bitmap at within a square and set those points to a specific value - /// - /// - /// - /// - /// - /// - /// - /// - public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, - bool set_value) - { - if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()"); - } - - int x, y; - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - if (x >= start_x / 4 && x < end_x / 4 - && y >= start_y / 4 && y < end_y / 4) - { - land_bitmap[x, y] = set_value; - } - } - } - return land_bitmap; - } - - /// - /// Join the true values of 2 bitmaps together - /// - /// - /// - /// - public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) - { - if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); - } - if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps"); - } - - int x, y; - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - if (bitmap_add[x, y]) - { - bitmap_base[x, y] = true; - } - } - } - return bitmap_base; - } - - /// - /// Converts the land bitmap to a packet friendly byte array - /// - /// - private byte[] ConvertLandBitmapToBytes() - { - byte[] tempConvertArr = new byte[512]; - byte tempByte = 0; - int x, y, i, byteNum = 0; - i = 0; - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); - if (i % 8 == 0) - { - tempConvertArr[byteNum] = tempByte; - tempByte = (byte) 0; - i = 0; - byteNum++; - } - } - } - return tempConvertArr; - } - - private bool[,] ConvertBytesToLandBitmap() - { - bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax]; - tempConvertMap.Initialize(); - byte tempByte = 0; - int x = 0, y = 0, i = 0, bitNum = 0; - for (i = 0; i < 512; i++) - { - tempByte = LandData.Bitmap[i]; - for (bitNum = 0; bitNum < 8; bitNum++) - { - bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); - tempConvertMap[x, y] = bit; - x++; - if (x > 63) - { - x = 0; - y++; - } - } - } - return tempConvertMap; - } - - #endregion - - #region Object Select and Object Owner Listing - - public void SendForceObjectSelect(int local_id, int request_type, List returnIDs, IClientAPI remote_client) - { - if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) - { - List resultLocalIDs = new List(); - try - { - lock (primsOverMe) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.LocalId > 0) - { - if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID) - { - resultLocalIDs.Add(obj.LocalId); - } - else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero) - { - resultLocalIDs.Add(obj.LocalId); - } - else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER && - obj.OwnerID != remote_client.AgentId) - { - resultLocalIDs.Add(obj.LocalId); - } - else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID)) - { - resultLocalIDs.Add(obj.LocalId); - } - } - } - } - } catch (InvalidOperationException) - { - m_log.Error("[LAND]: Unable to force select the parcel objects. Arr."); - } - - remote_client.SendForceClientSelectObjects(resultLocalIDs); - } - } - - /// - /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes - /// aggreagete details such as the number of prims. - /// - /// - /// - /// A - /// - public void SendLandObjectOwners(IClientAPI remote_client) - { - if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) - { - Dictionary primCount = new Dictionary(); - List groups = new List(); - - lock (primsOverMe) - { - try - { - - foreach (SceneObjectGroup obj in primsOverMe) - { - try - { - if (!primCount.ContainsKey(obj.OwnerID)) - { - primCount.Add(obj.OwnerID, 0); - } - } - catch (NullReferenceException) - { - m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel"); - } - try - { - primCount[obj.OwnerID] += obj.PrimCount; - } - catch (KeyNotFoundException) - { - m_log.Error("[LAND]: Unable to match a prim with it's owner."); - } - if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID))) - groups.Add(obj.OwnerID); - } - } - catch (InvalidOperationException) - { - m_log.Error("[LAND]: Unable to Enumerate Land object arr."); - } - } - - remote_client.SendLandObjectOwners(LandData, groups, primCount); - } - } - - public Dictionary GetLandObjectOwners() - { - Dictionary ownersAndCount = new Dictionary(); - lock (primsOverMe) - { - try - { - - foreach (SceneObjectGroup obj in primsOverMe) - { - if (!ownersAndCount.ContainsKey(obj.OwnerID)) - { - ownersAndCount.Add(obj.OwnerID, 0); - } - ownersAndCount[obj.OwnerID] += obj.PrimCount; - } - } - catch (InvalidOperationException) - { - m_log.Error("[LAND]: Unable to enumerate land owners. arr."); - } - - } - return ownersAndCount; - } - - #endregion - - #region Object Returning - - public void ReturnObject(SceneObjectGroup obj) - { - SceneObjectGroup[] objs = new SceneObjectGroup[1]; - objs[0] = obj; - m_scene.returnObjects(objs, obj.OwnerID); - } - - public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) - { - Dictionary> returns = - new Dictionary>(); - - lock (primsOverMe) - { - if (type == (uint)ObjectReturnType.Owner) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.OwnerID == m_landData.OwnerID) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.GroupID == m_landData.GroupID) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - else if (type == (uint)ObjectReturnType.Other) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.OwnerID != m_landData.OwnerID && - (obj.GroupID != m_landData.GroupID || - m_landData.GroupID == UUID.Zero)) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - else if (type == (uint)ObjectReturnType.List) - { - List ownerlist = new List(owners); - - foreach (SceneObjectGroup obj in primsOverMe) - { - if (ownerlist.Contains(obj.OwnerID)) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - } - - foreach (List ol in returns.Values) - { - if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) - m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); - } - } - - #endregion - - #region Object Adding/Removing from Parcel - - public void ResetLandPrimCounts() - { - LandData.GroupPrims = 0; - LandData.OwnerPrims = 0; - LandData.OtherPrims = 0; - LandData.SelectedPrims = 0; - - - lock (primsOverMe) - primsOverMe.Clear(); - } - - public void AddPrimToCount(SceneObjectGroup obj) - { - - UUID prim_owner = obj.OwnerID; - int prim_count = obj.PrimCount; - - if (obj.IsSelected) - { - LandData.SelectedPrims += prim_count; - } - else - { - if (prim_owner == LandData.OwnerID) - { - LandData.OwnerPrims += prim_count; - } - else if ((obj.GroupID == LandData.GroupID || - prim_owner == LandData.GroupID) && - LandData.GroupID != UUID.Zero) - { - LandData.GroupPrims += prim_count; - } - else - { - LandData.OtherPrims += prim_count; - } - } - - lock (primsOverMe) - primsOverMe.Add(obj); - } - - public void RemovePrimFromCount(SceneObjectGroup obj) - { - lock (primsOverMe) - { - if (primsOverMe.Contains(obj)) - { - UUID prim_owner = obj.OwnerID; - int prim_count = obj.PrimCount; - - if (prim_owner == LandData.OwnerID) - { - LandData.OwnerPrims -= prim_count; - } - else if (obj.GroupID == LandData.GroupID || - prim_owner == LandData.GroupID) - { - LandData.GroupPrims -= prim_count; - } - else - { - LandData.OtherPrims -= prim_count; - } - - primsOverMe.Remove(obj); - } - } - } - - #endregion - - #endregion - - #endregion - - /// - /// Set the media url for this land parcel - /// - /// - public void SetMediaUrl(string url) - { - LandData.MediaURL = url; - SendLandUpdateToAvatarsOverMe(); - } - - /// - /// Set the music url for this land parcel - /// - /// - public void SetMusicUrl(string url) - { - LandData.MusicURL = url; - SendLandUpdateToAvatarsOverMe(); - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Land +{ + /// + /// Keeps track of a specific piece of land's information + /// + public class LandObject : ILandObject + { + #region Member Variables + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + #pragma warning disable 0429 + private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64; + #pragma warning restore 0429 + private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax]; + + private int m_lastSeqId = 0; + + protected LandData m_landData = new LandData(); + protected Scene m_scene; + protected List primsOverMe = new List(); + + public bool[,] LandBitmap + { + get { return m_landBitmap; } + set { m_landBitmap = value; } + } + + #endregion + + #region ILandObject Members + + public LandData LandData + { + get { return m_landData; } + + set { m_landData = value; } + } + + public UUID RegionUUID + { + get { return m_scene.RegionInfo.RegionID; } + } + + #region Constructors + + public LandObject(UUID owner_id, bool is_group_owned, Scene scene) + { + m_scene = scene; + LandData.OwnerID = owner_id; + if (is_group_owned) + LandData.GroupID = owner_id; + else + LandData.GroupID = UUID.Zero; + LandData.IsGroupOwned = is_group_owned; + } + + #endregion + + #region Member Functions + + #region General Functions + + /// + /// Checks to see if this land object contains a point + /// + /// + /// + /// Returns true if the piece of land contains the specified point + public bool ContainsPoint(int x, int y) + { + if (x >= 0 && y >= 0 && x <= Constants.RegionSize && y <= Constants.RegionSize) + { + return (LandBitmap[x / 4, y / 4] == true); + } + else + { + return false; + } + } + + public ILandObject Copy() + { + ILandObject newLand = new LandObject(LandData.OwnerID, LandData.IsGroupOwned, m_scene); + + //Place all new variables here! + newLand.LandBitmap = (bool[,]) (LandBitmap.Clone()); + newLand.LandData = LandData.Copy(); + + return newLand; + } + + static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount; + static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount; + + public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) + { + overrideParcelMaxPrimCount = overrideDel; + } + public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) + { + overrideSimulatorMaxPrimCount = overrideDel; + } + + public int GetParcelMaxPrimCount(ILandObject thisObject) + { + if (overrideParcelMaxPrimCount != null) + { + return overrideParcelMaxPrimCount(thisObject); + } + else + { + // Normal Calculations + return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); + } + } + public int GetSimulatorMaxPrimCount(ILandObject thisObject) + { + if (overrideSimulatorMaxPrimCount != null) + { + return overrideSimulatorMaxPrimCount(thisObject); + } + else + { + //Normal Calculations + return m_scene.RegionInfo.ObjectCapacity; + } + } + #endregion + + #region Packet Request Handling + + public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) + { + IEstateModule estateModule = m_scene.RequestModuleInterface(); + uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); + if (estateModule != null) + regionFlags = estateModule.GetRegionFlags(); + + // In a perfect world, this would have worked. + // +// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0) +// regionFlags |= (uint)RegionFlags.AllowLandmark; +// if (landData.OwnerID == remote_client.AgentId) +// regionFlags |= (uint)RegionFlags.AllowSetHome; + + int seq_id; + if (snap_selection && (sequence_id == 0)) + { + seq_id = m_lastSeqId; + } + else + { + seq_id = sequence_id; + m_lastSeqId = seq_id; + } + + remote_client.SendLandProperties(seq_id, + snap_selection, request_result, LandData, + (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, + GetParcelMaxPrimCount(this), + GetSimulatorMaxPrimCount(this), regionFlags); + } + + public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) + { + if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this)) + { + //Needs later group support + bool snap_selection = false; + LandData newData = LandData.Copy(); + + if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice) + { + if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this)) + { + newData.AuthBuyerID = args.AuthBuyerID; + newData.SalePrice = args.SalePrice; + snap_selection = true; + } + } + newData.Category = args.Category; + newData.Description = args.Desc; + newData.GroupID = args.GroupID; + newData.LandingType = args.LandingType; + newData.MediaAutoScale = args.MediaAutoScale; + newData.MediaID = args.MediaID; + newData.MediaURL = args.MediaURL; + newData.MusicURL = args.MusicURL; + newData.Name = args.Name; + newData.Flags = args.ParcelFlags; + newData.PassHours = args.PassHours; + newData.PassPrice = args.PassPrice; + newData.SnapshotID = args.SnapshotID; + newData.UserLocation = args.UserLocation; + newData.UserLookAt = args.UserLookAt; + + m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); + + SendLandUpdateToAvatarsOverMe(snap_selection); + } + } + + public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) + { + LandData newData = LandData.Copy(); + newData.OwnerID = avatarID; + newData.GroupID = groupID; + newData.IsGroupOwned = groupOwned; + //newData.auctionID = AuctionID; + newData.ClaimDate = Util.UnixTimeSinceEpoch(); + newData.ClaimPrice = claimprice; + newData.SalePrice = 0; + newData.AuthBuyerID = UUID.Zero; + newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); + m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); + + SendLandUpdateToAvatarsOverMe(true); + } + + public void DeedToGroup(UUID groupID) + { + LandData newData = LandData.Copy(); + newData.OwnerID = groupID; + newData.GroupID = groupID; + newData.IsGroupOwned = true; + + // Reset show in directory flag on deed + newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); + + m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); + + SendLandUpdateToAvatarsOverMe(true); + } + + public bool IsEitherBannedOrRestricted(UUID avatar) + { + if (IsBannedFromLand(avatar)) + { + return true; + } + else if (IsRestrictedFromLand(avatar)) + { + return true; + } + return false; + } + + public bool HasGroupAccess(UUID avatar) + { + if ((LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) + { + IGroupsModule groupsModule = + m_scene.RequestModuleInterface(); + + List agentGroups = new List(); + if (groupsModule != null) + { + GroupMembershipData[] GroupMembership = + groupsModule.GetMembershipData(avatar); + + if (GroupMembership != null) + { + for (int i = 0; i < GroupMembership.Length; i++) + { + if (LandData.GroupID == GroupMembership[i].GroupID) + { + return true; + } + } + } + } + } + return false; + } + + public bool IsBannedFromLand(UUID avatar) + { + if (m_scene.Permissions.IsAdministrator(avatar)) + return false; + + if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = avatar; + entry.Flags = AccessList.Ban; + entry.Time = new DateTime(); + //See if they are on the list, but make sure the owner isn't banned + if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) + { + //They are banned, so lets send them a notice about this parcel + return true; + } + } + return false; + } + + public bool IsRestrictedFromLand(UUID avatar) + { + if (m_scene.Permissions.IsAdministrator(avatar)) + return false; + + if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = avatar; + entry.Flags = AccessList.Access; + entry.Time = new DateTime(); + + //If they are not on the access list and are not the owner + if (!LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) + { + if (!HasGroupAccess(avatar)) + { + //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel + return true; + } + } + } + + return false; + } + + public void SendLandUpdateToClient(IClientAPI remote_client) + { + SendLandProperties(0, false, 0, remote_client); + } + + public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client) + { + SendLandProperties(0, snap_selection, 0, remote_client); + } + + public void SendLandUpdateToAvatarsOverMe() + { + SendLandUpdateToAvatarsOverMe(false); + } + + public void SendLandUpdateToAvatarsOverMe(bool snap_selection) + { + m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + if (avatar.IsChildAgent) + return; + + ILandObject over = null; + try + { + over = + m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)), + Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1))); + } + catch (Exception) + { + m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " + + Math.Round(avatar.AbsolutePosition.Y)); + } + + if (over != null) + { + if (over.LandData.LocalID == LandData.LocalID) + { + if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) && + m_scene.RegionInfo.RegionSettings.AllowDamage) + avatar.Invulnerable = false; + else + avatar.Invulnerable = true; + + SendLandUpdateToClient(snap_selection, avatar.ControllingClient); + } + } + }); + } + + #endregion + + #region AccessList Functions + + public List CreateAccessListArrayByFlag(AccessList flag) + { + List list = new List(); + foreach (ParcelManager.ParcelAccessEntry entry in LandData.ParcelAccessList) + { + if (entry.Flags == flag) + { + list.Add(entry.AgentID); + } + } + if (list.Count == 0) + { + list.Add(UUID.Zero); + } + + return list; + } + + public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID, + IClientAPI remote_client) + { + + if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both) + { + List avatars = CreateAccessListArrayByFlag(AccessList.Access); + remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,LandData.LocalID); + } + + if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both) + { + List avatars = CreateAccessListArrayByFlag(AccessList.Ban); + remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, LandData.LocalID); + } + } + + public void UpdateAccessList(uint flags, List entries, IClientAPI remote_client) + { + LandData newData = LandData.Copy(); + + if (entries.Count == 1 && entries[0].AgentID == UUID.Zero) + { + entries.Clear(); + } + + List toRemove = new List(); + foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList) + { + if (entry.Flags == (AccessList)flags) + { + toRemove.Add(entry); + } + } + + foreach (ParcelManager.ParcelAccessEntry entry in toRemove) + { + newData.ParcelAccessList.Remove(entry); + } + foreach (ParcelManager.ParcelAccessEntry entry in entries) + { + ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry(); + temp.AgentID = entry.AgentID; + temp.Time = new DateTime(); //Pointless? Yes. + temp.Flags = (AccessList)flags; + + if (!newData.ParcelAccessList.Contains(temp)) + { + newData.ParcelAccessList.Add(temp); + } + } + + m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); + } + + #endregion + + #region Update Functions + + public void UpdateLandBitmapByteArray() + { + LandData.Bitmap = ConvertLandBitmapToBytes(); + } + + /// + /// Update all settings in land such as area, bitmap byte array, etc + /// + public void ForceUpdateLandInfo() + { + UpdateAABBAndAreaValues(); + UpdateLandBitmapByteArray(); + } + + public void SetLandBitmapFromByteArray() + { + LandBitmap = ConvertBytesToLandBitmap(); + } + + /// + /// Updates the AABBMin and AABBMax values after area/shape modification of the land object + /// + private void UpdateAABBAndAreaValues() + { + int min_x = 64; + int min_y = 64; + int max_x = 0; + int max_y = 0; + int tempArea = 0; + int x, y; + for (x = 0; x < 64; x++) + { + for (y = 0; y < 64; y++) + { + if (LandBitmap[x, y] == true) + { + if (min_x > x) min_x = x; + if (min_y > y) min_y = y; + if (max_x < x) max_x = x; + if (max_y < y) max_y = y; + tempArea += 16; //16sqm peice of land + } + } + } + int tx = min_x * 4; + if (tx > ((int)Constants.RegionSize - 1)) + tx = ((int)Constants.RegionSize - 1); + int ty = min_y * 4; + if (ty > ((int)Constants.RegionSize - 1)) + ty = ((int)Constants.RegionSize - 1); + LandData.AABBMin = + new Vector3((float) (min_x * 4), (float) (min_y * 4), + (float) m_scene.Heightmap[tx, ty]); + + tx = max_x * 4; + if (tx > ((int)Constants.RegionSize - 1)) + tx = ((int)Constants.RegionSize - 1); + ty = max_y * 4; + if (ty > ((int)Constants.RegionSize - 1)) + ty = ((int)Constants.RegionSize - 1); + LandData.AABBMax = + new Vector3((float) (max_x * 4), (float) (max_y * 4), + (float) m_scene.Heightmap[tx, ty]); + LandData.Area = tempArea; + } + + #endregion + + #region Land Bitmap Functions + + /// + /// Sets the land's bitmap manually + /// + /// 64x64 block representing where this land is on a map + public void SetLandBitmap(bool[,] bitmap) + { + if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + //throw new Exception("Error: Invalid Parcel Bitmap"); + } + else + { + //Valid: Lets set it + LandBitmap = bitmap; + ForceUpdateLandInfo(); + } + } + + /// + /// Gets the land's bitmap manually + /// + /// + public bool[,] GetLandBitmap() + { + return LandBitmap; + } + + /// + /// Full sim land object creation + /// + /// + public bool[,] BasicFullRegionLandBitmap() + { + return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); + } + + /// + /// Used to modify the bitmap between the x and y points. Points use 64 scale + /// + /// + /// + /// + /// + /// + public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) + { + bool[,] tempBitmap = new bool[64,64]; + tempBitmap.Initialize(); + + tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); + return tempBitmap; + } + + /// + /// Change a land bitmap at within a square and set those points to a specific value + /// + /// + /// + /// + /// + /// + /// + /// + public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, + bool set_value) + { + if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()"); + } + + int x, y; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + if (x >= start_x / 4 && x < end_x / 4 + && y >= start_y / 4 && y < end_y / 4) + { + land_bitmap[x, y] = set_value; + } + } + } + return land_bitmap; + } + + /// + /// Join the true values of 2 bitmaps together + /// + /// + /// + /// + public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) + { + if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); + } + if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps"); + } + + int x, y; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + if (bitmap_add[x, y]) + { + bitmap_base[x, y] = true; + } + } + } + return bitmap_base; + } + + /// + /// Converts the land bitmap to a packet friendly byte array + /// + /// + private byte[] ConvertLandBitmapToBytes() + { + byte[] tempConvertArr = new byte[512]; + byte tempByte = 0; + int x, y, i, byteNum = 0; + i = 0; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); + if (i % 8 == 0) + { + tempConvertArr[byteNum] = tempByte; + tempByte = (byte) 0; + i = 0; + byteNum++; + } + } + } + return tempConvertArr; + } + + private bool[,] ConvertBytesToLandBitmap() + { + bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax]; + tempConvertMap.Initialize(); + byte tempByte = 0; + int x = 0, y = 0, i = 0, bitNum = 0; + for (i = 0; i < 512; i++) + { + tempByte = LandData.Bitmap[i]; + for (bitNum = 0; bitNum < 8; bitNum++) + { + bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); + tempConvertMap[x, y] = bit; + x++; + if (x > 63) + { + x = 0; + y++; + } + } + } + return tempConvertMap; + } + + #endregion + + #region Object Select and Object Owner Listing + + public void SendForceObjectSelect(int local_id, int request_type, List returnIDs, IClientAPI remote_client) + { + if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) + { + List resultLocalIDs = new List(); + try + { + lock (primsOverMe) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.LocalId > 0) + { + if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID) + { + resultLocalIDs.Add(obj.LocalId); + } + else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero) + { + resultLocalIDs.Add(obj.LocalId); + } + else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER && + obj.OwnerID != remote_client.AgentId) + { + resultLocalIDs.Add(obj.LocalId); + } + else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID)) + { + resultLocalIDs.Add(obj.LocalId); + } + } + } + } + } catch (InvalidOperationException) + { + m_log.Error("[LAND]: Unable to force select the parcel objects. Arr."); + } + + remote_client.SendForceClientSelectObjects(resultLocalIDs); + } + } + + /// + /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes + /// aggreagete details such as the number of prims. + /// + /// + /// + /// A + /// + public void SendLandObjectOwners(IClientAPI remote_client) + { + if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) + { + Dictionary primCount = new Dictionary(); + List groups = new List(); + + lock (primsOverMe) + { + try + { + + foreach (SceneObjectGroup obj in primsOverMe) + { + try + { + if (!primCount.ContainsKey(obj.OwnerID)) + { + primCount.Add(obj.OwnerID, 0); + } + } + catch (NullReferenceException) + { + m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel"); + } + try + { + primCount[obj.OwnerID] += obj.PrimCount; + } + catch (KeyNotFoundException) + { + m_log.Error("[LAND]: Unable to match a prim with it's owner."); + } + if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID))) + groups.Add(obj.OwnerID); + } + } + catch (InvalidOperationException) + { + m_log.Error("[LAND]: Unable to Enumerate Land object arr."); + } + } + + remote_client.SendLandObjectOwners(LandData, groups, primCount); + } + } + + public Dictionary GetLandObjectOwners() + { + Dictionary ownersAndCount = new Dictionary(); + lock (primsOverMe) + { + try + { + + foreach (SceneObjectGroup obj in primsOverMe) + { + if (!ownersAndCount.ContainsKey(obj.OwnerID)) + { + ownersAndCount.Add(obj.OwnerID, 0); + } + ownersAndCount[obj.OwnerID] += obj.PrimCount; + } + } + catch (InvalidOperationException) + { + m_log.Error("[LAND]: Unable to enumerate land owners. arr."); + } + + } + return ownersAndCount; + } + + #endregion + + #region Object Returning + + public void ReturnObject(SceneObjectGroup obj) + { + SceneObjectGroup[] objs = new SceneObjectGroup[1]; + objs[0] = obj; + m_scene.returnObjects(objs, obj.OwnerID); + } + + public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) + { + Dictionary> returns = + new Dictionary>(); + + lock (primsOverMe) + { + if (type == (uint)ObjectReturnType.Owner) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.OwnerID == m_landData.OwnerID) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.GroupID == m_landData.GroupID) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + else if (type == (uint)ObjectReturnType.Other) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.OwnerID != m_landData.OwnerID && + (obj.GroupID != m_landData.GroupID || + m_landData.GroupID == UUID.Zero)) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + else if (type == (uint)ObjectReturnType.List) + { + List ownerlist = new List(owners); + + foreach (SceneObjectGroup obj in primsOverMe) + { + if (ownerlist.Contains(obj.OwnerID)) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + } + + foreach (List ol in returns.Values) + { + if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) + m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); + } + } + + #endregion + + #region Object Adding/Removing from Parcel + + public void ResetLandPrimCounts() + { + LandData.GroupPrims = 0; + LandData.OwnerPrims = 0; + LandData.OtherPrims = 0; + LandData.SelectedPrims = 0; + + + lock (primsOverMe) + primsOverMe.Clear(); + } + + public void AddPrimToCount(SceneObjectGroup obj) + { + + UUID prim_owner = obj.OwnerID; + int prim_count = obj.PrimCount; + + if (obj.IsSelected) + { + LandData.SelectedPrims += prim_count; + } + else + { + if (prim_owner == LandData.OwnerID) + { + LandData.OwnerPrims += prim_count; + } + else if ((obj.GroupID == LandData.GroupID || + prim_owner == LandData.GroupID) && + LandData.GroupID != UUID.Zero) + { + LandData.GroupPrims += prim_count; + } + else + { + LandData.OtherPrims += prim_count; + } + } + + lock (primsOverMe) + primsOverMe.Add(obj); + } + + public void RemovePrimFromCount(SceneObjectGroup obj) + { + lock (primsOverMe) + { + if (primsOverMe.Contains(obj)) + { + UUID prim_owner = obj.OwnerID; + int prim_count = obj.PrimCount; + + if (prim_owner == LandData.OwnerID) + { + LandData.OwnerPrims -= prim_count; + } + else if (obj.GroupID == LandData.GroupID || + prim_owner == LandData.GroupID) + { + LandData.GroupPrims -= prim_count; + } + else + { + LandData.OtherPrims -= prim_count; + } + + primsOverMe.Remove(obj); + } + } + } + + #endregion + + #endregion + + #endregion + + /// + /// Set the media url for this land parcel + /// + /// + public void SetMediaUrl(string url) + { + LandData.MediaURL = url; + SendLandUpdateToAvatarsOverMe(); + } + + /// + /// Set the music url for this land parcel + /// + /// + public void SetMusicUrl(string url) + { + LandData.MusicURL = url; + SendLandUpdateToAvatarsOverMe(); + } + } +} -- cgit v1.1 From f9b5f23383675abe0ae1c2ed83dd5ccce738d940 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 22:19:26 -0700 Subject: Reverted: * Fix the unscripted sit rotation being incorrect .. will commit a proper fix now. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index cca296e..87cf135 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2053,13 +2053,9 @@ namespace OpenSim.Region.Framework.Scenes //Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child - Quaternion roffset = Quaternion.Identity; - if (SitTargetisSet) - { - roffset = part.RotationOffset; - } - ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * roffset) + part.OffsetPosition), sitOrientation / part.RotationOffset, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); + ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); + m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target // This calls HandleAgentSit twice, once from here, and the client calls // HandleAgentSit itself after it gets to the location // It doesn't get to the location until we've moved them there though @@ -2444,7 +2440,7 @@ namespace OpenSim.Region.Framework.Scenes } m_linkedPrim = part.UUID; - m_offsetRotation = m_offsetRotation / part.RotationOffset; + Velocity = Vector3.Zero; RemoveFromPhysicalScene(); Animator.TrySetMovementAnimation(sitAnimation); -- cgit v1.1 From a1f2be5e69ef04a8520229e161bdd0527badb844 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 7 Aug 2010 22:25:37 -0700 Subject: The real fix for unscripted sit positions. This one doesn't fuck everything else up. Promise. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 87cf135..fc8e0d7 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2440,7 +2440,10 @@ namespace OpenSim.Region.Framework.Scenes } m_linkedPrim = part.UUID; - + if (part.GetAvatarOnSitTarget() != UUID) + { + m_offsetRotation = m_offsetRotation / part.RotationOffset; + } Velocity = Vector3.Zero; RemoveFromPhysicalScene(); Animator.TrySetMovementAnimation(sitAnimation); -- cgit v1.1 From 1cde77293e993c3a7329ea8e1fa013c8d7b898e5 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 8 Aug 2010 17:51:43 +0200 Subject: Thank you, Marck00, for a patch that implemented region distance sorting for fallback regions. Applied with changes. --- OpenSim/Data/IRegionData.cs | 22 ++++++++++++++++++++++ OpenSim/Data/MSSQL/MSSQLRegionData.cs | 7 +++++-- OpenSim/Data/MySQL/MySQLRegionData.cs | 6 ++++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs index 42533c6..46dc4fb 100644 --- a/OpenSim/Data/IRegionData.cs +++ b/OpenSim/Data/IRegionData.cs @@ -79,4 +79,26 @@ namespace OpenSim.Data Authenticate = 256, // Require authentication Hyperlink = 512 // Record represents a HG link } + + public class RegionDataDistanceCompare : IComparer + { + private Vector2 m_origin; + + public RegionDataDistanceCompare(int x, int y) + { + m_origin = new Vector2(x, y); + } + + public int Compare(RegionData regionA, RegionData regionB) + { + Vector2 vectorA = new Vector2(regionA.posX, regionA.posY); + Vector2 vectorB = new Vector2(regionB.posX, regionB.posY); + return Math.Sign(VectorDistance(m_origin, vectorA) - VectorDistance(m_origin, vectorB)); + } + + private float VectorDistance(Vector2 x, Vector2 y) + { + return (x - y).Length(); + } + } } diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs index 9656be1..cdf8ec0 100644 --- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs @@ -315,8 +315,11 @@ namespace OpenSim.Data.MSSQL public List GetFallbackRegions(UUID scopeID, int x, int y) { - // TODO: distance-sort results - return Get((int)RegionFlags.FallbackRegion, scopeID); + List regions = Get((int)RegionFlags.FallbackRegion, scopeID); + RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y); + regions.Sort(distanceComparer); + + return regions; } public List GetHyperlinks(UUID scopeID) diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs index aec37e2..878b8e8 100644 --- a/OpenSim/Data/MySQL/MySQLRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLRegionData.cs @@ -289,8 +289,10 @@ namespace OpenSim.Data.MySQL public List GetFallbackRegions(UUID scopeID, int x, int y) { - // TODO: distance-sort results - return Get((int)RegionFlags.FallbackRegion, scopeID); + List regions = Get((int)RegionFlags.FallbackRegion, scopeID); + RegionDataDistanceCompare distanceComparer = new RegionDataDistanceCompare(x, y); + regions.Sort(distanceComparer); + return regions; } public List GetHyperlinks(UUID scopeID) -- cgit v1.1 From ca2a4bbded8c33125c5b96bb3b715e3f3925ddad Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 8 Aug 2010 19:35:20 +0200 Subject: Add debug messages to attachment receiving and cowardly refuse to create them if the owner can't be determined. --- OpenSim/Region/Framework/Scenes/Scene.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 6c17be8..8a8dabc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2592,6 +2592,12 @@ namespace OpenSim.Region.Framework.Scenes /// True if the SceneObjectGroup was added, False if it was not public bool AddSceneObject(SceneObjectGroup sceneObject) { + if (sceneObject.OwnerID == UUID.Zero) + { + m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID); + return false; + } + // If the user is banned, we won't let any of their objects // enter. Period. // @@ -2641,15 +2647,27 @@ namespace OpenSim.Region.Framework.Scenes if (AttachmentsModule != null) AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); + m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID); } else { + m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID); RootPrim.RemFlag(PrimFlags.TemporaryOnRez); RootPrim.AddFlag(PrimFlags.TemporaryOnRez); } + if (sceneObject.OwnerID == UUID.Zero) + { + m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID); + return false; + } } else { + if (sceneObject.OwnerID == UUID.Zero) + { + m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID); + return false; + } AddRestoredSceneObject(sceneObject, true, false); if (!Permissions.CanObjectEntry(sceneObject.UUID, @@ -5333,4 +5351,4 @@ namespace OpenSim.Region.Framework.Scenes return offsets.ToArray(); } } -} \ No newline at end of file +} -- cgit v1.1 From 603b3a1606396e355416eae838f6bdaa5051bf1f Mon Sep 17 00:00:00 2001 From: meta7 Date: Sun, 8 Aug 2010 17:31:29 -0700 Subject: Fix minimap issues. This addresses mantis #228. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 5acc227..94ec534 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -228,27 +228,8 @@ namespace OpenSim.Region.Framework.Scenes if (sp.IsChildAgent) return; - if (sp.ParentID != 0) - { - // sitting avatar - SceneObjectPart sop = m_parentScene.GetSceneObjectPart(sp.ParentID); - if (sop != null) - { - coarseLocations.Add(sop.AbsolutePosition + sp.AbsolutePosition); - avatarUUIDs.Add(sp.UUID); - } - else - { - // we can't find the parent.. ! arg! - coarseLocations.Add(sp.AbsolutePosition); - avatarUUIDs.Add(sp.UUID); - } - } - else - { - coarseLocations.Add(sp.AbsolutePosition); - avatarUUIDs.Add(sp.UUID); - } + coarseLocations.Add(sp.AbsolutePosition); + avatarUUIDs.Add(sp.UUID); } } -- cgit v1.1 From 680e801bf229d54dc57dbca24e841f7f2e8f43d4 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sun, 8 Aug 2010 17:32:20 -0700 Subject: Print a console message when we deny access because of no valid parcel found. --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 8a8dabc..779f898 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3513,7 +3513,8 @@ namespace OpenSim.Region.Framework.Scenes if (tp == TeleportFlags.ViaLogin) { if (land != null && !TestLandRestrictions(agent, land, out reason)) - { + { + m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); return false; } } -- cgit v1.1 From f20dc512e87983b9ba6b86f806489380d3cfef5a Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 9 Aug 2010 02:46:09 +0200 Subject: Whitespace conflict --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- OpenSim/Services/LLLoginService/LLLoginService.cs | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 779f898..06bbe32 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3513,7 +3513,7 @@ namespace OpenSim.Region.Framework.Scenes if (tp == TeleportFlags.ViaLogin) { if (land != null && !TestLandRestrictions(agent, land, out reason)) - { + { m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); return false; } diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 602616f..0bf75b0 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -691,11 +691,7 @@ namespace OpenSim.Services.LLLoginService } } } -<<<<<<< HEAD:OpenSim/Services/LLLoginService/LLLoginService.cs - } -======= } ->>>>>>> master:OpenSim/Services/LLLoginService/LLLoginService.cs dest = destination; if (success) return aCircuit; -- cgit v1.1 From 32ccc19a6238b2b0f4fa81efdc3115dd58578b00 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sun, 8 Aug 2010 18:56:47 -0700 Subject: Make fallbacks work, the destination was never actually updated with the fallback details. --- OpenSim/Services/LLLoginService/LLLoginService.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index f9fe7f0..2674eef 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -344,9 +344,10 @@ namespace OpenSim.Services.LLLoginService // // Instantiate/get the simulation interface and launch an agent at the destination // - string reason = string.Empty; - AgentCircuitData aCircuit = LaunchAgentAtGrid(gatekeeper, destination, account, avatar, session, secureSession, position, where, clientVersion, clientIP, out where, out reason); - + string reason = string.Empty; + GridRegion dest; + AgentCircuitData aCircuit = LaunchAgentAtGrid(gatekeeper, destination, account, avatar, session, secureSession, position, where, clientVersion, clientIP, out where, out reason, out dest); + destination = dest; if (aCircuit == null) { m_PresenceService.LogoutAgent(session); @@ -605,7 +606,7 @@ namespace OpenSim.Services.LLLoginService } protected AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarData avatar, - UUID session, UUID secureSession, Vector3 position, string currentWhere, string viewer, IPEndPoint clientIP, out string where, out string reason) + UUID session, UUID secureSession, Vector3 position, string currentWhere, string viewer, IPEndPoint clientIP, out string where, out string reason, out GridRegion dest) { where = currentWhere; ISimulationService simConnector = null; @@ -690,8 +691,8 @@ namespace OpenSim.Services.LLLoginService } } } - } - + } + dest = destination; if (success) return aCircuit; else -- cgit v1.1 From 0f9eebdfb1e948bc1ffb148322e668b5a2f560a6 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 10 Aug 2010 03:52:00 +0200 Subject: Change prejump from hardcoded true to default true so it can be disabled. It completely destroys roleplay jumping --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 06bbe32..05036f1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -726,8 +726,7 @@ namespace OpenSim.Region.Framework.Scenes //Animation states m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); // TODO: Change default to true once the feature is supported - m_usePreJump = startupConfig.GetBoolean("enableprejump", false); - m_usePreJump = true; // Above line fails!? + m_usePreJump = startupConfig.GetBoolean("enableprejump", true); m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); if (RegionInfo.NonphysPrimMax > 0) { -- cgit v1.1 From f0bad66d414e1c42875bc82d533cc7cd66af8a89 Mon Sep 17 00:00:00 2001 From: meta7 Date: Mon, 9 Aug 2010 23:34:37 -0700 Subject: For my own sanity, fix a bug in xengine --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 916e27f..0f274f3 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1091,7 +1091,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine return false; uuids = m_PrimObjects[localID]; - } + foreach (UUID itemID in uuids) { @@ -1109,6 +1109,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine result = true; } } + } return result; } -- cgit v1.1 From eb5c508f8b396ea65d5d80c763aaea70a46c4653 Mon Sep 17 00:00:00 2001 From: meta7 Date: Mon, 9 Aug 2010 23:35:40 -0700 Subject: Add a DebuggerSafe option to the ini to help with debugging in visual studio. This essentially silences exceptions in the script engine. Disabled by default, naturally. --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 8 ++++++-- .../Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 11 ++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 68b645e..71d63bb 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 protected int m_notecardLineReadCharsMax = 255; protected int m_scriptConsoleChannel = 0; protected bool m_scriptConsoleChannelEnabled = false; + protected bool m_debuggerSafe = false; protected IUrlModule m_UrlModule = null; protected Dictionary m_userInfoCache = new Dictionary(); @@ -110,6 +111,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host = host; m_localID = localID; m_itemID = itemID; + m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); m_ScriptDelayFactor = m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); @@ -3220,13 +3222,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return m_host.OwnerID.ToString(); } - [DebuggerNonUserCode] public void llInstantMessage(string user, string message) { UUID result; if (!UUID.TryParse(user, out result)) { - throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user)); + if (!m_debuggerSafe) + { + throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user)); + } return; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 80b021f..73e87b5 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -129,6 +129,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; internal float m_ScriptDelayFactor = 1.0f; internal float m_ScriptDistanceFactor = 1.0f; + internal bool m_debuggerSafe = false; internal Dictionary m_FunctionPerms = new Dictionary(); public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) @@ -137,6 +138,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host = host; m_localID = localID; m_itemID = itemID; + m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) m_OSFunctionsEnabled = true; @@ -195,7 +197,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void OSSLError(string msg) { - throw new Exception("OSSL Runtime Error: " + msg); + if (m_debuggerSafe) + { + OSSLShoutError(msg); + } + else + { + throw new Exception("OSSL Runtime Error: " + msg); + } } private void InitLSL() -- cgit v1.1 From 1ead2ed5eea379c500d2657e7bed8908b376e336 Mon Sep 17 00:00:00 2001 From: meta7 Date: Tue, 10 Aug 2010 09:07:17 -0700 Subject: Add a stack trace to the error output on the recursive read lock warning on my RWlocks. Whilst recursive locks are safe, coupled with other issues we're experiencing with the TaskInventoryDictionary it implies that somewhere the lock is not being freed possibly due to a merge error somewhere, and thus it needs to be looked into. --- OpenSim/Framework/TaskInventoryDictionary.cs | 14 ++ .../Region/Framework/Scenes/SceneObjectGroup.cs | 218 +++++++++++---------- 2 files changed, 128 insertions(+), 104 deletions(-) diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 4b9a509..6b65fba 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.Threading; using System.Reflection; using System.Xml; +using System.Diagnostics; using System.Xml.Schema; using System.Xml.Serialization; using log4net; @@ -90,6 +91,19 @@ namespace OpenSim.Framework if (m_itemLock.RecursiveReadCount > 0) { m_log.Error("[TaskInventoryDictionary] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); + try + { + StackTrace stackTrace = new StackTrace(); // get call stack + StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) + + // write call stack method names + foreach (StackFrame stackFrame in stackFrames) + { + m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name); // write method name + } + } + catch + {} m_itemLock.ExitReadLock(); } if (m_itemLock.RecursiveWriteCount > 0) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 3c3f4b7..4f6bc52 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Diagnostics; using System.Threading; using System.Xml; using System.Xml.Serialization; @@ -138,6 +139,15 @@ namespace OpenSim.Region.Framework.Scenes m_log.Error("[SceneObjectGroup.m_parts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue."); try { + StackTrace stackTrace = new StackTrace(); // get call stack + StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) + + // write call stack method names + foreach (StackFrame stackFrame in stackFrames) + { + m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name); // write method name + } + m_partsLock.ExitReadLock(); } catch { } // Ignore errors, to allow resync @@ -317,7 +327,7 @@ namespace OpenSim.Region.Framework.Scenes private bool m_scriptListens_notAtTarget = false; private bool m_scriptListens_atRotTarget = false; - private bool m_scriptListens_notAtRotTarget = false; + private bool m_scriptListens_notAtRotTarget = false; public bool m_dupeInProgress = false; internal Dictionary m_savedScriptState = null; @@ -475,21 +485,21 @@ namespace OpenSim.Region.Framework.Scenes { part.IgnoreUndoUpdate = false; part.StoreUndoState(UndoType.STATE_GROUP_POSITION); - part.GroupPosition = val; - if (!m_dupeInProgress) - { - part.TriggerScriptChangedEvent(Changed.POSITION); + part.GroupPosition = val; + if (!m_dupeInProgress) + { + part.TriggerScriptChangedEvent(Changed.POSITION); + } + } + if (!m_dupeInProgress) + { + foreach (ScenePresence av in m_linkedAvatars) + { + Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; + av.AbsolutePosition += offset; + av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition + av.SendFullUpdateToAllClients(); } - } - if (!m_dupeInProgress) - { - foreach (ScenePresence av in m_linkedAvatars) - { - Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; - av.AbsolutePosition += offset; - av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition - av.SendFullUpdateToAllClients(); - } } //if (m_rootPart.PhysActor != null) @@ -1805,95 +1815,95 @@ namespace OpenSim.Region.Framework.Scenes /// True if the duplicate will immediately be in the scene, false otherwise /// public SceneObjectGroup Copy(bool userExposed) - { - SceneObjectGroup dupe; - try - { - m_dupeInProgress = true; - dupe = (SceneObjectGroup)MemberwiseClone(); - dupe.m_isBackedUp = false; - dupe.m_parts = new Dictionary(); - - // Warning, The following code related to previousAttachmentStatus is needed so that clones of - // attachments do not bordercross while they're being duplicated. This is hacktastic! - // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! - // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state - // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, - // then restore it's attachment state - - // This is only necessary when userExposed is false! - - bool previousAttachmentStatus = dupe.RootPart.IsAttachment; - - if (!userExposed) - dupe.RootPart.IsAttachment = true; - - dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); - - if (!userExposed) - { - dupe.RootPart.IsAttachment = previousAttachmentStatus; - } - - dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); - dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; - - if (userExposed) - dupe.m_rootPart.TrimPermissions(); - - /// may need to create a new Physics actor. - if (dupe.RootPart.PhysActor != null && userExposed) - { - PrimitiveBaseShape pbs = dupe.RootPart.Shape; - - dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( - dupe.RootPart.Name, - pbs, - dupe.RootPart.AbsolutePosition, - dupe.RootPart.Scale, - dupe.RootPart.RotationOffset, - dupe.RootPart.PhysActor.IsPhysical); - - dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; - dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); - } - - List partList; - - lockPartsForRead(true); - - partList = new List(m_parts.Values); - - lockPartsForRead(false); - - partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) - { - return p1.LinkNum.CompareTo(p2.LinkNum); - } - ); - - foreach (SceneObjectPart part in partList) - { - if (part.UUID != m_rootPart.UUID) - { - SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); - - newPart.LinkNum = part.LinkNum; - } - } - - if (userExposed) - { - dupe.UpdateParentIDs(); - dupe.HasGroupChanged = true; - dupe.AttachToBackup(); - - ScheduleGroupForFullUpdate(); - } - } - finally - { - m_dupeInProgress = false; + { + SceneObjectGroup dupe; + try + { + m_dupeInProgress = true; + dupe = (SceneObjectGroup)MemberwiseClone(); + dupe.m_isBackedUp = false; + dupe.m_parts = new Dictionary(); + + // Warning, The following code related to previousAttachmentStatus is needed so that clones of + // attachments do not bordercross while they're being duplicated. This is hacktastic! + // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! + // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state + // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, + // then restore it's attachment state + + // This is only necessary when userExposed is false! + + bool previousAttachmentStatus = dupe.RootPart.IsAttachment; + + if (!userExposed) + dupe.RootPart.IsAttachment = true; + + dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); + + if (!userExposed) + { + dupe.RootPart.IsAttachment = previousAttachmentStatus; + } + + dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); + dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; + + if (userExposed) + dupe.m_rootPart.TrimPermissions(); + + /// may need to create a new Physics actor. + if (dupe.RootPart.PhysActor != null && userExposed) + { + PrimitiveBaseShape pbs = dupe.RootPart.Shape; + + dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( + dupe.RootPart.Name, + pbs, + dupe.RootPart.AbsolutePosition, + dupe.RootPart.Scale, + dupe.RootPart.RotationOffset, + dupe.RootPart.PhysActor.IsPhysical); + + dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; + dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); + } + + List partList; + + lockPartsForRead(true); + + partList = new List(m_parts.Values); + + lockPartsForRead(false); + + partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) + { + return p1.LinkNum.CompareTo(p2.LinkNum); + } + ); + + foreach (SceneObjectPart part in partList) + { + if (part.UUID != m_rootPart.UUID) + { + SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); + + newPart.LinkNum = part.LinkNum; + } + } + + if (userExposed) + { + dupe.UpdateParentIDs(); + dupe.HasGroupChanged = true; + dupe.AttachToBackup(); + + ScheduleGroupForFullUpdate(); + } + } + finally + { + m_dupeInProgress = false; } return dupe; } -- cgit v1.1 From d98d5ee6be233cf644be5ee1011c4a7f4b86ae46 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 10 Aug 2010 19:42:18 +0100 Subject: Remove windows line endinge --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 208 ++++++++++----------- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 28 +-- 2 files changed, 118 insertions(+), 118 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 3c3f4b7..a862fa2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -317,7 +317,7 @@ namespace OpenSim.Region.Framework.Scenes private bool m_scriptListens_notAtTarget = false; private bool m_scriptListens_atRotTarget = false; - private bool m_scriptListens_notAtRotTarget = false; + private bool m_scriptListens_notAtRotTarget = false; public bool m_dupeInProgress = false; internal Dictionary m_savedScriptState = null; @@ -475,21 +475,21 @@ namespace OpenSim.Region.Framework.Scenes { part.IgnoreUndoUpdate = false; part.StoreUndoState(UndoType.STATE_GROUP_POSITION); - part.GroupPosition = val; - if (!m_dupeInProgress) - { - part.TriggerScriptChangedEvent(Changed.POSITION); + part.GroupPosition = val; + if (!m_dupeInProgress) + { + part.TriggerScriptChangedEvent(Changed.POSITION); + } + } + if (!m_dupeInProgress) + { + foreach (ScenePresence av in m_linkedAvatars) + { + Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; + av.AbsolutePosition += offset; + av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition + av.SendFullUpdateToAllClients(); } - } - if (!m_dupeInProgress) - { - foreach (ScenePresence av in m_linkedAvatars) - { - Vector3 offset = m_parts[av.LinkedPrim].GetWorldPosition() - av.ParentPosition; - av.AbsolutePosition += offset; - av.ParentPosition = m_parts[av.LinkedPrim].GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition - av.SendFullUpdateToAllClients(); - } } //if (m_rootPart.PhysActor != null) @@ -1805,95 +1805,95 @@ namespace OpenSim.Region.Framework.Scenes /// True if the duplicate will immediately be in the scene, false otherwise /// public SceneObjectGroup Copy(bool userExposed) - { - SceneObjectGroup dupe; - try - { - m_dupeInProgress = true; - dupe = (SceneObjectGroup)MemberwiseClone(); - dupe.m_isBackedUp = false; - dupe.m_parts = new Dictionary(); - - // Warning, The following code related to previousAttachmentStatus is needed so that clones of - // attachments do not bordercross while they're being duplicated. This is hacktastic! - // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! - // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state - // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, - // then restore it's attachment state - - // This is only necessary when userExposed is false! - - bool previousAttachmentStatus = dupe.RootPart.IsAttachment; - - if (!userExposed) - dupe.RootPart.IsAttachment = true; - - dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); - - if (!userExposed) - { - dupe.RootPart.IsAttachment = previousAttachmentStatus; - } - - dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); - dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; - - if (userExposed) - dupe.m_rootPart.TrimPermissions(); - - /// may need to create a new Physics actor. - if (dupe.RootPart.PhysActor != null && userExposed) - { - PrimitiveBaseShape pbs = dupe.RootPart.Shape; - - dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( - dupe.RootPart.Name, - pbs, - dupe.RootPart.AbsolutePosition, - dupe.RootPart.Scale, - dupe.RootPart.RotationOffset, - dupe.RootPart.PhysActor.IsPhysical); - - dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; - dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); - } - - List partList; - - lockPartsForRead(true); - - partList = new List(m_parts.Values); - - lockPartsForRead(false); - - partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) - { - return p1.LinkNum.CompareTo(p2.LinkNum); - } - ); - - foreach (SceneObjectPart part in partList) - { - if (part.UUID != m_rootPart.UUID) - { - SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); - - newPart.LinkNum = part.LinkNum; - } - } - - if (userExposed) - { - dupe.UpdateParentIDs(); - dupe.HasGroupChanged = true; - dupe.AttachToBackup(); - - ScheduleGroupForFullUpdate(); - } - } - finally - { - m_dupeInProgress = false; + { + SceneObjectGroup dupe; + try + { + m_dupeInProgress = true; + dupe = (SceneObjectGroup)MemberwiseClone(); + dupe.m_isBackedUp = false; + dupe.m_parts = new Dictionary(); + + // Warning, The following code related to previousAttachmentStatus is needed so that clones of + // attachments do not bordercross while they're being duplicated. This is hacktastic! + // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! + // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state + // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, + // then restore it's attachment state + + // This is only necessary when userExposed is false! + + bool previousAttachmentStatus = dupe.RootPart.IsAttachment; + + if (!userExposed) + dupe.RootPart.IsAttachment = true; + + dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); + + if (!userExposed) + { + dupe.RootPart.IsAttachment = previousAttachmentStatus; + } + + dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); + dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; + + if (userExposed) + dupe.m_rootPart.TrimPermissions(); + + /// may need to create a new Physics actor. + if (dupe.RootPart.PhysActor != null && userExposed) + { + PrimitiveBaseShape pbs = dupe.RootPart.Shape; + + dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( + dupe.RootPart.Name, + pbs, + dupe.RootPart.AbsolutePosition, + dupe.RootPart.Scale, + dupe.RootPart.RotationOffset, + dupe.RootPart.PhysActor.IsPhysical); + + dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; + dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); + } + + List partList; + + lockPartsForRead(true); + + partList = new List(m_parts.Values); + + lockPartsForRead(false); + + partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) + { + return p1.LinkNum.CompareTo(p2.LinkNum); + } + ); + + foreach (SceneObjectPart part in partList) + { + if (part.UUID != m_rootPart.UUID) + { + SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); + + newPart.LinkNum = part.LinkNum; + } + } + + if (userExposed) + { + dupe.UpdateParentIDs(); + dupe.HasGroupChanged = true; + dupe.AttachToBackup(); + + ScheduleGroupForFullUpdate(); + } + } + finally + { + m_dupeInProgress = false; } return dupe; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 77581af..277384e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -718,20 +718,20 @@ namespace OpenSim.Region.Framework.Scenes // Tell the physics engines that this prim changed. m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); - } - - if (!m_parentGroup.m_dupeInProgress) - { - List avs = ParentGroup.GetLinkedAvatars(); - foreach (ScenePresence av in avs) - { - if (av.LinkedPrim == m_uuid) - { - Vector3 offset = (m_offsetPosition - oldpos); - av.OffsetPosition += offset; - av.SendFullUpdateToAllClients(); - } - } + } + + if (!m_parentGroup.m_dupeInProgress) + { + List avs = ParentGroup.GetLinkedAvatars(); + foreach (ScenePresence av in avs) + { + if (av.LinkedPrim == m_uuid) + { + Vector3 offset = (m_offsetPosition - oldpos); + av.OffsetPosition += offset; + av.SendFullUpdateToAllClients(); + } + } } } TriggerScriptChangedEvent(Changed.POSITION); -- cgit v1.1 From 383ee0d647df245dcb933e71f2b4bcdfbc026a15 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 10 Aug 2010 19:48:45 +0100 Subject: Remove 4000+ DOS line endings. Grrr! --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 8664 +++++++++++----------- 1 file changed, 4332 insertions(+), 4332 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index fc8e0d7..9d95324 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1,4332 +1,4332 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Xml; -using System.Collections.Generic; -using System.Reflection; -using System.Timers; -using OpenMetaverse; -using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Client; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes.Animation; -using OpenSim.Region.Framework.Scenes.Types; -using OpenSim.Region.Physics.Manager; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; -using OpenSim.Services.Interfaces; - -namespace OpenSim.Region.Framework.Scenes -{ - enum ScriptControlled : uint - { - CONTROL_ZERO = 0, - CONTROL_FWD = 1, - CONTROL_BACK = 2, - CONTROL_LEFT = 4, - CONTROL_RIGHT = 8, - CONTROL_UP = 16, - CONTROL_DOWN = 32, - CONTROL_ROT_LEFT = 256, - CONTROL_ROT_RIGHT = 512, - CONTROL_LBUTTON = 268435456, - CONTROL_ML_LBUTTON = 1073741824 - } - - struct ScriptControllers - { - public UUID itemID; - public ScriptControlled ignoreControls; - public ScriptControlled eventControls; - } - - public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); - - public class ScenePresence : EntityBase, ISceneEntity - { -// ~ScenePresence() -// { -// m_log.Debug("[ScenePresence] Destructor called"); -// } - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; -// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); - private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); - private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); - - /// - /// Experimentally determined "fudge factor" to make sit-target positions - /// the same as in SecondLife. Fudge factor was tested for 36 different - /// test cases including prims of type box, sphere, cylinder, and torus, - /// with varying parameters for sit target location, prim size, prim - /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis - /// issue #1716 - /// -// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); - // Value revised by KF 091121 by comparison with SL. - private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); - - public UUID currentParcelUUID = UUID.Zero; - - private ISceneViewer m_sceneViewer; - - /// - /// The animator for this avatar - /// - public ScenePresenceAnimator Animator - { - get { return m_animator; } - } - protected ScenePresenceAnimator m_animator; - - /// - /// The scene objects attached to this avatar. Do not change this list directly - use methods such as - /// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it. - /// - public List Attachments - { - get { return m_attachments; } - } - protected List m_attachments = new List(); - - private Dictionary scriptedcontrols = new Dictionary(); - private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; - private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; - private bool MouseDown = false; - private SceneObjectGroup proxyObjectGroup; - //private SceneObjectPart proxyObjectPart = null; - public Vector3 lastKnownAllowedPosition; - public bool sentMessageAboutRestrictedParcelFlyingDown; - public Vector4 CollisionPlane = Vector4.UnitW; - - private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation - private Vector3 m_avUnscriptedSitPos; // for non-scripted prims - private Vector3 m_lastPosition; - private Vector3 m_lastWorldPosition; - private Quaternion m_lastRotation; - private Vector3 m_lastVelocity; - //private int m_lastTerseSent; - - private bool m_updateflag; - private byte m_movementflag; - private Vector3? m_forceToApply; - private uint m_requestedSitTargetID; - private UUID m_requestedSitTargetUUID; - public bool SitGround = false; - - private SendCourseLocationsMethod m_sendCourseLocationsMethod; - - private bool m_startAnimationSet; - - //private Vector3 m_requestedSitOffset = new Vector3(); - - private Vector3 m_LastFinitePos; - - private float m_sitAvatarHeight = 2.0f; - - private int m_godLevel; - private int m_userLevel; - - private bool m_invulnerable = true; - - private Vector3 m_lastChildAgentUpdatePosition; - private Vector3 m_lastChildAgentUpdateCamPosition; - - private int m_perfMonMS; - - private bool m_setAlwaysRun; - private bool m_forceFly; - private bool m_flyDisabled; - - private float m_speedModifier = 1.0f; - - private Quaternion m_bodyRot= Quaternion.Identity; - - private Quaternion m_bodyRotPrevious = Quaternion.Identity; - - private const int LAND_VELOCITYMAG_MAX = 12; - - public bool IsRestrictedToRegion; - - public string JID = String.Empty; - - private float m_health = 100f; - - // Default AV Height - private float m_avHeight = 127.0f; - - protected RegionInfo m_regionInfo; - protected ulong crossingFromRegion; - - private readonly Vector3[] Dir_Vectors = new Vector3[11]; - private bool m_isNudging = false; - - // Position of agent's camera in world (region cordinates) - protected Vector3 m_CameraCenter; - protected Vector3 m_lastCameraCenter; - - protected Timer m_reprioritization_timer; - protected bool m_reprioritizing; - protected bool m_reprioritization_called; - - // Use these three vectors to figure out what the agent is looking at - // Convert it to a Matrix and/or Quaternion - protected Vector3 m_CameraAtAxis; - protected Vector3 m_CameraLeftAxis; - protected Vector3 m_CameraUpAxis; - private AgentManager.ControlFlags m_AgentControlFlags; - private Quaternion m_headrotation = Quaternion.Identity; - private byte m_state; - - //Reuse the Vector3 instead of creating a new one on the UpdateMovement method -// private Vector3 movementvector; - - private bool m_autopilotMoving; - private Vector3 m_autoPilotTarget; - private bool m_sitAtAutoTarget; - private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit - - private string m_nextSitAnimation = String.Empty; - - //PauPaw:Proper PID Controler for autopilot************ - private bool m_moveToPositionInProgress; - private Vector3 m_moveToPositionTarget; - private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - - private bool m_followCamAuto; - - private int m_movementUpdateCount; - private int m_lastColCount = -1; //KF: Look for Collision chnages - private int m_updateCount = 0; //KF: Update Anims for a while - private static readonly int UPDATE_COUNT = 10; // how many frames to update for - private const int NumMovementsBetweenRayCast = 5; - private List m_lastColliders = new List(); - - private bool CameraConstraintActive; - //private int m_moveToPositionStateStatus; - //***************************************************** - - // Agent's Draw distance. - protected float m_DrawDistance; - - protected AvatarAppearance m_appearance; - - // neighbouring regions we have enabled a child agent in - // holds the seed cap for the child agent in that region - private Dictionary m_knownChildRegions = new Dictionary(); - - /// - /// Implemented Control Flags - /// - private enum Dir_ControlFlags - { - DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, - DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, - DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, - DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, - DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, - DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, - DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, - DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, - DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, - DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, - DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG - } - - /// - /// Position at which a significant movement was made - /// - private Vector3 posLastSignificantMove; - - // For teleports and crossings callbacks - string m_callbackURI; - UUID m_originRegionID; - - ulong m_rootRegionHandle; - - /// - /// Script engines present in the scene - /// - private IScriptModule[] m_scriptEngines; - - #region Properties - - /// - /// Physical scene representation of this Avatar. - /// - public PhysicsActor PhysicsActor - { - set { m_physicsActor = value; } - get { return m_physicsActor; } - } - - public byte MovementFlag - { - set { m_movementflag = value; } - get { return m_movementflag; } - } - - public bool Updated - { - set { m_updateflag = value; } - get { return m_updateflag; } - } - - public bool Invulnerable - { - set { m_invulnerable = value; } - get { return m_invulnerable; } - } - - public int UserLevel - { - get { return m_userLevel; } - } - - public int GodLevel - { - get { return m_godLevel; } - } - - public ulong RegionHandle - { - get { return m_rootRegionHandle; } - } - - public Vector3 CameraPosition - { - get { return m_CameraCenter; } - } - - public Quaternion CameraRotation - { - get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); } - } - - public Vector3 CameraAtAxis - { - get { return m_CameraAtAxis; } - } - - public Vector3 CameraLeftAxis - { - get { return m_CameraLeftAxis; } - } - - public Vector3 CameraUpAxis - { - get { return m_CameraUpAxis; } - } - - public Vector3 Lookat - { - get - { - Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0); - - if (a == Vector3.Zero) - return a; - - return Util.GetNormalizedVector(a); - } - } - - private readonly string m_firstname; - - public string Firstname - { - get { return m_firstname; } - } - - private readonly string m_lastname; - - public string Lastname - { - get { return m_lastname; } - } - - private string m_grouptitle; - - public string Grouptitle - { - get { return m_grouptitle; } - set { m_grouptitle = value; } - } - - public float DrawDistance - { - get { return m_DrawDistance; } - } - - protected bool m_allowMovement = true; - - public bool AllowMovement - { - get { return m_allowMovement; } - set { m_allowMovement = value; } - } - - public bool SetAlwaysRun - { - get - { - if (PhysicsActor != null) - { - return PhysicsActor.SetAlwaysRun; - } - else - { - return m_setAlwaysRun; - } - } - set - { - m_setAlwaysRun = value; - if (PhysicsActor != null) - { - PhysicsActor.SetAlwaysRun = value; - } - } - } - - public byte State - { - get { return m_state; } - set { m_state = value; } - } - - public uint AgentControlFlags - { - get { return (uint)m_AgentControlFlags; } - set { m_AgentControlFlags = (AgentManager.ControlFlags)value; } - } - - /// - /// This works out to be the ClientView object associated with this avatar, or it's client connection manager - /// - private IClientAPI m_controllingClient; - - protected PhysicsActor m_physicsActor; - - /// - /// The client controlling this presence - /// - public IClientAPI ControllingClient - { - get { return m_controllingClient; } - } - - public IClientCore ClientView - { - get { return (IClientCore) m_controllingClient; } - } - - protected Vector3 m_parentPosition; - public Vector3 ParentPosition - { - get { return m_parentPosition; } - set { m_parentPosition = value; } - } - - /// - /// Position of this avatar relative to the region the avatar is in - /// - public override Vector3 AbsolutePosition - { - get - { - PhysicsActor actor = m_physicsActor; -// if (actor != null) - if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting! - m_pos = actor.Position; - - // If we're sitting, we need to update our position - if (m_parentID != 0) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); - if (part != null) - m_parentPosition = part.AbsolutePosition; - } - - return m_parentPosition + m_pos; - } - set - { - PhysicsActor actor = m_physicsActor; - if (actor != null) - { - try - { - lock (m_scene.SyncRoot) - m_physicsActor.Position = value; - } - catch (Exception e) - { - m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message); - } - } - - if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting! - m_pos = value; - m_parentPosition = Vector3.Zero; - } - } - - public Vector3 OffsetPosition - { - get { return m_pos; } - set { m_pos = value; } - } - - /// - /// Current velocity of the avatar. - /// - public override Vector3 Velocity - { - get - { - PhysicsActor actor = m_physicsActor; - if (actor != null) - m_velocity = actor.Velocity; - - return m_velocity; - } - set - { - PhysicsActor actor = m_physicsActor; - if (actor != null) - { - try - { - lock (m_scene.SyncRoot) - actor.Velocity = value; - } - catch (Exception e) - { - m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message); - } - } - - m_velocity = value; - } - } - - public Quaternion OffsetRotation - { - get { return m_offsetRotation; } - set { m_offsetRotation = value; } - } - - public Quaternion Rotation - { - get { - if (m_parentID != 0) - { - if (m_offsetRotation != null) - { - return m_offsetRotation; - } - else - { - return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - } - - } - else - { - return m_bodyRot; - } - } - set { - m_bodyRot = value; - if (m_parentID != 0) - { - m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - } - } - } - - public Quaternion PreviousRotation - { - get { return m_bodyRotPrevious; } - set { m_bodyRotPrevious = value; } - } - - /// - /// If this is true, agent doesn't have a representation in this scene. - /// this is an agent 'looking into' this scene from a nearby scene(region) - /// - /// if False, this agent has a representation in this scene - /// - private bool m_isChildAgent = true; - - public bool IsChildAgent - { - get { return m_isChildAgent; } - set { m_isChildAgent = value; } - } - - private uint m_parentID; - - - private UUID m_linkedPrim; - - public uint ParentID - { - get { return m_parentID; } - set { m_parentID = value; } - } - - public UUID LinkedPrim - { - get { return m_linkedPrim; } - set { m_linkedPrim = value; } - } - - public float Health - { - get { return m_health; } - set { m_health = value; } - } - - /// - /// These are the region handles known by the avatar. - /// - public List KnownChildRegionHandles - { - get - { - if (m_knownChildRegions.Count == 0) - return new List(); - else - return new List(m_knownChildRegions.Keys); - } - } - - public Dictionary KnownRegions - { - get { return m_knownChildRegions; } - set - { - m_knownChildRegions = value; - } - } - - public ISceneViewer SceneViewer - { - get { return m_sceneViewer; } - } - - public void AdjustKnownSeeds() - { - Dictionary seeds; - - if (Scene.CapsModule != null) - seeds = Scene.CapsModule.GetChildrenSeeds(UUID); - else - seeds = new Dictionary(); - - List old = new List(); - foreach (ulong handle in seeds.Keys) - { - uint x, y; - Utils.LongToUInts(handle, out x, out y); - x = x / Constants.RegionSize; - y = y / Constants.RegionSize; - if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) - { - old.Add(handle); - } - } - DropOldNeighbours(old); - - if (Scene.CapsModule != null) - Scene.CapsModule.SetChildrenSeed(UUID, seeds); - - KnownRegions = seeds; - //m_log.Debug(" ++++++++++AFTER+++++++++++++ "); - //DumpKnownRegions(); - } - - public void DumpKnownRegions() - { - m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================"); - foreach (KeyValuePair kvp in KnownRegions) - { - uint x, y; - Utils.LongToUInts(kvp.Key, out x, out y); - x = x / Constants.RegionSize; - y = y / Constants.RegionSize; - m_log.Info(" >> "+x+", "+y+": "+kvp.Value); - } - } - - private bool m_inTransit; - private bool m_mouseLook; - private bool m_leftButtonDown; - - public bool IsInTransit - { - get { return m_inTransit; } - set { m_inTransit = value; } - } - - public float SpeedModifier - { - get { return m_speedModifier; } - set { m_speedModifier = value; } - } - - public bool ForceFly - { - get { return m_forceFly; } - set { m_forceFly = value; } - } - - public bool FlyDisabled - { - get { return m_flyDisabled; } - set { m_flyDisabled = value; } - } - - public string Viewer - { - get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; } - } - - #endregion - - #region Constructor(s) - - public ScenePresence() - { - m_sendCourseLocationsMethod = SendCoarseLocationsDefault; - CreateSceneViewer(); - m_animator = new ScenePresenceAnimator(this); - } - - private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() - { - m_rootRegionHandle = reginfo.RegionHandle; - m_controllingClient = client; - m_firstname = m_controllingClient.FirstName; - m_lastname = m_controllingClient.LastName; - m_name = String.Format("{0} {1}", m_firstname, m_lastname); - m_scene = world; - m_uuid = client.AgentId; - m_regionInfo = reginfo; - m_localId = m_scene.AllocateLocalId(); - - UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); - - if (account != null) - m_userLevel = account.UserLevel; - - IGroupsModule gm = m_scene.RequestModuleInterface(); - if (gm != null) - m_grouptitle = gm.GetGroupTitle(m_uuid); - - m_scriptEngines = m_scene.RequestModuleInterfaces(); - - AbsolutePosition = posLastSignificantMove = m_CameraCenter = - m_lastCameraCenter = m_controllingClient.StartPos; - - m_reprioritization_timer = new Timer(world.ReprioritizationInterval); - m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize); - m_reprioritization_timer.AutoReset = false; - - AdjustKnownSeeds(); - Animator.TrySetMovementAnimation("STAND"); - // we created a new ScenePresence (a new child agent) in a fresh region. - // Request info about all the (root) agents in this region - // Note: This won't send data *to* other clients in that region (children don't send) - SendInitialFullUpdateToAllClients(); - RegisterToEvents(); - if (m_controllingClient != null) - { - m_controllingClient.ProcessPendingPackets(); - } - SetDirectionVectors(); - } - - public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams, - AvatarWearable[] wearables) - : this(client, world, reginfo) - { - m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams); - } - - public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance) - : this(client, world, reginfo) - { - m_appearance = appearance; - } - - private void CreateSceneViewer() - { - m_sceneViewer = new SceneViewer(this); - } - - public void RegisterToEvents() - { - m_controllingClient.OnRequestWearables += SendWearables; - m_controllingClient.OnSetAppearance += SetAppearance; - m_controllingClient.OnCompleteMovementToRegion += CompleteMovement; - //m_controllingClient.OnCompleteMovementToRegion += SendInitialData; - m_controllingClient.OnAgentUpdate += HandleAgentUpdate; - m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit; - m_controllingClient.OnAgentSit += HandleAgentSit; - m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; - m_controllingClient.OnStartAnim += HandleStartAnim; - m_controllingClient.OnStopAnim += HandleStopAnim; - m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls; - m_controllingClient.OnAutoPilotGo += DoAutoPilot; - m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition); - - // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); - // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); - } - - private void SetDirectionVectors() - { - Dir_Vectors[0] = Vector3.UnitX; //FORWARD - Dir_Vectors[1] = -Vector3.UnitX; //BACK - Dir_Vectors[2] = Vector3.UnitY; //LEFT - Dir_Vectors[3] = -Vector3.UnitY; //RIGHT - Dir_Vectors[4] = Vector3.UnitZ; //UP - Dir_Vectors[5] = -Vector3.UnitZ; //DOWN - Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE - Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE - Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE - Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE - Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge - } - - private Vector3[] GetWalkDirectionVectors() - { - Vector3[] vector = new Vector3[11]; - vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD - vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK - vector[2] = Vector3.UnitY; //LEFT - vector[3] = -Vector3.UnitY; //RIGHT - vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP - vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN - vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE - vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE - vector[8] = Vector3.UnitY; //LEFT_NUDGE - vector[9] = -Vector3.UnitY; //RIGHT_NUDGE - vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE - return vector; - } - - private bool[] GetDirectionIsNudge() - { - bool[] isNudge = new bool[11]; - isNudge[0] = false; //FORWARD - isNudge[1] = false; //BACK - isNudge[2] = false; //LEFT - isNudge[3] = false; //RIGHT - isNudge[4] = false; //UP - isNudge[5] = false; //DOWN - isNudge[6] = true; //FORWARD_NUDGE - isNudge[7] = true; //BACK_NUDGE - isNudge[8] = true; //LEFT_NUDGE - isNudge[9] = true; //RIGHT_NUDGE - isNudge[10] = true; //DOWN_Nudge - return isNudge; - } - - - #endregion - - public uint GenerateClientFlags(UUID ObjectID) - { - return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID); - } - - /// - /// Send updates to the client about prims which have been placed on the update queue. We don't - /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent - /// timestamp has already been sent. - /// - public void SendPrimUpdates() - { - m_perfMonMS = Util.EnvironmentTickCount(); - - m_sceneViewer.SendPrimUpdates(); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - #region Status Methods - - /// - /// This turns a child agent, into a root agent - /// This is called when an agent teleports into a region, or if an - /// agent crosses into this region from a neighbor over the border - /// - public void MakeRootAgent(Vector3 pos, bool isFlying) - { - m_log.DebugFormat( - "[SCENE]: Upgrading child to root agent for {0} in {1}", - Name, m_scene.RegionInfo.RegionName); - - //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); - - IGroupsModule gm = m_scene.RequestModuleInterface(); - if (gm != null) - m_grouptitle = gm.GetGroupTitle(m_uuid); - - m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; - m_scene.SetRootAgentScene(m_uuid); - - // Moved this from SendInitialData to ensure that m_appearance is initialized - // before the inventory is processed in MakeRootAgent. This fixes a race condition - // related to the handling of attachments - //m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); - if (m_scene.TestBorderCross(pos, Cardinals.E)) - { - Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); - pos.X = crossedBorder.BorderLine.Z - 1; - } - - if (m_scene.TestBorderCross(pos, Cardinals.N)) - { - Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); - pos.Y = crossedBorder.BorderLine.Z - 1; - } - - //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet. - //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent, - //they'll bypass the landing point. But I can't think of any decent way of fixing this. - if (KnownChildRegionHandles.Count == 0) - { - ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); - if (land != null) - { - //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. - if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) - { - pos = land.LandData.UserLocation; - } - } - } - - if (pos.X < 0 || pos.Y < 0 || pos.Z < 0) - { - Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128); - - if (pos.X < 0) - { - emergencyPos.X = (int)Constants.RegionSize + pos.X; - if (!(pos.Y < 0)) - emergencyPos.Y = pos.Y; - if (!(pos.Z < 0)) - emergencyPos.Z = pos.Z; - } - if (pos.Y < 0) - { - emergencyPos.Y = (int)Constants.RegionSize + pos.Y; - if (!(pos.X < 0)) - emergencyPos.X = pos.X; - if (!(pos.Z < 0)) - emergencyPos.Z = pos.Z; - } - if (pos.Z < 0) - { - emergencyPos.Z = 128; - if (!(pos.Y < 0)) - emergencyPos.Y = pos.Y; - if (!(pos.X < 0)) - emergencyPos.X = pos.X; - } - } - - if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) - { - m_log.WarnFormat( - "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", - pos, Name, UUID); - - if (pos.X < 0f) pos.X = 0f; - if (pos.Y < 0f) pos.Y = 0f; - if (pos.Z < 0f) pos.Z = 0f; - } - - float localAVHeight = 1.56f; - if (m_avHeight != 127.0f) - { - localAVHeight = m_avHeight; - } - - float posZLimit = 0; - - if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) - posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; - - float newPosZ = posZLimit + localAVHeight / 2; - if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) - { - pos.Z = newPosZ; - } - AbsolutePosition = pos; - - AddToPhysicalScene(isFlying); - - if (m_forceFly) - { - m_physicsActor.Flying = true; - } - else if (m_flyDisabled) - { - m_physicsActor.Flying = false; - } - - if (m_appearance != null) - { - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); - } - else - { - m_log.ErrorFormat("[SCENE PRESENCE]: null appearance in MakeRoot in {0}", Scene.RegionInfo.RegionName); - // emergency; this really shouldn't happen - m_appearance = new AvatarAppearance(UUID); - } - - // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying - // avatar to return to the standing position in mid-air. On login it looks like this is being sent - // elsewhere anyway - // Animator.SendAnimPack(); - - m_scene.SwapRootAgentCount(false); - - //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid); - //if (userInfo != null) - // userInfo.FetchInventory(); - //else - // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid); - - // On the next prim update, all objects will be sent - // - m_sceneViewer.Reset(); - - m_isChildAgent = false; - - // send the animations of the other presences to me - m_scene.ForEachScenePresence(delegate(ScenePresence presence) - { - if (presence != this) - presence.Animator.SendAnimPackToClient(ControllingClient); - }); - - m_scene.EventManager.TriggerOnMakeRootAgent(this); - } - - /// - /// This turns a root agent into a child agent - /// when an agent departs this region for a neighbor, this gets called. - /// - /// It doesn't get called for a teleport. Reason being, an agent that - /// teleports out may not end up anywhere near this region - /// - public void MakeChildAgent() - { - // It looks like m_animator is set to null somewhere, and MakeChild - // is called after that. Probably in aborted teleports. - if (m_animator == null) - m_animator = new ScenePresenceAnimator(this); - else - Animator.ResetAnimations(); - -// m_log.DebugFormat( -// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", -// Name, UUID, m_scene.RegionInfo.RegionName); - - // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing, - // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated. - //Velocity = new Vector3(0, 0, 0); - - m_isChildAgent = true; - m_scene.SwapRootAgentCount(true); - RemoveFromPhysicalScene(); - - // FIXME: Set m_rootRegionHandle to the region handle of the scene this agent is moving into - - m_scene.EventManager.TriggerOnMakeChildAgent(this); - } - - /// - /// Removes physics plugin scene representation of this agent if it exists. - /// - private void RemoveFromPhysicalScene() - { - if (PhysicsActor != null) - { - m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; - m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; - m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); - m_physicsActor.UnSubscribeEvents(); - m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; - PhysicsActor = null; - } - } - - /// - /// - /// - /// - public void Teleport(Vector3 pos) - { - bool isFlying = false; - - if (m_physicsActor != null) - isFlying = m_physicsActor.Flying; - - RemoveFromPhysicalScene(); - Velocity = Vector3.Zero; - AbsolutePosition = pos; - AddToPhysicalScene(isFlying); - if (m_appearance != null) - { - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); - } - - SendTerseUpdateToAllClients(); - - } - - public void TeleportWithMomentum(Vector3 pos) - { - bool isFlying = false; - if (m_physicsActor != null) - isFlying = m_physicsActor.Flying; - - RemoveFromPhysicalScene(); - AbsolutePosition = pos; - AddToPhysicalScene(isFlying); - if (m_appearance != null) - { - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); - } - - SendTerseUpdateToAllClients(); - } - - /// - /// - /// - public void StopMovement() - { - } - - public void StopFlying() - { - ControllingClient.StopFlying(this); - } - - public void AddNeighbourRegion(ulong regionHandle, string cap) - { - lock (m_knownChildRegions) - { - if (!m_knownChildRegions.ContainsKey(regionHandle)) - { - uint x, y; - Utils.LongToUInts(regionHandle, out x, out y); - m_knownChildRegions.Add(regionHandle, cap); - } - } - } - - public void RemoveNeighbourRegion(ulong regionHandle) - { - lock (m_knownChildRegions) - { - if (m_knownChildRegions.ContainsKey(regionHandle)) - { - m_knownChildRegions.Remove(regionHandle); - //m_log.Debug(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); - } - } - } - - public void DropOldNeighbours(List oldRegions) - { - foreach (ulong handle in oldRegions) - { - RemoveNeighbourRegion(handle); - Scene.CapsModule.DropChildSeed(UUID, handle); - } - } - - public List GetKnownRegionList() - { - return new List(m_knownChildRegions.Keys); - } - - #endregion - - #region Event Handlers - - /// - /// Sets avatar height in the phyiscs plugin - /// - internal void SetHeight(float height) - { - m_avHeight = height; - if (PhysicsActor != null && !IsChildAgent) - { - Vector3 SetSize = new Vector3(0.45f, 0.6f, m_avHeight); - PhysicsActor.Size = SetSize; - } - } - - /// - /// Complete Avatar's movement into the region. - /// This is called upon a very important packet sent from the client, - /// so it's client-controlled. Never call this method directly. - /// - public void CompleteMovement(IClientAPI client) - { - //m_log.Debug("[SCENE PRESENCE]: CompleteMovement"); - - Vector3 look = Velocity; - if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) - { - look = new Vector3(0.99f, 0.042f, 0); - } - - // Prevent teleporting to an underground location - // (may crash client otherwise) - // - Vector3 pos = AbsolutePosition; - float ground = m_scene.GetGroundHeight(pos.X, pos.Y); - if (pos.Z < ground + 1.5f) - { - pos.Z = ground + 1.5f; - AbsolutePosition = pos; - } - m_isChildAgent = false; - bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - MakeRootAgent(AbsolutePosition, m_flying); - - if ((m_callbackURI != null) && !m_callbackURI.Equals("")) - { - m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI); - Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); - m_callbackURI = null; - } - - //m_log.DebugFormat("Completed movement"); - - m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); - SendInitialData(); - - // Create child agents in neighbouring regions - if (!m_isChildAgent) - { - IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); - if (m_agentTransfer != null) - m_agentTransfer.EnableChildAgents(this); - else - m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active"); - - IFriendsModule friendsModule = m_scene.RequestModuleInterface(); - if (friendsModule != null) - friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); - } - - } - - /// - /// Callback for the Camera view block check. Gets called with the results of the camera view block test - /// hitYN is true when there's something in the way. - /// - /// - /// - /// - /// - public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) - { - const float POSITION_TOLERANCE = 0.02f; - const float VELOCITY_TOLERANCE = 0.02f; - const float ROTATION_TOLERANCE = 0.02f; - - if (m_followCamAuto) - { - if (hitYN) - { - CameraConstraintActive = true; - //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance); - - Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint); - ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint))); - } - else - { - if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || - !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || - !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) - { - if (CameraConstraintActive) - { - ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f)); - CameraConstraintActive = false; - } - } - } - } - } - - /// - /// This is the event handler for client movement. If a client is moving, this event is triggering. - /// - public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) - { - //if (m_isChildAgent) - //{ - // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); - // return; - //} - - m_perfMonMS = Util.EnvironmentTickCount(); - - ++m_movementUpdateCount; - if (m_movementUpdateCount < 1) - m_movementUpdateCount = 1; - - #region Sanity Checking - - // This is irritating. Really. - if (!AbsolutePosition.IsFinite()) - { - RemoveFromPhysicalScene(); - m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); - - m_pos = m_LastFinitePos; - - if (!m_pos.IsFinite()) - { - m_pos.X = 127f; - m_pos.Y = 127f; - m_pos.Z = 127f; - m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); - } - - AddToPhysicalScene(false); - } - else - { - m_LastFinitePos = m_pos; - } - - #endregion Sanity Checking - - #region Inputs - - AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; - Quaternion bodyRotation = agentData.BodyRotation; - - // Camera location in world. We'll need to raytrace - // from this location from time to time. - m_CameraCenter = agentData.CameraCenter; - if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance) - { - ReprioritizeUpdates(); - m_lastCameraCenter = m_CameraCenter; - } - - // Use these three vectors to figure out what the agent is looking at - // Convert it to a Matrix and/or Quaternion - m_CameraAtAxis = agentData.CameraAtAxis; - m_CameraLeftAxis = agentData.CameraLeftAxis; - m_CameraUpAxis = agentData.CameraUpAxis; - - // The Agent's Draw distance setting - m_DrawDistance = agentData.Far; - - // Check if Client has camera in 'follow cam' or 'build' mode. - Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation); - - m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f) - && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; - - m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; - m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; - - #endregion Inputs - - if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) - { - StandUp(); - } - - //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); - // Raycast from the avatar's head to the camera to see if there's anything blocking the view - if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) - { - if (m_followCamAuto) - { - Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; - m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); - } - } - lock (scriptedcontrols) - { - if (scriptedcontrols.Count > 0) - { - SendControlToScripts((uint)flags); - flags = RemoveIgnoredControls(flags, IgnoredControls); - } - } - - if (m_autopilotMoving) - CheckAtSitTarget(); - - if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) - { - m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. - Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); - - // TODO: This doesn't prevent the user from walking yet. - // Setting parent ID would fix this, if we knew what value - // to use. Or we could add a m_isSitting variable. - //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); - SitGround = true; - } - - // In the future, these values might need to go global. - // Here's where you get them. - m_AgentControlFlags = flags; - m_headrotation = agentData.HeadRotation; - m_state = agentData.State; - - PhysicsActor actor = PhysicsActor; - if (actor == null) - { - return; - } - - bool update_movementflag = false; - - if (m_allowMovement && !SitGround) - { - if (agentData.UseClientAgentPosition) - { - m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; - m_moveToPositionTarget = agentData.ClientAgentPosition; - } - - int i = 0; - - bool update_rotation = false; - bool DCFlagKeyPressed = false; - Vector3 agent_control_v3 = Vector3.Zero; - Quaternion q = bodyRotation; - - bool oldflying = PhysicsActor.Flying; - - if (m_forceFly) - actor.Flying = true; - else if (m_flyDisabled) - actor.Flying = false; - else - actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - - if (actor.Flying != oldflying) - update_movementflag = true; - - if (q != m_bodyRot) - { - m_bodyRot = q; - update_rotation = true; - } - - //guilty until proven innocent.. - bool Nudging = true; - //Basically, if there is at least one non-nudge control then we don't need - //to worry about stopping the avatar - - if (m_parentID == 0) - { - bool bAllowUpdateMoveToPosition = false; - bool bResetMoveToPosition = false; - - Vector3[] dirVectors; - - // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying - // this prevents 'jumping' in inappropriate situations. - if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying)) - dirVectors = GetWalkDirectionVectors(); - else - dirVectors = Dir_Vectors; - - bool[] isNudge = GetDirectionIsNudge(); - - - - - - foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) - { - if (((uint)flags & (uint)DCF) != 0) - { - bResetMoveToPosition = true; - DCFlagKeyPressed = true; - try - { - agent_control_v3 += dirVectors[i]; - if (isNudge[i] == false) - { - Nudging = false; - } - } - catch (IndexOutOfRangeException) - { - // Why did I get this? - } - - if ((m_movementflag & (uint)DCF) == 0) - { - m_movementflag += (byte)(uint)DCF; - update_movementflag = true; - } - } - else - { - if ((m_movementflag & (uint)DCF) != 0) - { - m_movementflag -= (byte)(uint)DCF; - update_movementflag = true; - } - else - { - bAllowUpdateMoveToPosition = true; - } - } - i++; - } - //Paupaw:Do Proper PID for Autopilot here - if (bResetMoveToPosition) - { - m_moveToPositionTarget = Vector3.Zero; - m_moveToPositionInProgress = false; - update_movementflag = true; - bAllowUpdateMoveToPosition = false; - } - - if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) - { - //Check the error term of the current position in relation to the target position - if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) - { - // we are close enough to the target - m_moveToPositionTarget = Vector3.Zero; - m_moveToPositionInProgress = false; - update_movementflag = true; - } - else - { - try - { - // move avatar in 2D at one meter/second towards target, in avatar coordinate frame. - // This movement vector gets added to the velocity through AddNewMovement(). - // Theoretically we might need a more complex PID approach here if other - // unknown forces are acting on the avatar and we need to adaptively respond - // to such forces, but the following simple approach seems to works fine. - Vector3 LocalVectorToTarget3D = - (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords - * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords - // Ignore z component of vector - Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); - LocalVectorToTarget2D.Normalize(); - - //We're not nudging - Nudging = false; - agent_control_v3 += LocalVectorToTarget2D; - - // update avatar movement flags. the avatar coordinate system is as follows: - // - // +X (forward) - // - // ^ - // | - // | - // | - // | - // (left) +Y <--------o--------> -Y - // avatar - // | - // | - // | - // | - // v - // -X - // - - // based on the above avatar coordinate system, classify the movement into - // one of left/right/back/forward. - if (LocalVectorToTarget2D.Y > 0)//MoveLeft - { - m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; - //AgentControlFlags - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; - update_movementflag = true; - } - else if (LocalVectorToTarget2D.Y < 0) //MoveRight - { - m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; - update_movementflag = true; - } - if (LocalVectorToTarget2D.X < 0) //MoveBack - { - m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; - update_movementflag = true; - } - else if (LocalVectorToTarget2D.X > 0) //Move Forward - { - m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; - update_movementflag = true; - } - } - catch (Exception e) - { - //Avoid system crash, can be slower but... - m_log.DebugFormat("Crash! {0}", e.ToString()); - } - } - } - } - - // Cause the avatar to stop flying if it's colliding - // with something with the down arrow pressed. - - // Only do this if we're flying - if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly) - { - // Landing detection code - - // Are the landing controls requirements filled? - bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || - ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); - - // Are the collision requirements fulfilled? - bool colliding = (m_physicsActor.IsColliding == true); - - if (m_physicsActor.Flying && colliding && controlland) - { - // nesting this check because LengthSquared() is expensive and we don't - // want to do it every step when flying. - if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) - StopFlying(); - } - } - - if (update_movementflag || (update_rotation && DCFlagKeyPressed)) - { - // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed)); - // m_log.DebugFormat( - // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); - - AddNewMovement(agent_control_v3, q, Nudging); - - - } - } - - if (update_movementflag && !SitGround) - Animator.UpdateMovementAnimations(); - - m_scene.EventManager.TriggerOnClientMovement(this); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client) - { - m_autopilotMoving = true; - m_autoPilotTarget = Pos; - m_sitAtAutoTarget = false; - PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; - //proxy.PCode = (byte)PCode.ParticleSystem; - proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); - proxyObjectGroup.AttachToScene(m_scene); - - // Commented out this code since it could never have executed, but might still be informative. -// if (proxyObjectGroup != null) -// { - proxyObjectGroup.SendGroupFullUpdate(); - remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); - m_scene.DeleteSceneObject(proxyObjectGroup, false); -// } -// else -// { -// m_autopilotMoving = false; -// m_autoPilotTarget = Vector3.Zero; -// ControllingClient.SendAlertMessage("Autopilot cancelled"); -// } - } - - public void DoMoveToPosition(Object sender, string method, List args) - { - try - { - float locx = 0f; - float locy = 0f; - float locz = 0f; - uint regionX = 0; - uint regionY = 0; - try - { - Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); - locx = Convert.ToSingle(args[0]) - (float)regionX; - locy = Convert.ToSingle(args[1]) - (float)regionY; - locz = Convert.ToSingle(args[2]); - } - catch (InvalidCastException) - { - m_log.Error("[CLIENT]: Invalid autopilot request"); - return; - } - m_moveToPositionInProgress = true; - m_moveToPositionTarget = new Vector3(locx, locy, locz); - } - catch (Exception ex) - { - //Why did I get this error? - m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex); - } - } - - private void CheckAtSitTarget() - { - //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString()); - if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5) - { - if (m_sitAtAutoTarget) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID); - if (part != null) - { - AbsolutePosition = part.AbsolutePosition; - Velocity = Vector3.Zero; - SendFullUpdateToAllClients(); - - HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ?? - } - //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); - m_requestedSitTargetUUID = UUID.Zero; - } - /* - else - { - //ControllingClient.SendAlertMessage("Autopilot cancelled"); - //SendTerseUpdateToAllClients(); - //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; - //proxy.PCode = (byte)PCode.ParticleSystem; - ////uint nextUUID = m_scene.NextLocalId; - - //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy); - //if (proxyObjectGroup != null) - //{ - //proxyObjectGroup.SendGroupFullUpdate(); - //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); - //m_scene.DeleteSceneObject(proxyObjectGroup); - //} - } - */ - m_autoPilotTarget = Vector3.Zero; - m_autopilotMoving = false; - } - } - /// - /// Perform the logic necessary to stand the avatar up. This method also executes - /// the stand animation. - /// - public void StandUp() - { - SitGround = false; - - if (m_parentID != 0) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); - if (part != null) - { - part.TaskInventory.LockItemsForRead(true); - TaskInventoryDictionary taskIDict = part.TaskInventory; - if (taskIDict != null) - { - foreach (UUID taskID in taskIDict.Keys) - { - UnRegisterControlEventsToScript(LocalId, taskID); - taskIDict[taskID].PermsMask &= ~( - 2048 | //PERMISSION_CONTROL_CAMERA - 4); // PERMISSION_TAKE_CONTROLS - } - } - part.TaskInventory.LockItemsForRead(false); - // Reset sit target. - if (part.GetAvatarOnSitTarget() == UUID) - part.SetAvatarOnSitTarget(UUID.Zero); - m_parentPosition = part.GetWorldPosition(); - ControllingClient.SendClearFollowCamProperties(part.ParentUUID); - } - // part.GetWorldRotation() is the rotation of the object being sat on - // Rotation is the sittiing Av's rotation - - Quaternion partRot; -// if (part.LinkNum == 1) -// { // Root prim of linkset -// partRot = part.ParentGroup.RootPart.RotationOffset; -// } -// else -// { // single or child prim - -// } - if (part == null) //CW: Part may be gone. llDie() for example. - { - partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - } - else - { - partRot = part.GetWorldRotation(); - } - - Quaternion partIRot = Quaternion.Inverse(partRot); - - Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av - Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av - - - if (m_physicsActor == null) - { - AddToPhysicalScene(false); - } - //CW: If the part isn't null then we can set the current position - if (part != null) - { - Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset! - AbsolutePosition = avWorldStandUp; //KF: Fix stand up. - part.IsOccupied = false; - part.ParentGroup.DeleteAvatar(ControllingClient.AgentId); - } - else - { - //CW: Since the part doesn't exist, a coarse standup position isn't an issue - AbsolutePosition = m_lastWorldPosition; - } - - m_parentPosition = Vector3.Zero; - m_parentID = 0; - m_linkedPrim = UUID.Zero; - m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - SendFullUpdateToAllClients(); - m_requestedSitTargetID = 0; - - if ((m_physicsActor != null) && (m_avHeight > 0)) - { - SetHeight(m_avHeight); - } - } - Animator.TrySetMovementAnimation("STAND"); - } - - private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) - { - SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID); - if (targetPart == null) - return null; - - // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used. - // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used. - - // Get our own copy of the part array, and sort into the order we want to test - SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts(); - Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2) - { - // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1) - int linkNum1 = p1==targetPart ? -1 : p1.LinkNum; - int linkNum2 = p2==targetPart ? -1 : p2.LinkNum; - return linkNum1 - linkNum2; - } - ); - - //look for prims with explicit sit targets that are available - foreach (SceneObjectPart part in partArray) - { - // Is a sit target available? - Vector3 avSitOffSet = part.SitTargetPosition; - Quaternion avSitOrientation = part.SitTargetOrientation; - UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); - bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero); - bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. - if (SitTargetisSet && !SitTargetOccupied) - { - //switch the target to this prim - return part; - } - } - - // no explicit sit target found - use original target - return targetPart; - } - - private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) - { - bool autopilot = true; - Vector3 autopilotTarget = new Vector3(); - Quaternion sitOrientation = Quaternion.Identity; - Vector3 pos = new Vector3(); - Vector3 cameraEyeOffset = Vector3.Zero; - Vector3 cameraAtOffset = Vector3.Zero; - bool forceMouselook = false; - - //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); - SceneObjectPart part = FindNextAvailableSitTarget(targetID); - if (part == null) return; - - // TODO: determine position to sit at based on scene geometry; don't trust offset from client - // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it - - // part is the prim to sit on - // offset is the world-ref vector distance from that prim center to the click-spot - // UUID is the UUID of the Avatar doing the clicking - - m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation - - // Is a sit target available? - Vector3 avSitOffSet = part.SitTargetPosition; - Quaternion avSitOrientation = part.SitTargetOrientation; - - bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. - // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); - Quaternion partRot; -// if (part.LinkNum == 1) -// { // Root prim of linkset -// partRot = part.ParentGroup.RootPart.RotationOffset; -// } -// else -// { // single or child prim - partRot = part.GetWorldRotation(); -// } - Quaternion partIRot = Quaternion.Inverse(partRot); -//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet); - // Sit analysis rewritten by KF 091125 - if (SitTargetisSet) // scipted sit - { - if (!part.IsOccupied) - { -//Console.WriteLine("Scripted, unoccupied"); - part.SetAvatarOnSitTarget(UUID); // set that Av will be on it - offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one - - Quaternion nrot = avSitOrientation; - if (!part.IsRoot) - { - nrot = part.RotationOffset * avSitOrientation; - } - sitOrientation = nrot; // Change rotatione to the scripted one - OffsetRotation = nrot; - autopilot = false; // Jump direct to scripted llSitPos() - } - else - { -//Console.WriteLine("Scripted, occupied"); - return; - } - } - else // Not Scripted - { - if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) - { - // large prim & offset, ignore if other Avs sitting -// offset.Z -= 0.05f; - m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked - autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point - -//Console.WriteLine(" offset ={0}", offset); -//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos); -//Console.WriteLine(" autopilotTarget={0}", autopilotTarget); - - } - else // small offset - { -//Console.WriteLine("Small offset"); - if (!part.IsOccupied) - { - m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center - autopilotTarget = part.AbsolutePosition; -//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget); - } - else return; // occupied small - } // end large/small - } // end Scripted/not - cameraAtOffset = part.GetCameraAtOffset(); - cameraEyeOffset = part.GetCameraEyeOffset(); - forceMouselook = part.GetForceMouselook(); - if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); // - if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); // - - if (m_physicsActor != null) - { - // If we're not using the client autopilot, we're immediately warping the avatar to the location - // We can remove the physicsActor until they stand up. - m_sitAvatarHeight = m_physicsActor.Size.Z; - if (autopilot) - { // its not a scripted sit -// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) - if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) ) - { - autopilot = false; // close enough - m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup. - Not using the part's position because returning the AV to the last known standing - position is likely to be more friendly, isn't it? */ - RemoveFromPhysicalScene(); - Velocity = Vector3.Zero; - AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target - } // else the autopilot will get us close - } - else - { // its a scripted sit - m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup. - I *am* using the part's position this time because we have no real idea how far away - the avatar is from the sit target. */ - RemoveFromPhysicalScene(); - Velocity = Vector3.Zero; - } - } - else return; // physactor is null! - - Vector3 offsetr; // = offset * partIRot; - // KF: In a linkset, offsetr needs to be relative to the group root! 091208 - // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot); - // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error. - // { // Single, or Root prim of linkset, target is ClickOffset * RootRot - //offsetr = offset * partIRot; -// - // else - // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot) - // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + - // (offset * partRot); - // } - -//Console.WriteLine(" "); -//Console.WriteLine("link number ={0}", part.LinkNum); -//Console.WriteLine("Prim offset ={0}", part.OffsetPosition ); -//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset); -//Console.WriteLine("Click offst ={0}", offset); -//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation()); -//Console.WriteLine("offsetr ={0}", offsetr); -//Console.WriteLine("Camera At ={0}", cameraAtOffset); -//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); - - //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child - ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); - - m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target - // This calls HandleAgentSit twice, once from here, and the client calls - // HandleAgentSit itself after it gets to the location - // It doesn't get to the location until we've moved them there though - // which happens in HandleAgentSit :P - m_autopilotMoving = autopilot; - m_autoPilotTarget = autopilotTarget; - m_sitAtAutoTarget = autopilot; - m_initialSitTarget = autopilotTarget; - if (!autopilot) - HandleAgentSit(remoteClient, UUID); - } - - public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset) - { - if (m_parentID != 0) - { - StandUp(); - } - m_nextSitAnimation = "SIT"; - - //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); - SceneObjectPart part = FindNextAvailableSitTarget(targetID); - - if (part != null) - { - if (!String.IsNullOrEmpty(part.SitAnimation)) - { - m_nextSitAnimation = part.SitAnimation; - } - m_requestedSitTargetID = part.LocalId; - //m_requestedSitOffset = offset; - m_requestedSitTargetUUID = targetID; - - m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); - - if (m_scene.PhysicsScene.SupportsRayCast()) - { - //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback()); - //SitRayCastAvatarPosition(part); - //return; - } - } - else - { - - m_log.Warn("Sit requested on unknown object: " + targetID.ToString()); - } - - - - SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity); - } - /* - public void SitRayCastAvatarPosition(SceneObjectPart part) - { - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = AbsolutePosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse); - } - - public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); - } - else - { - SitRayCastAvatarPositionCameraZ(part); - } - } - else - { - SitRayCastAvatarPositionCameraZ(part); - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part) - { - // Next, try to raycast from the camera Z position - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse); - } - - public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal); - } - else - { - SitRayCastCameraPosition(part); - } - } - else - { - SitRayCastCameraPosition(part); - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - public void SitRayCastCameraPosition(SceneObjectPart part) - { - // Next, try to raycast from the camera position - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = CameraPosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse); - } - - public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); - } - else - { - SitRayHorizontal(part); - } - } - else - { - SitRayHorizontal(part); - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - public void SitRayHorizontal(SceneObjectPart part) - { - // Next, try to raycast from the avatar position to fwd - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = CameraPosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse); - } - - public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); - // Next, try to raycast from the camera position - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = CameraPosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition); - } - else - { - ControllingClient.SendAlertMessage("Sit position not accessable."); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - } - else - { - ControllingClient.SendAlertMessage("Sit position not accessable."); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal) - { - int i = 0; - //throw new NotImplementedException(); - //m_requestedSitTargetUUID = UUID.Zero; - //m_requestedSitTargetID = 0; - //m_requestedSitOffset = Vector3.Zero; - - SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity); - } - */ - public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation) - { - if (m_parentID != 0) - { - StandUp(); - } - if (!String.IsNullOrEmpty(sitAnimation)) - { - m_nextSitAnimation = sitAnimation; - } - else - { - m_nextSitAnimation = "SIT"; - } - - //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); - SceneObjectPart part = FindNextAvailableSitTarget(targetID); - if (part != null) - { - m_requestedSitTargetID = part.LocalId; - //m_requestedSitOffset = offset; - m_requestedSitTargetUUID = targetID; - - m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); - - if (m_scene.PhysicsScene.SupportsRayCast()) - { - //SitRayCastAvatarPosition(part); - //return; - } - } - else - { - m_log.Warn("Sit requested on unknown object: " + targetID); - } - - SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity); - } - - public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) - { - if (!String.IsNullOrEmpty(m_nextSitAnimation)) - { - HandleAgentSit(remoteClient, agentID, m_nextSitAnimation); - } - else - { - HandleAgentSit(remoteClient, agentID, "SIT"); - } - } - - public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation) - { - SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); - - if (m_sitAtAutoTarget || !m_autopilotMoving) - { - if (part != null) - { -//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation()); - if (part.GetAvatarOnSitTarget() == UUID) - { -//Console.WriteLine("Scripted Sit"); - // Scripted sit - Vector3 sitTargetPos = part.SitTargetPosition; - Quaternion sitTargetOrient = part.SitTargetOrientation; - m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); - m_pos += SIT_TARGET_ADJUSTMENT; - if (!part.IsRoot) - { - m_pos *= part.RotationOffset; - } - m_bodyRot = sitTargetOrient; - m_parentPosition = part.AbsolutePosition; - part.IsOccupied = true; - part.ParentGroup.AddAvatar(agentID); - } - else - { - // if m_avUnscriptedSitPos is zero then Av sits above center - // Else Av sits at m_avUnscriptedSitPos - - // Non-scripted sit by Kitto Flora 21Nov09 - // Calculate angle of line from prim to Av - Quaternion partIRot; -// if (part.LinkNum == 1) -// { // Root prim of linkset -// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); -// } -// else -// { // single or child prim - partIRot = Quaternion.Inverse(part.GetWorldRotation()); -// } - Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos; - float y_diff = (m_avInitialPos.Y - sitTargetPos.Y); - float x_diff = ( m_avInitialPos.X - sitTargetPos.X); - if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0 - if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0 - float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff); - // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'. - // Av sits at world euler <0,0, z>, translated by part rotation - m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click - - m_parentPosition = part.AbsolutePosition; - part.IsOccupied = true; - part.ParentGroup.AddAvatar(agentID); - m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation - (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center - (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) + - m_avUnscriptedSitPos; // adds click offset, if any - //Set up raytrace to find top surface of prim - Vector3 size = part.Scale; - float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); - Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); - Vector3 down = new Vector3(0f, 0f, -1f); -//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag); - m_scene.PhysicsScene.RaycastWorld( - start, // Vector3 position, - down, // Vector3 direction, - mag, // float length, - SitAltitudeCallback); // retMethod - } // end scripted/not - } - else // no Av - { - return; - } - } - - //We want our offsets to reference the root prim, not the child we may have sat on - if (!part.IsRoot) - { - m_parentID = part.ParentGroup.RootPart.LocalId; - m_pos += part.OffsetPosition; - } - else - { - m_parentID = m_requestedSitTargetID; - } - - m_linkedPrim = part.UUID; - if (part.GetAvatarOnSitTarget() != UUID) - { - m_offsetRotation = m_offsetRotation / part.RotationOffset; - } - Velocity = Vector3.Zero; - RemoveFromPhysicalScene(); - Animator.TrySetMovementAnimation(sitAnimation); - SendFullUpdateToAllClients(); - SendTerseUpdateToAllClients(); - } - - public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal) - { - // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer - // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height. - if(hitYN) - { - // m_pos = Av offset from prim center to make look like on center - // m_parentPosition = Actual center pos of prim - // collisionPoint = spot on prim where we want to sit - // collisionPoint.Z = global sit surface height - SceneObjectPart part = m_scene.GetSceneObjectPart(localid); - Quaternion partIRot; -// if (part.LinkNum == 1) -/// { // Root prim of linkset -// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); -// } -// else -// { // single or child prim - partIRot = Quaternion.Inverse(part.GetWorldRotation()); -// } - if (m_initialSitTarget != null) - { - float offZ = collisionPoint.Z - m_initialSitTarget.Z; - Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction - //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); - m_pos += offset; - // ControllingClient.SendClearFollowCamProperties(part.UUID); - } - - } - } // End SitAltitudeCallback KF. - - /// - /// Event handler for the 'Always run' setting on the client - /// Tells the physics plugin to increase speed of movement. - /// - public void HandleSetAlwaysRun(IClientAPI remoteClient, bool pSetAlwaysRun) - { - m_setAlwaysRun = pSetAlwaysRun; - if (PhysicsActor != null) - { - PhysicsActor.SetAlwaysRun = pSetAlwaysRun; - } - } - - public void HandleStartAnim(IClientAPI remoteClient, UUID animID) - { - Animator.AddAnimation(animID, UUID.Zero); - } - - public void HandleStopAnim(IClientAPI remoteClient, UUID animID) - { - Animator.RemoveAnimation(animID); - } - - /// - /// Rotate the avatar to the given rotation and apply a movement in the given relative vector - /// - /// The vector in which to move. This is relative to the rotation argument - /// The direction in which this avatar should now face. - public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging) - { - if (m_isChildAgent) - { - // WHAT??? - m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); - - // we have to reset the user's child agent connections. - // Likely, here they've lost the eventqueue for other regions so border - // crossings will fail at this point unless we reset them. - - List regions = new List(KnownChildRegionHandles); - regions.Remove(m_scene.RegionInfo.RegionHandle); - - MakeRootAgent(new Vector3(127f, 127f, 127f), true); - - // Async command - if (m_scene.SceneGridService != null) - { - m_scene.SceneGridService.SendCloseChildAgentConnections(UUID, regions); - - // Give the above command some time to try and close the connections. - // this is really an emergency.. so sleep, or we'll get all discombobulated. - System.Threading.Thread.Sleep(500); - } - - if (m_scene.SceneGridService != null) - { - IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); - if (m_agentTransfer != null) - m_agentTransfer.EnableChildAgents(this); - } - - return; - } - - m_perfMonMS = Util.EnvironmentTickCount(); - - Rotation = rotation; - Vector3 direc = vec * rotation; - direc.Normalize(); - PhysicsActor actor = m_physicsActor; - if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up. - - direc *= 0.03f * 128f * m_speedModifier; - - if (actor != null) - { - if (actor.Flying) - { - direc *= 4.0f; - //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); - //bool colliding = (m_physicsActor.IsColliding==true); - //if (controlland) - // m_log.Info("[AGENT]: landCommand"); - //if (colliding) - // m_log.Info("[AGENT]: colliding"); - //if (m_physicsActor.Flying && colliding && controlland) - //{ - // StopFlying(); - // m_log.Info("[AGENT]: Stop FLying"); - //} - } - else if (!actor.Flying && actor.IsColliding) - { - if (direc.Z > 2.0f) - { - if(m_animator.m_animTickJump == -1) - { - direc.Z *= 3.0f; // jump - } - else - { - direc.Z *= 0.1f; // prejump - } - /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs - Animator.TrySetMovementAnimation("PREJUMP"); - Animator.TrySetMovementAnimation("JUMP"); - */ - } - } - } - - // TODO: Add the force instead of only setting it to support multiple forces per frame? - m_forceToApply = direc; - m_isNudging = Nudging; - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - #endregion - - #region Overridden Methods - - public override void Update() - { - const float ROTATION_TOLERANCE = 0.01f; - const float VELOCITY_TOLERANCE = 0.001f; - const float POSITION_TOLERANCE = 0.05f; - //const int TIME_MS_TOLERANCE = 3000; - - - - if (m_isChildAgent == false) - { -// PhysicsActor actor = m_physicsActor; - - // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to - // grab the latest PhysicsActor velocity, whereas m_velocity is often - // storing a requested force instead of an actual traveling velocity - - // Throw away duplicate or insignificant updates - if (!m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || - !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || - !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) - //Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) - { - SendTerseUpdateToAllClients(); - - // Update the "last" values - m_lastPosition = m_pos; - m_lastRotation = m_bodyRot; - m_lastVelocity = Velocity; - //m_lastTerseSent = Environment.TickCount; - } - - // followed suggestion from mic bowman. reversed the two lines below. - if (m_parentID == 0 && m_physicsActor != null || m_parentID != 0) // Check that we have a physics actor or we're sitting on something - CheckForBorderCrossing(); - CheckForSignificantMovement(); // sends update to the modules. - } - - //Sending prim updates AFTER the avatar terse updates are sent - SendPrimUpdates(); - } - - #endregion - - #region Update Client(s) - - /// - /// Sends a location update to the client connected to this scenePresence - /// - /// - public void SendTerseUpdateToClient(IClientAPI remoteClient) - { - // If the client is inactive, it's getting its updates from another - // server. - if (remoteClient.IsActive) - { - m_perfMonMS = Util.EnvironmentTickCount(); - - PhysicsActor actor = m_physicsActor; - Vector3 velocity = (actor != null) ? actor.Velocity : Vector3.Zero; - - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - - //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); - - remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - m_scene.StatsReporter.AddAgentUpdates(1); - } - } - - /// - /// Send a location/velocity/accelleration update to all agents in scene - /// - public void SendTerseUpdateToAllClients() - { - m_perfMonMS = Util.EnvironmentTickCount(); - - m_scene.ForEachClient(SendTerseUpdateToClient); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - public void SendCoarseLocations(List coarseLocations, List avatarUUIDs) - { - SendCourseLocationsMethod d = m_sendCourseLocationsMethod; - if (d != null) - { - d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); - } - } - - public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) - { - if (d != null) - m_sendCourseLocationsMethod = d; - } - - public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs) - { - m_perfMonMS = Util.EnvironmentTickCount(); - m_controllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - /// - /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar) - /// - /// - public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar) - { - // 2 stage check is needed. - if (remoteAvatar == null) - return; - IClientAPI cl=remoteAvatar.ControllingClient; - if (cl == null) - return; - if (m_appearance.Texture == null) - return; - - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - - remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this); - m_scene.StatsReporter.AddAgentUpdates(1); - } - - /// - /// Tell *ALL* agents about this agent - /// - public void SendInitialFullUpdateToAllClients() - { - m_perfMonMS = Util.EnvironmentTickCount(); - int avUpdates = 0; - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - ++avUpdates; - // only send if this is the root (children are only "listening posts" in a foreign region) - if (!IsChildAgent) - { - SendFullUpdateToOtherClient(avatar); - } - - if (avatar.LocalId != LocalId) - { - if (!avatar.IsChildAgent) - { - avatar.SendFullUpdateToOtherClient(this); - avatar.SendAppearanceToOtherAgent(this); - avatar.Animator.SendAnimPackToClient(ControllingClient); - } - } - }); - - m_scene.StatsReporter.AddAgentUpdates(avUpdates); - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - - //Animator.SendAnimPack(); - } - - public void SendFullUpdateToAllClients() - { - m_perfMonMS = Util.EnvironmentTickCount(); - - // only send update from root agents to other clients; children are only "listening posts" - int count = 0; - m_scene.ForEachScenePresence(delegate(ScenePresence sp) - { - if (sp.IsChildAgent) - return; - SendFullUpdateToOtherClient(sp); - ++count; - }); - m_scene.StatsReporter.AddAgentUpdates(count); - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - - Animator.SendAnimPack(); - } - - /// - /// Do everything required once a client completes its movement into a region - /// - public void SendInitialData() - { - // Moved this into CompleteMovement to ensure that m_appearance is initialized before - // the inventory arrives - // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); - - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - - m_controllingClient.SendAvatarDataImmediate(this); - - SendInitialFullUpdateToAllClients(); - SendAppearanceToAllOtherAgents(); - } - - /// - /// Tell the client for this scene presence what items it should be wearing now - /// - public void SendWearables() - { - m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name); - - ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); - } - - /// - /// - /// - public void SendAppearanceToAllOtherAgents() - { - m_perfMonMS = Util.EnvironmentTickCount(); - - m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) - { - if (scenePresence.UUID != UUID) - { - SendAppearanceToOtherAgent(scenePresence); - } - }); - - m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - } - - /// - /// Send appearance data to an agent that isn't this one. - /// - /// - public void SendAppearanceToOtherAgent(ScenePresence avatar) - { - avatar.ControllingClient.SendAppearance( - m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes()); - } - - /// - /// Set appearance data (textureentry and slider settings) received from the client - /// - /// - /// - public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams) - { - if (m_physicsActor != null) - { - if (!IsChildAgent) - { - // This may seem like it's redundant, remove the avatar from the physics scene - // just to add it back again, but it saves us from having to update - // 3 variables 10 times a second. - bool flyingTemp = m_physicsActor.Flying; - RemoveFromPhysicalScene(); - //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor); - - //PhysicsActor = null; - - AddToPhysicalScene(flyingTemp); - } - } - - #region Bake Cache Check - - if (textureEntry != null) - { - for (int i = 0; i < BAKE_INDICES.Length; i++) - { - int j = BAKE_INDICES[i]; - Primitive.TextureEntryFace face = textureEntry.FaceTextures[j]; - - if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) - { - if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) - { - m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name); - this.ControllingClient.SendRebakeAvatarTextures(face.TextureID); - } - } - } - - } - - - #endregion Bake Cache Check - - m_appearance.SetAppearance(textureEntry, visualParams); - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); - - // This is not needed, because only the transient data changed - //AvatarData adata = new AvatarData(m_appearance); - //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); - - SendAppearanceToAllOtherAgents(); - if (!m_startAnimationSet) - { - Animator.UpdateMovementAnimations(); - m_startAnimationSet = true; - } - - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; - - m_controllingClient.SendAvatarDataImmediate(this); - } - - public void SetWearable(int wearableId, AvatarWearable wearable) - { - m_appearance.SetWearable(wearableId, wearable); - AvatarData adata = new AvatarData(m_appearance); - m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); - m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); - } - - // Because appearance setting is in a module, we actually need - // to give it access to our appearance directly, otherwise we - // get a synchronization issue. - public AvatarAppearance Appearance - { - get { return m_appearance; } - set { m_appearance = value; } - } - - #endregion - - #region Significant Movement Method - - /// - /// This checks for a significant movement and sends a courselocationchange update - /// - protected void CheckForSignificantMovement() - { - // Movement updates for agents in neighboring regions are sent directly to clients. - // This value only affects how often agent positions are sent to neighbor regions - // for things such as distance-based update prioritization - const float SIGNIFICANT_MOVEMENT = 2.0f; - - if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT) - { - posLastSignificantMove = AbsolutePosition; - m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient); - } - - // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m - if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || - Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance) - { - m_lastChildAgentUpdatePosition = AbsolutePosition; - m_lastChildAgentUpdateCamPosition = CameraPosition; - - ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); - cadu.ActiveGroupID = UUID.Zero.Guid; - cadu.AgentID = UUID.Guid; - cadu.alwaysrun = m_setAlwaysRun; - cadu.AVHeight = m_avHeight; - Vector3 tempCameraCenter = m_CameraCenter; - cadu.cameraPosition = tempCameraCenter; - cadu.drawdistance = m_DrawDistance; - cadu.GroupAccess = 0; - cadu.Position = AbsolutePosition; - cadu.regionHandle = m_rootRegionHandle; - float multiplier = 1; - int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); - if (innacurateNeighbors != 0) - { - multiplier = 1f / (float)innacurateNeighbors; - } - if (multiplier <= 0f) - { - multiplier = 0.25f; - } - - //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); - cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); - cadu.Velocity = Velocity; - - AgentPosition agentpos = new AgentPosition(); - agentpos.CopyFrom(cadu); - - m_scene.SendOutChildAgentUpdates(agentpos, this); - } - } - - #endregion - - #region Border Crossing Methods - - /// - /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion - /// - protected void CheckForBorderCrossing() - { - if (IsChildAgent) - return; - - Vector3 pos2 = AbsolutePosition; - Vector3 vel = Velocity; - int neighbor = 0; - int[] fix = new int[2]; - - float timeStep = 0.1f; - pos2.X = pos2.X + (vel.X*timeStep); - pos2.Y = pos2.Y + (vel.Y*timeStep); - pos2.Z = pos2.Z + (vel.Z*timeStep); - - if (!IsInTransit) - { - // Checks if where it's headed exists a region - - bool needsTransit = false; - if (m_scene.TestBorderCross(pos2, Cardinals.W)) - { - if (m_scene.TestBorderCross(pos2, Cardinals.S)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.SW, ref fix); - } - else if (m_scene.TestBorderCross(pos2, Cardinals.N)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.NW, ref fix); - } - else - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.W, ref fix); - } - } - else if (m_scene.TestBorderCross(pos2, Cardinals.E)) - { - if (m_scene.TestBorderCross(pos2, Cardinals.S)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.SE, ref fix); - } - else if (m_scene.TestBorderCross(pos2, Cardinals.N)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.NE, ref fix); - } - else - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.E, ref fix); - } - } - else if (m_scene.TestBorderCross(pos2, Cardinals.S)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.S, ref fix); - } - else if (m_scene.TestBorderCross(pos2, Cardinals.N)) - { - needsTransit = true; - neighbor = HaveNeighbor(Cardinals.N, ref fix); - } - - - // Makes sure avatar does not end up outside region - if (neighbor <= 0) - { - if (!needsTransit) - { - if (m_requestedSitTargetUUID == UUID.Zero) - { - Vector3 pos = AbsolutePosition; - if (AbsolutePosition.X < 0) - pos.X += Velocity.X; - else if (AbsolutePosition.X > Constants.RegionSize) - pos.X -= Velocity.X; - if (AbsolutePosition.Y < 0) - pos.Y += Velocity.Y; - else if (AbsolutePosition.Y > Constants.RegionSize) - pos.Y -= Velocity.Y; - AbsolutePosition = pos; - } - } - } - else if (neighbor > 0) - CrossToNewRegion(); - } - else - { - RemoveFromPhysicalScene(); - // This constant has been inferred from experimentation - // I'm not sure what this value should be, so I tried a few values. - timeStep = 0.04f; - pos2 = AbsolutePosition; - pos2.X = pos2.X + (vel.X * timeStep); - pos2.Y = pos2.Y + (vel.Y * timeStep); - pos2.Z = pos2.Z + (vel.Z * timeStep); - m_pos = pos2; - } - } - - protected int HaveNeighbor(Cardinals car, ref int[] fix) - { - uint neighbourx = m_regionInfo.RegionLocX; - uint neighboury = m_regionInfo.RegionLocY; - - int dir = (int)car; - - if (dir > 1 && dir < 5) //Heading East - neighbourx++; - else if (dir > 5) // Heading West - neighbourx--; - - if (dir < 3 || dir == 8) // Heading North - neighboury++; - else if (dir > 3 && dir < 7) // Heading Sout - neighboury--; - - int x = (int)(neighbourx * Constants.RegionSize); - int y = (int)(neighboury * Constants.RegionSize); - GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y); - - if (neighbourRegion == null) - { - fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx); - fix[1] = (int)(m_regionInfo.RegionLocY - neighboury); - return dir * (-1); - } - else - return dir; - } - - /// - /// Moves the agent outside the region bounds - /// Tells neighbor region that we're crossing to it - /// If the neighbor accepts, remove the agent's viewable avatar from this scene - /// set them to a child agent. - /// - protected void CrossToNewRegion() - { - InTransit(); - try - { - m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying); - } - catch - { - m_scene.CrossAgentToNewRegion(this, false); - } - } - - public void InTransit() - { - m_inTransit = true; - - if ((m_physicsActor != null) && m_physicsActor.Flying) - m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY; - else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) - m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY; - } - - public void NotInTransit() - { - m_inTransit = false; - } - - public void RestoreInCurrentScene() - { - AddToPhysicalScene(false); // not exactly false - } - - public void Reset() - { - // Put the child agent back at the center - AbsolutePosition - = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); - Animator.ResetAnimations(); - } - - /// - /// Computes which child agents to close when the scene presence moves to another region. - /// Removes those regions from m_knownRegions. - /// - /// The new region's x on the map - /// The new region's y on the map - /// - public void CloseChildAgents(uint newRegionX, uint newRegionY) - { - List byebyeRegions = new List(); - m_log.DebugFormat( - "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", - m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName); - //DumpKnownRegions(); - - lock (m_knownChildRegions) - { - foreach (ulong handle in m_knownChildRegions.Keys) - { - // Don't close the agent on this region yet - if (handle != Scene.RegionInfo.RegionHandle) - { - uint x, y; - Utils.LongToUInts(handle, out x, out y); - x = x / Constants.RegionSize; - y = y / Constants.RegionSize; - - //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); - //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); - if (Util.IsOutsideView(x, newRegionX, y, newRegionY)) - { - byebyeRegions.Add(handle); - } - } - } - } - - if (byebyeRegions.Count > 0) - { - m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); - m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions); - } - - foreach (ulong handle in byebyeRegions) - { - RemoveNeighbourRegion(handle); - } - } - - #endregion - - /// - /// This allows the Sim owner the abiility to kick users from their sim currently. - /// It tells the client that the agent has permission to do so. - /// - public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) - { - if (godStatus) - { - // For now, assign god level 200 to anyone - // who is granted god powers, but has no god level set. - // - UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID); - if (account != null) - { - if (account.UserLevel > 0) - m_godLevel = account.UserLevel; - else - m_godLevel = 200; - } - } - else - { - m_godLevel = 0; - } - - ControllingClient.SendAdminResponse(token, (uint)m_godLevel); - } - - #region Child Agent Updates - - public void ChildAgentDataUpdate(AgentData cAgentData) - { - //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); - if (!IsChildAgent) - return; - - CopyFrom(cAgentData); - } - - /// - /// This updates important decision making data about a child agent - /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region - /// - public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) - { - if (!IsChildAgent) - return; - - //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); - int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; - int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; - - Vector3 offset = new Vector3(shiftx, shifty, 0f); - - m_DrawDistance = cAgentData.Far; - if (cAgentData.Position != new Vector3(-1f, -1f, -1f)) // UGH!! - m_pos = cAgentData.Position + offset; - - if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance) - { - posLastSignificantMove = AbsolutePosition; - ReprioritizeUpdates(); - } - - m_CameraCenter = cAgentData.Center + offset; - - m_avHeight = cAgentData.Size.Z; - //SetHeight(cAgentData.AVHeight); - - if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) - ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); - - // Sends out the objects in the user's draw distance if m_sendTasksToChild is true. - if (m_scene.m_seeIntoRegionFromNeighbor) - m_sceneViewer.Reset(); - - //cAgentData.AVHeight; - m_rootRegionHandle = cAgentData.RegionHandle; - //m_velocity = cAgentData.Velocity; - } - - public void CopyTo(AgentData cAgent) - { - cAgent.AgentID = UUID; - cAgent.RegionID = Scene.RegionInfo.RegionID; - - cAgent.Position = AbsolutePosition; - cAgent.Velocity = m_velocity; - cAgent.Center = m_CameraCenter; - // Don't copy the size; it is inferred from apearance parameters - //cAgent.Size = new Vector3(0, 0, m_avHeight); - cAgent.AtAxis = m_CameraAtAxis; - cAgent.LeftAxis = m_CameraLeftAxis; - cAgent.UpAxis = m_CameraUpAxis; - - cAgent.Far = m_DrawDistance; - - // Throttles - float multiplier = 1; - int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); - if (innacurateNeighbors != 0) - { - multiplier = 1f / innacurateNeighbors; - } - if (multiplier <= 0f) - { - multiplier = 0.25f; - } - //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); - cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); - - cAgent.HeadRotation = m_headrotation; - cAgent.BodyRotation = m_bodyRot; - cAgent.ControlFlags = (uint)m_AgentControlFlags; - - if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) - cAgent.GodLevel = (byte)m_godLevel; - else - cAgent.GodLevel = (byte) 0; - - cAgent.AlwaysRun = m_setAlwaysRun; - - try - { - // We might not pass the Wearables in all cases... - // They're only needed so that persistent changes to the appearance - // are preserved in the new region where the user is moving to. - // But in Hypergrid we might not let this happen. - int i = 0; - UUID[] wears = new UUID[m_appearance.Wearables.Length * 2]; - foreach (AvatarWearable aw in m_appearance.Wearables) - { - if (aw != null) - { - wears[i++] = aw.ItemID; - wears[i++] = aw.AssetID; - } - else - { - wears[i++] = UUID.Zero; - wears[i++] = UUID.Zero; - } - } - cAgent.Wearables = wears; - - cAgent.VisualParams = m_appearance.VisualParams; - - if (m_appearance.Texture != null) - cAgent.AgentTextures = m_appearance.Texture.GetBytes(); - } - catch (Exception e) - { - m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message); - } - - //Attachments - List attPoints = m_appearance.GetAttachedPoints(); - if (attPoints != null) - { - //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count); - int i = 0; - AttachmentData[] attachs = new AttachmentData[attPoints.Count]; - foreach (int point in attPoints) - { - attachs[i++] = new AttachmentData(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point)); - } - cAgent.Attachments = attachs; - } - - lock (scriptedcontrols) - { - ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; - int i = 0; - - foreach (ScriptControllers c in scriptedcontrols.Values) - { - controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); - } - cAgent.Controllers = controls; - } - - // Animations - try - { - cAgent.Anims = Animator.Animations.ToArray(); - } - catch { } - - // cAgent.GroupID = ?? - // Groups??? - - } - - public void CopyFrom(AgentData cAgent) - { - m_originRegionID = cAgent.RegionID; - - m_callbackURI = cAgent.CallbackURI; - - m_pos = cAgent.Position; - - m_velocity = cAgent.Velocity; - m_CameraCenter = cAgent.Center; - //m_avHeight = cAgent.Size.Z; - m_CameraAtAxis = cAgent.AtAxis; - m_CameraLeftAxis = cAgent.LeftAxis; - m_CameraUpAxis = cAgent.UpAxis; - - m_DrawDistance = cAgent.Far; - - if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) - ControllingClient.SetChildAgentThrottle(cAgent.Throttles); - - m_headrotation = cAgent.HeadRotation; - m_bodyRot = cAgent.BodyRotation; - m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; - - if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) - m_godLevel = cAgent.GodLevel; - m_setAlwaysRun = cAgent.AlwaysRun; - - uint i = 0; - try - { - if (cAgent.Wearables == null) - cAgent.Wearables = new UUID[0]; - AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2]; - for (uint n = 0; n < cAgent.Wearables.Length; n += 2) - { - UUID itemId = cAgent.Wearables[n]; - UUID assetId = cAgent.Wearables[n + 1]; - wears[i++] = new AvatarWearable(itemId, assetId); - } - m_appearance.Wearables = wears; - Primitive.TextureEntry te; - if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1) - te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); - else - te = AvatarAppearance.GetDefaultTexture(); - if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) - cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams(); - m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone()); - } - catch (Exception e) - { - m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message); - } - - // Attachments - try - { - if (cAgent.Attachments != null) - { - m_appearance.ClearAttachments(); - foreach (AttachmentData att in cAgent.Attachments) - { - m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); - } - } - } - catch { } - - try - { - lock (scriptedcontrols) - { - if (cAgent.Controllers != null) - { - scriptedcontrols.Clear(); - - foreach (ControllerData c in cAgent.Controllers) - { - ScriptControllers sc = new ScriptControllers(); - sc.itemID = c.ItemID; - sc.ignoreControls = (ScriptControlled)c.IgnoreControls; - sc.eventControls = (ScriptControlled)c.EventControls; - - scriptedcontrols[sc.itemID] = sc; - } - } - } - } - catch { } - // Animations - try - { - Animator.ResetAnimations(); - Animator.Animations.FromArray(cAgent.Anims); - } - catch { } - - //cAgent.GroupID = ?? - //Groups??? - } - - public bool CopyAgent(out IAgentData agent) - { - agent = new CompleteAgentData(); - CopyTo((AgentData)agent); - return true; - } - - #endregion Child Agent Updates - - /// - /// Handles part of the PID controller function for moving an avatar. - /// - public override void UpdateMovement() - { - if (m_forceToApply.HasValue) - { - - Vector3 force = m_forceToApply.Value; - m_updateflag = true; - Velocity = force; - - m_forceToApply = null; - } - else - { - if (m_isNudging) - { - Vector3 force = Vector3.Zero; - - m_updateflag = true; - Velocity = force; - m_isNudging = false; - m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND" - } - } - } - - public override void SetText(string text, Vector3 color, double alpha) - { - throw new Exception("Can't set Text on avatar."); - } - - /// - /// Adds a physical representation of the avatar to the Physics plugin - /// - public void AddToPhysicalScene(bool isFlying) - { - PhysicsScene scene = m_scene.PhysicsScene; - - Vector3 pVec = AbsolutePosition; - - // Old bug where the height was in centimeters instead of meters - if (m_avHeight == 127.0f) - { - m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new Vector3(0f, 0f, 1.56f), - isFlying); - } - else - { - m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, - new Vector3(0f, 0f, m_avHeight), isFlying); - } - scene.AddPhysicsActorTaint(m_physicsActor); - //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; - m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; - m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong - m_physicsActor.SubscribeEvents(500); - m_physicsActor.LocalID = LocalId; - } - - private void OutOfBoundsCall(Vector3 pos) - { - //bool flying = m_physicsActor.Flying; - //RemoveFromPhysicalScene(); - - //AddToPhysicalScene(flying); - if (ControllingClient != null) - ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); - } - - // Event called by the physics plugin to tell the avatar about a collision. - private void PhysicsCollisionUpdate(EventArgs e) - { - if (e == null) - return; - - // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents( - // as of this comment the interval is set in AddToPhysicalScene - if (Animator!=null) - { - if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper, - { // else its will lock out other animation changes, like ground sit. - Animator.UpdateMovementAnimations(); - m_updateCount--; - } - } - - CollisionEventUpdate collisionData = (CollisionEventUpdate)e; - Dictionary coldata = collisionData.m_objCollisionList; - - CollisionPlane = Vector4.UnitW; - - if (m_lastColCount != coldata.Count) - { - m_updateCount = UPDATE_COUNT; - m_lastColCount = coldata.Count; - } - - if (coldata.Count != 0 && Animator != null) - { - switch (Animator.CurrentMovementAnimation) - { - case "STAND": - case "WALK": - case "RUN": - case "CROUCH": - case "CROUCHWALK": - { - ContactPoint lowest; - lowest.SurfaceNormal = Vector3.Zero; - lowest.Position = Vector3.Zero; - lowest.Position.Z = Single.NaN; - - foreach (ContactPoint contact in coldata.Values) - { - if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z) - { - lowest = contact; - } - } - - CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal)); - } - break; - } - } - - List thisHitColliders = new List(); - List endedColliders = new List(); - List startedColliders = new List(); - - foreach (uint localid in coldata.Keys) - { - thisHitColliders.Add(localid); - if (!m_lastColliders.Contains(localid)) - { - startedColliders.Add(localid); - } - //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString()); - } - - // calculate things that ended colliding - foreach (uint localID in m_lastColliders) - { - if (!thisHitColliders.Contains(localID)) - { - endedColliders.Add(localID); - } - } - //add the items that started colliding this time to the last colliders list. - foreach (uint localID in startedColliders) - { - m_lastColliders.Add(localID); - } - // remove things that ended colliding from the last colliders list - foreach (uint localID in endedColliders) - { - m_lastColliders.Remove(localID); - } - - // do event notification - if (startedColliders.Count > 0) - { - ColliderArgs StartCollidingMessage = new ColliderArgs(); - List colliding = new List(); - foreach (uint localId in startedColliders) - { - if (localId == 0) - continue; - - SceneObjectPart obj = Scene.GetSceneObjectPart(localId); - string data = ""; - if (obj != null) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = obj.UUID; - detobj.nameStr = obj.Name; - detobj.ownerUUID = obj.OwnerID; - detobj.posVector = obj.AbsolutePosition; - detobj.rotQuat = obj.GetWorldRotation(); - detobj.velVector = obj.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = obj.GroupID; - colliding.Add(detobj); - } - } - - if (colliding.Count > 0) - { - StartCollidingMessage.Colliders = colliding; - - foreach (SceneObjectGroup att in Attachments) - Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage); - } - } - - if (endedColliders.Count > 0) - { - ColliderArgs EndCollidingMessage = new ColliderArgs(); - List colliding = new List(); - foreach (uint localId in endedColliders) - { - if (localId == 0) - continue; - - SceneObjectPart obj = Scene.GetSceneObjectPart(localId); - string data = ""; - if (obj != null) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = obj.UUID; - detobj.nameStr = obj.Name; - detobj.ownerUUID = obj.OwnerID; - detobj.posVector = obj.AbsolutePosition; - detobj.rotQuat = obj.GetWorldRotation(); - detobj.velVector = obj.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = obj.GroupID; - colliding.Add(detobj); - } - } - - if (colliding.Count > 0) - { - EndCollidingMessage.Colliders = colliding; - - foreach (SceneObjectGroup att in Attachments) - Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage); - } - } - - if (thisHitColliders.Count > 0) - { - ColliderArgs CollidingMessage = new ColliderArgs(); - List colliding = new List(); - foreach (uint localId in thisHitColliders) - { - if (localId == 0) - continue; - - SceneObjectPart obj = Scene.GetSceneObjectPart(localId); - string data = ""; - if (obj != null) - { - DetectedObject detobj = new DetectedObject(); - detobj.keyUUID = obj.UUID; - detobj.nameStr = obj.Name; - detobj.ownerUUID = obj.OwnerID; - detobj.posVector = obj.AbsolutePosition; - detobj.rotQuat = obj.GetWorldRotation(); - detobj.velVector = obj.Velocity; - detobj.colliderType = 0; - detobj.groupUUID = obj.GroupID; - colliding.Add(detobj); - } - } - - if (colliding.Count > 0) - { - CollidingMessage.Colliders = colliding; - - lock (m_attachments) - { - foreach (SceneObjectGroup att in m_attachments) - Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage); - } - } - } - - if (m_invulnerable) - return; - - float starthealth = Health; - uint killerObj = 0; - foreach (uint localid in coldata.Keys) - { - SceneObjectPart part = Scene.GetSceneObjectPart(localid); - - if (part != null && part.ParentGroup.Damage != -1.0f) - Health -= part.ParentGroup.Damage; - else - { - if (coldata[localid].PenetrationDepth >= 0.10f) - Health -= coldata[localid].PenetrationDepth * 5.0f; - } - - if (Health <= 0.0f) - { - if (localid != 0) - killerObj = localid; - } - //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString()); - } - //Health = 100; - if (!m_invulnerable) - { - if (starthealth != Health) - { - ControllingClient.SendHealth(Health); - } - if (m_health <= 0) - m_scene.EventManager.TriggerAvatarKill(killerObj, this); - } - } - - public void setHealthWithUpdate(float health) - { - Health = health; - ControllingClient.SendHealth(Health); - } - - public void Close() - { - lock (m_attachments) - { - // Delete attachments from scene - // Don't try to save, as this thread won't live long - // enough to complete the save. This would cause no copy - // attachments to poof! - // - foreach (SceneObjectGroup grp in m_attachments) - { - m_scene.DeleteSceneObject(grp, false); - } - m_attachments.Clear(); - } - - lock (m_knownChildRegions) - { - m_knownChildRegions.Clear(); - } - - lock (m_reprioritization_timer) - { - m_reprioritization_timer.Enabled = false; - m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize); - } - - // I don't get it but mono crashes when you try to dispose of this timer, - // unsetting the elapsed callback should be enough to allow for cleanup however. - // m_reprioritizationTimer.Dispose(); - - m_sceneViewer.Close(); - - RemoveFromPhysicalScene(); - m_animator.Close(); - m_animator = null; - } - - public void AddAttachment(SceneObjectGroup gobj) - { - lock (m_attachments) - { - m_attachments.Add(gobj); - } - } - - public bool HasAttachments() - { - return m_attachments.Count > 0; - } - - public bool HasScriptedAttachments() - { - lock (m_attachments) - { - foreach (SceneObjectGroup gobj in m_attachments) - { - if (gobj != null) - { - if (gobj.RootPart.Inventory.ContainsScripts()) - return true; - } - } - } - return false; - } - - public void RemoveAttachment(SceneObjectGroup gobj) - { - lock (m_attachments) - { - if (m_attachments.Contains(gobj)) - { - m_attachments.Remove(gobj); - } - } - } - - public bool ValidateAttachments() - { - lock (m_attachments) - { - // Validate - foreach (SceneObjectGroup gobj in m_attachments) - { - if (gobj == null) - return false; - - if (gobj.IsDeleted) - return false; - } - } - return true; - } - - /// - /// Send a script event to this scene presence's attachments - /// - /// The name of the event - /// The arguments for the event - public void SendScriptEventToAttachments(string eventName, Object[] args) - { - if (m_scriptEngines != null) - { - lock (m_attachments) - { - foreach (SceneObjectGroup grp in m_attachments) - { - // 16384 is CHANGED_ANIMATION - // - // Send this to all attachment root prims - // - foreach (IScriptModule m in m_scriptEngines) - { - if (m == null) // No script engine loaded - continue; - - m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION }); - } - } - } - } - } - - - public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene) - { - m_controllingClient = client; - m_regionInfo = region; - m_scene = scene; - - RegisterToEvents(); - if (m_controllingClient != null) - { - m_controllingClient.ProcessPendingPackets(); - } - /* - AbsolutePosition = client.StartPos; - - Animations = new AvatarAnimations(); - Animations.LoadAnims(); - - m_animations = new List(); - m_animations.Add(Animations.AnimsUUID["STAND"]); - m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber); - - SetDirectionVectors(); - */ - } - - internal void PushForce(Vector3 impulse) - { - if (PhysicsActor != null) - { - PhysicsActor.AddForce(impulse,true); - } - } - - public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) - { - ScriptControllers obj = new ScriptControllers(); - obj.ignoreControls = ScriptControlled.CONTROL_ZERO; - obj.eventControls = ScriptControlled.CONTROL_ZERO; - - obj.itemID = Script_item_UUID; - if (pass_on == 0 && accept == 0) - { - IgnoredControls |= (ScriptControlled)controls; - obj.ignoreControls = (ScriptControlled)controls; - } - - if (pass_on == 0 && accept == 1) - { - IgnoredControls |= (ScriptControlled)controls; - obj.ignoreControls = (ScriptControlled)controls; - obj.eventControls = (ScriptControlled)controls; - } - if (pass_on == 1 && accept == 1) - { - IgnoredControls = ScriptControlled.CONTROL_ZERO; - obj.eventControls = (ScriptControlled)controls; - obj.ignoreControls = ScriptControlled.CONTROL_ZERO; - } - - lock (scriptedcontrols) - { - if (pass_on == 1 && accept == 0) - { - IgnoredControls &= ~(ScriptControlled)controls; - if (scriptedcontrols.ContainsKey(Script_item_UUID)) - scriptedcontrols.Remove(Script_item_UUID); - } - else - { - scriptedcontrols[Script_item_UUID] = obj; - } - } - ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); - } - - public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID) - { - IgnoredControls = ScriptControlled.CONTROL_ZERO; - lock (scriptedcontrols) - { - scriptedcontrols.Clear(); - } - ControllingClient.SendTakeControls(int.MaxValue, false, false); - } - - public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) - { - ScriptControllers takecontrols; - - lock (scriptedcontrols) - { - if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols)) - { - ScriptControlled sctc = takecontrols.eventControls; - - ControllingClient.SendTakeControls((int)sctc, false, false); - ControllingClient.SendTakeControls((int)sctc, true, false); - - scriptedcontrols.Remove(Script_item_UUID); - IgnoredControls = ScriptControlled.CONTROL_ZERO; - foreach (ScriptControllers scData in scriptedcontrols.Values) - { - IgnoredControls |= scData.ignoreControls; - } - } - } - } - - internal void SendControlToScripts(uint flags) - { - ScriptControlled allflags = ScriptControlled.CONTROL_ZERO; - - if (MouseDown) - { - allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0) - { - allflags = ScriptControlled.CONTROL_ZERO; - MouseDown = true; - } - } - - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0) - { - allflags |= ScriptControlled.CONTROL_ML_LBUTTON; - MouseDown = true; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0) - { - allflags |= ScriptControlled.CONTROL_LBUTTON; - MouseDown = true; - } - - // find all activated controls, whether the scripts are interested in them or not - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0) - { - allflags |= ScriptControlled.CONTROL_FWD; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0) - { - allflags |= ScriptControlled.CONTROL_BACK; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0) - { - allflags |= ScriptControlled.CONTROL_UP; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0) - { - allflags |= ScriptControlled.CONTROL_DOWN; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0) - { - allflags |= ScriptControlled.CONTROL_LEFT; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0) - { - allflags |= ScriptControlled.CONTROL_RIGHT; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) - { - allflags |= ScriptControlled.CONTROL_ROT_RIGHT; - } - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) - { - allflags |= ScriptControlled.CONTROL_ROT_LEFT; - } - // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that - if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands) - { - lock (scriptedcontrols) - { - foreach (KeyValuePair kvp in scriptedcontrols) - { - UUID scriptUUID = kvp.Key; - ScriptControllers scriptControlData = kvp.Value; - - ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us - ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle - ScriptControlled localChange = localHeld ^ localLast; // the changed bits - if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO) - { - // only send if still pressed or just changed - m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange); - } - } - } - } - - LastCommands = allflags; - } - - internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored) - { - if (ignored == ScriptControlled.CONTROL_ZERO) - return flags; - - if ((ignored & ScriptControlled.CONTROL_BACK) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); - if ((ignored & ScriptControlled.CONTROL_FWD) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS); - if ((ignored & ScriptControlled.CONTROL_DOWN) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG); - if ((ignored & ScriptControlled.CONTROL_UP) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS); - if ((ignored & ScriptControlled.CONTROL_LEFT) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); - if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG); - if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG); - if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS); - if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN); - if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0) - flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN); - - //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, - //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, - //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, - //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, - //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, - //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, - //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG - - return flags; - } - - /// - /// RezAttachments. This should only be called upon login on the first region. - /// Attachment rezzings on crossings and TPs are done in a different way. - /// - public void RezAttachments() - { - if (null == m_appearance) - { - m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID); - return; - } - - XmlDocument doc = new XmlDocument(); - string stateData = String.Empty; - - IAttachmentsService attServ = m_scene.RequestModuleInterface(); - if (attServ != null) - { - m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service"); - stateData = attServ.Get(ControllingClient.AgentId.ToString()); - if (stateData != String.Empty) - { - try - { - doc.LoadXml(stateData); - } - catch { } - } - } - - Dictionary itemData = new Dictionary(); - - XmlNodeList nodes = doc.GetElementsByTagName("Attachment"); - if (nodes.Count > 0) - { - foreach (XmlNode n in nodes) - { - XmlElement elem = (XmlElement)n; - string itemID = elem.GetAttribute("ItemID"); - string xml = elem.InnerXml; - - itemData[new UUID(itemID)] = xml; - } - } - - List attPoints = m_appearance.GetAttachedPoints(); - foreach (int p in attPoints) - { - if (m_isDeleted) - return; - - UUID itemID = m_appearance.GetAttachedItem(p); - UUID assetID = m_appearance.GetAttachedAsset(p); - - // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down - // But they're not used anyway, the item is being looked up for now, so let's proceed. - //if (UUID.Zero == assetID) - //{ - // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); - // continue; - //} - - try - { - string xmlData; - XmlDocument d = new XmlDocument(); - UUID asset; - if (itemData.TryGetValue(itemID, out xmlData)) - { - d.LoadXml(xmlData); - m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID); - - // Rez from inventory - asset - = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d); - - } - else - { - // Rez from inventory (with a null doc to let - // CHANGED_OWNER happen) - asset - = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null); - } - - m_log.InfoFormat( - "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", - p, itemID, assetID, asset); - } - catch (Exception e) - { - m_log.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}", e.ToString()); - } - } - } - - private void ReprioritizeUpdates() - { - if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time) - { - lock (m_reprioritization_timer) - { - if (!m_reprioritizing) - m_reprioritization_timer.Enabled = m_reprioritizing = true; - else - m_reprioritization_called = true; - } - } - } - - private void Reprioritize(object sender, ElapsedEventArgs e) - { - m_controllingClient.ReprioritizeUpdates(); - - lock (m_reprioritization_timer) - { - m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called; - m_reprioritization_called = false; - } - } - - private Vector3 Quat2Euler(Quaternion rot){ - float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) , - (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z))); - float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W))); - float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) , - (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z))); - return(new Vector3(x,y,z)); - } - - - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Xml; +using System.Collections.Generic; +using System.Reflection; +using System.Timers; +using OpenMetaverse; +using log4net; +using OpenSim.Framework; +using OpenSim.Framework.Client; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes.Animation; +using OpenSim.Region.Framework.Scenes.Types; +using OpenSim.Region.Physics.Manager; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using OpenSim.Services.Interfaces; + +namespace OpenSim.Region.Framework.Scenes +{ + enum ScriptControlled : uint + { + CONTROL_ZERO = 0, + CONTROL_FWD = 1, + CONTROL_BACK = 2, + CONTROL_LEFT = 4, + CONTROL_RIGHT = 8, + CONTROL_UP = 16, + CONTROL_DOWN = 32, + CONTROL_ROT_LEFT = 256, + CONTROL_ROT_RIGHT = 512, + CONTROL_LBUTTON = 268435456, + CONTROL_ML_LBUTTON = 1073741824 + } + + struct ScriptControllers + { + public UUID itemID; + public ScriptControlled ignoreControls; + public ScriptControlled eventControls; + } + + public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); + + public class ScenePresence : EntityBase, ISceneEntity + { +// ~ScenePresence() +// { +// m_log.Debug("[ScenePresence] Destructor called"); +// } + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 }; +// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); + private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags)); + private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f); + + /// + /// Experimentally determined "fudge factor" to make sit-target positions + /// the same as in SecondLife. Fudge factor was tested for 36 different + /// test cases including prims of type box, sphere, cylinder, and torus, + /// with varying parameters for sit target location, prim size, prim + /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis + /// issue #1716 + /// +// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); + // Value revised by KF 091121 by comparison with SL. + private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); + + public UUID currentParcelUUID = UUID.Zero; + + private ISceneViewer m_sceneViewer; + + /// + /// The animator for this avatar + /// + public ScenePresenceAnimator Animator + { + get { return m_animator; } + } + protected ScenePresenceAnimator m_animator; + + /// + /// The scene objects attached to this avatar. Do not change this list directly - use methods such as + /// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it. + /// + public List Attachments + { + get { return m_attachments; } + } + protected List m_attachments = new List(); + + private Dictionary scriptedcontrols = new Dictionary(); + private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; + private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; + private bool MouseDown = false; + private SceneObjectGroup proxyObjectGroup; + //private SceneObjectPart proxyObjectPart = null; + public Vector3 lastKnownAllowedPosition; + public bool sentMessageAboutRestrictedParcelFlyingDown; + public Vector4 CollisionPlane = Vector4.UnitW; + + private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation + private Vector3 m_avUnscriptedSitPos; // for non-scripted prims + private Vector3 m_lastPosition; + private Vector3 m_lastWorldPosition; + private Quaternion m_lastRotation; + private Vector3 m_lastVelocity; + //private int m_lastTerseSent; + + private bool m_updateflag; + private byte m_movementflag; + private Vector3? m_forceToApply; + private uint m_requestedSitTargetID; + private UUID m_requestedSitTargetUUID; + public bool SitGround = false; + + private SendCourseLocationsMethod m_sendCourseLocationsMethod; + + private bool m_startAnimationSet; + + //private Vector3 m_requestedSitOffset = new Vector3(); + + private Vector3 m_LastFinitePos; + + private float m_sitAvatarHeight = 2.0f; + + private int m_godLevel; + private int m_userLevel; + + private bool m_invulnerable = true; + + private Vector3 m_lastChildAgentUpdatePosition; + private Vector3 m_lastChildAgentUpdateCamPosition; + + private int m_perfMonMS; + + private bool m_setAlwaysRun; + private bool m_forceFly; + private bool m_flyDisabled; + + private float m_speedModifier = 1.0f; + + private Quaternion m_bodyRot= Quaternion.Identity; + + private Quaternion m_bodyRotPrevious = Quaternion.Identity; + + private const int LAND_VELOCITYMAG_MAX = 12; + + public bool IsRestrictedToRegion; + + public string JID = String.Empty; + + private float m_health = 100f; + + // Default AV Height + private float m_avHeight = 127.0f; + + protected RegionInfo m_regionInfo; + protected ulong crossingFromRegion; + + private readonly Vector3[] Dir_Vectors = new Vector3[11]; + private bool m_isNudging = false; + + // Position of agent's camera in world (region cordinates) + protected Vector3 m_CameraCenter; + protected Vector3 m_lastCameraCenter; + + protected Timer m_reprioritization_timer; + protected bool m_reprioritizing; + protected bool m_reprioritization_called; + + // Use these three vectors to figure out what the agent is looking at + // Convert it to a Matrix and/or Quaternion + protected Vector3 m_CameraAtAxis; + protected Vector3 m_CameraLeftAxis; + protected Vector3 m_CameraUpAxis; + private AgentManager.ControlFlags m_AgentControlFlags; + private Quaternion m_headrotation = Quaternion.Identity; + private byte m_state; + + //Reuse the Vector3 instead of creating a new one on the UpdateMovement method +// private Vector3 movementvector; + + private bool m_autopilotMoving; + private Vector3 m_autoPilotTarget; + private bool m_sitAtAutoTarget; + private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit + + private string m_nextSitAnimation = String.Empty; + + //PauPaw:Proper PID Controler for autopilot************ + private bool m_moveToPositionInProgress; + private Vector3 m_moveToPositionTarget; + private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + + private bool m_followCamAuto; + + private int m_movementUpdateCount; + private int m_lastColCount = -1; //KF: Look for Collision chnages + private int m_updateCount = 0; //KF: Update Anims for a while + private static readonly int UPDATE_COUNT = 10; // how many frames to update for + private const int NumMovementsBetweenRayCast = 5; + private List m_lastColliders = new List(); + + private bool CameraConstraintActive; + //private int m_moveToPositionStateStatus; + //***************************************************** + + // Agent's Draw distance. + protected float m_DrawDistance; + + protected AvatarAppearance m_appearance; + + // neighbouring regions we have enabled a child agent in + // holds the seed cap for the child agent in that region + private Dictionary m_knownChildRegions = new Dictionary(); + + /// + /// Implemented Control Flags + /// + private enum Dir_ControlFlags + { + DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, + DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, + DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, + DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, + DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, + DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, + DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, + DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, + DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, + DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, + DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG + } + + /// + /// Position at which a significant movement was made + /// + private Vector3 posLastSignificantMove; + + // For teleports and crossings callbacks + string m_callbackURI; + UUID m_originRegionID; + + ulong m_rootRegionHandle; + + /// + /// Script engines present in the scene + /// + private IScriptModule[] m_scriptEngines; + + #region Properties + + /// + /// Physical scene representation of this Avatar. + /// + public PhysicsActor PhysicsActor + { + set { m_physicsActor = value; } + get { return m_physicsActor; } + } + + public byte MovementFlag + { + set { m_movementflag = value; } + get { return m_movementflag; } + } + + public bool Updated + { + set { m_updateflag = value; } + get { return m_updateflag; } + } + + public bool Invulnerable + { + set { m_invulnerable = value; } + get { return m_invulnerable; } + } + + public int UserLevel + { + get { return m_userLevel; } + } + + public int GodLevel + { + get { return m_godLevel; } + } + + public ulong RegionHandle + { + get { return m_rootRegionHandle; } + } + + public Vector3 CameraPosition + { + get { return m_CameraCenter; } + } + + public Quaternion CameraRotation + { + get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); } + } + + public Vector3 CameraAtAxis + { + get { return m_CameraAtAxis; } + } + + public Vector3 CameraLeftAxis + { + get { return m_CameraLeftAxis; } + } + + public Vector3 CameraUpAxis + { + get { return m_CameraUpAxis; } + } + + public Vector3 Lookat + { + get + { + Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0); + + if (a == Vector3.Zero) + return a; + + return Util.GetNormalizedVector(a); + } + } + + private readonly string m_firstname; + + public string Firstname + { + get { return m_firstname; } + } + + private readonly string m_lastname; + + public string Lastname + { + get { return m_lastname; } + } + + private string m_grouptitle; + + public string Grouptitle + { + get { return m_grouptitle; } + set { m_grouptitle = value; } + } + + public float DrawDistance + { + get { return m_DrawDistance; } + } + + protected bool m_allowMovement = true; + + public bool AllowMovement + { + get { return m_allowMovement; } + set { m_allowMovement = value; } + } + + public bool SetAlwaysRun + { + get + { + if (PhysicsActor != null) + { + return PhysicsActor.SetAlwaysRun; + } + else + { + return m_setAlwaysRun; + } + } + set + { + m_setAlwaysRun = value; + if (PhysicsActor != null) + { + PhysicsActor.SetAlwaysRun = value; + } + } + } + + public byte State + { + get { return m_state; } + set { m_state = value; } + } + + public uint AgentControlFlags + { + get { return (uint)m_AgentControlFlags; } + set { m_AgentControlFlags = (AgentManager.ControlFlags)value; } + } + + /// + /// This works out to be the ClientView object associated with this avatar, or it's client connection manager + /// + private IClientAPI m_controllingClient; + + protected PhysicsActor m_physicsActor; + + /// + /// The client controlling this presence + /// + public IClientAPI ControllingClient + { + get { return m_controllingClient; } + } + + public IClientCore ClientView + { + get { return (IClientCore) m_controllingClient; } + } + + protected Vector3 m_parentPosition; + public Vector3 ParentPosition + { + get { return m_parentPosition; } + set { m_parentPosition = value; } + } + + /// + /// Position of this avatar relative to the region the avatar is in + /// + public override Vector3 AbsolutePosition + { + get + { + PhysicsActor actor = m_physicsActor; +// if (actor != null) + if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting! + m_pos = actor.Position; + + // If we're sitting, we need to update our position + if (m_parentID != 0) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); + if (part != null) + m_parentPosition = part.AbsolutePosition; + } + + return m_parentPosition + m_pos; + } + set + { + PhysicsActor actor = m_physicsActor; + if (actor != null) + { + try + { + lock (m_scene.SyncRoot) + m_physicsActor.Position = value; + } + catch (Exception e) + { + m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message); + } + } + + if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting! + m_pos = value; + m_parentPosition = Vector3.Zero; + } + } + + public Vector3 OffsetPosition + { + get { return m_pos; } + set { m_pos = value; } + } + + /// + /// Current velocity of the avatar. + /// + public override Vector3 Velocity + { + get + { + PhysicsActor actor = m_physicsActor; + if (actor != null) + m_velocity = actor.Velocity; + + return m_velocity; + } + set + { + PhysicsActor actor = m_physicsActor; + if (actor != null) + { + try + { + lock (m_scene.SyncRoot) + actor.Velocity = value; + } + catch (Exception e) + { + m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message); + } + } + + m_velocity = value; + } + } + + public Quaternion OffsetRotation + { + get { return m_offsetRotation; } + set { m_offsetRotation = value; } + } + + public Quaternion Rotation + { + get { + if (m_parentID != 0) + { + if (m_offsetRotation != null) + { + return m_offsetRotation; + } + else + { + return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + + } + else + { + return m_bodyRot; + } + } + set { + m_bodyRot = value; + if (m_parentID != 0) + { + m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + } + } + + public Quaternion PreviousRotation + { + get { return m_bodyRotPrevious; } + set { m_bodyRotPrevious = value; } + } + + /// + /// If this is true, agent doesn't have a representation in this scene. + /// this is an agent 'looking into' this scene from a nearby scene(region) + /// + /// if False, this agent has a representation in this scene + /// + private bool m_isChildAgent = true; + + public bool IsChildAgent + { + get { return m_isChildAgent; } + set { m_isChildAgent = value; } + } + + private uint m_parentID; + + + private UUID m_linkedPrim; + + public uint ParentID + { + get { return m_parentID; } + set { m_parentID = value; } + } + + public UUID LinkedPrim + { + get { return m_linkedPrim; } + set { m_linkedPrim = value; } + } + + public float Health + { + get { return m_health; } + set { m_health = value; } + } + + /// + /// These are the region handles known by the avatar. + /// + public List KnownChildRegionHandles + { + get + { + if (m_knownChildRegions.Count == 0) + return new List(); + else + return new List(m_knownChildRegions.Keys); + } + } + + public Dictionary KnownRegions + { + get { return m_knownChildRegions; } + set + { + m_knownChildRegions = value; + } + } + + public ISceneViewer SceneViewer + { + get { return m_sceneViewer; } + } + + public void AdjustKnownSeeds() + { + Dictionary seeds; + + if (Scene.CapsModule != null) + seeds = Scene.CapsModule.GetChildrenSeeds(UUID); + else + seeds = new Dictionary(); + + List old = new List(); + foreach (ulong handle in seeds.Keys) + { + uint x, y; + Utils.LongToUInts(handle, out x, out y); + x = x / Constants.RegionSize; + y = y / Constants.RegionSize; + if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY)) + { + old.Add(handle); + } + } + DropOldNeighbours(old); + + if (Scene.CapsModule != null) + Scene.CapsModule.SetChildrenSeed(UUID, seeds); + + KnownRegions = seeds; + //m_log.Debug(" ++++++++++AFTER+++++++++++++ "); + //DumpKnownRegions(); + } + + public void DumpKnownRegions() + { + m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================"); + foreach (KeyValuePair kvp in KnownRegions) + { + uint x, y; + Utils.LongToUInts(kvp.Key, out x, out y); + x = x / Constants.RegionSize; + y = y / Constants.RegionSize; + m_log.Info(" >> "+x+", "+y+": "+kvp.Value); + } + } + + private bool m_inTransit; + private bool m_mouseLook; + private bool m_leftButtonDown; + + public bool IsInTransit + { + get { return m_inTransit; } + set { m_inTransit = value; } + } + + public float SpeedModifier + { + get { return m_speedModifier; } + set { m_speedModifier = value; } + } + + public bool ForceFly + { + get { return m_forceFly; } + set { m_forceFly = value; } + } + + public bool FlyDisabled + { + get { return m_flyDisabled; } + set { m_flyDisabled = value; } + } + + public string Viewer + { + get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; } + } + + #endregion + + #region Constructor(s) + + public ScenePresence() + { + m_sendCourseLocationsMethod = SendCoarseLocationsDefault; + CreateSceneViewer(); + m_animator = new ScenePresenceAnimator(this); + } + + private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() + { + m_rootRegionHandle = reginfo.RegionHandle; + m_controllingClient = client; + m_firstname = m_controllingClient.FirstName; + m_lastname = m_controllingClient.LastName; + m_name = String.Format("{0} {1}", m_firstname, m_lastname); + m_scene = world; + m_uuid = client.AgentId; + m_regionInfo = reginfo; + m_localId = m_scene.AllocateLocalId(); + + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); + + if (account != null) + m_userLevel = account.UserLevel; + + IGroupsModule gm = m_scene.RequestModuleInterface(); + if (gm != null) + m_grouptitle = gm.GetGroupTitle(m_uuid); + + m_scriptEngines = m_scene.RequestModuleInterfaces(); + + AbsolutePosition = posLastSignificantMove = m_CameraCenter = + m_lastCameraCenter = m_controllingClient.StartPos; + + m_reprioritization_timer = new Timer(world.ReprioritizationInterval); + m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize); + m_reprioritization_timer.AutoReset = false; + + AdjustKnownSeeds(); + Animator.TrySetMovementAnimation("STAND"); + // we created a new ScenePresence (a new child agent) in a fresh region. + // Request info about all the (root) agents in this region + // Note: This won't send data *to* other clients in that region (children don't send) + SendInitialFullUpdateToAllClients(); + RegisterToEvents(); + if (m_controllingClient != null) + { + m_controllingClient.ProcessPendingPackets(); + } + SetDirectionVectors(); + } + + public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams, + AvatarWearable[] wearables) + : this(client, world, reginfo) + { + m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams); + } + + public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance) + : this(client, world, reginfo) + { + m_appearance = appearance; + } + + private void CreateSceneViewer() + { + m_sceneViewer = new SceneViewer(this); + } + + public void RegisterToEvents() + { + m_controllingClient.OnRequestWearables += SendWearables; + m_controllingClient.OnSetAppearance += SetAppearance; + m_controllingClient.OnCompleteMovementToRegion += CompleteMovement; + //m_controllingClient.OnCompleteMovementToRegion += SendInitialData; + m_controllingClient.OnAgentUpdate += HandleAgentUpdate; + m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit; + m_controllingClient.OnAgentSit += HandleAgentSit; + m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; + m_controllingClient.OnStartAnim += HandleStartAnim; + m_controllingClient.OnStopAnim += HandleStopAnim; + m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls; + m_controllingClient.OnAutoPilotGo += DoAutoPilot; + m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition); + + // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); + // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); + } + + private void SetDirectionVectors() + { + Dir_Vectors[0] = Vector3.UnitX; //FORWARD + Dir_Vectors[1] = -Vector3.UnitX; //BACK + Dir_Vectors[2] = Vector3.UnitY; //LEFT + Dir_Vectors[3] = -Vector3.UnitY; //RIGHT + Dir_Vectors[4] = Vector3.UnitZ; //UP + Dir_Vectors[5] = -Vector3.UnitZ; //DOWN + Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE + Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE + Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE + Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE + Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge + } + + private Vector3[] GetWalkDirectionVectors() + { + Vector3[] vector = new Vector3[11]; + vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD + vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK + vector[2] = Vector3.UnitY; //LEFT + vector[3] = -Vector3.UnitY; //RIGHT + vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP + vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN + vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE + vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE + vector[8] = Vector3.UnitY; //LEFT_NUDGE + vector[9] = -Vector3.UnitY; //RIGHT_NUDGE + vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE + return vector; + } + + private bool[] GetDirectionIsNudge() + { + bool[] isNudge = new bool[11]; + isNudge[0] = false; //FORWARD + isNudge[1] = false; //BACK + isNudge[2] = false; //LEFT + isNudge[3] = false; //RIGHT + isNudge[4] = false; //UP + isNudge[5] = false; //DOWN + isNudge[6] = true; //FORWARD_NUDGE + isNudge[7] = true; //BACK_NUDGE + isNudge[8] = true; //LEFT_NUDGE + isNudge[9] = true; //RIGHT_NUDGE + isNudge[10] = true; //DOWN_Nudge + return isNudge; + } + + + #endregion + + public uint GenerateClientFlags(UUID ObjectID) + { + return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID); + } + + /// + /// Send updates to the client about prims which have been placed on the update queue. We don't + /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent + /// timestamp has already been sent. + /// + public void SendPrimUpdates() + { + m_perfMonMS = Util.EnvironmentTickCount(); + + m_sceneViewer.SendPrimUpdates(); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + #region Status Methods + + /// + /// This turns a child agent, into a root agent + /// This is called when an agent teleports into a region, or if an + /// agent crosses into this region from a neighbor over the border + /// + public void MakeRootAgent(Vector3 pos, bool isFlying) + { + m_log.DebugFormat( + "[SCENE]: Upgrading child to root agent for {0} in {1}", + Name, m_scene.RegionInfo.RegionName); + + //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); + + IGroupsModule gm = m_scene.RequestModuleInterface(); + if (gm != null) + m_grouptitle = gm.GetGroupTitle(m_uuid); + + m_rootRegionHandle = m_scene.RegionInfo.RegionHandle; + m_scene.SetRootAgentScene(m_uuid); + + // Moved this from SendInitialData to ensure that m_appearance is initialized + // before the inventory is processed in MakeRootAgent. This fixes a race condition + // related to the handling of attachments + //m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); + if (m_scene.TestBorderCross(pos, Cardinals.E)) + { + Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); + pos.X = crossedBorder.BorderLine.Z - 1; + } + + if (m_scene.TestBorderCross(pos, Cardinals.N)) + { + Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); + pos.Y = crossedBorder.BorderLine.Z - 1; + } + + //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet. + //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent, + //they'll bypass the landing point. But I can't think of any decent way of fixing this. + if (KnownChildRegionHandles.Count == 0) + { + ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); + if (land != null) + { + //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni. + if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid) + { + pos = land.LandData.UserLocation; + } + } + } + + if (pos.X < 0 || pos.Y < 0 || pos.Z < 0) + { + Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128); + + if (pos.X < 0) + { + emergencyPos.X = (int)Constants.RegionSize + pos.X; + if (!(pos.Y < 0)) + emergencyPos.Y = pos.Y; + if (!(pos.Z < 0)) + emergencyPos.Z = pos.Z; + } + if (pos.Y < 0) + { + emergencyPos.Y = (int)Constants.RegionSize + pos.Y; + if (!(pos.X < 0)) + emergencyPos.X = pos.X; + if (!(pos.Z < 0)) + emergencyPos.Z = pos.Z; + } + if (pos.Z < 0) + { + emergencyPos.Z = 128; + if (!(pos.Y < 0)) + emergencyPos.Y = pos.Y; + if (!(pos.X < 0)) + emergencyPos.X = pos.X; + } + } + + if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) + { + m_log.WarnFormat( + "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", + pos, Name, UUID); + + if (pos.X < 0f) pos.X = 0f; + if (pos.Y < 0f) pos.Y = 0f; + if (pos.Z < 0f) pos.Z = 0f; + } + + float localAVHeight = 1.56f; + if (m_avHeight != 127.0f) + { + localAVHeight = m_avHeight; + } + + float posZLimit = 0; + + if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) + posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; + + float newPosZ = posZLimit + localAVHeight / 2; + if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) + { + pos.Z = newPosZ; + } + AbsolutePosition = pos; + + AddToPhysicalScene(isFlying); + + if (m_forceFly) + { + m_physicsActor.Flying = true; + } + else if (m_flyDisabled) + { + m_physicsActor.Flying = false; + } + + if (m_appearance != null) + { + if (m_appearance.AvatarHeight > 0) + SetHeight(m_appearance.AvatarHeight); + } + else + { + m_log.ErrorFormat("[SCENE PRESENCE]: null appearance in MakeRoot in {0}", Scene.RegionInfo.RegionName); + // emergency; this really shouldn't happen + m_appearance = new AvatarAppearance(UUID); + } + + // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying + // avatar to return to the standing position in mid-air. On login it looks like this is being sent + // elsewhere anyway + // Animator.SendAnimPack(); + + m_scene.SwapRootAgentCount(false); + + //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid); + //if (userInfo != null) + // userInfo.FetchInventory(); + //else + // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid); + + // On the next prim update, all objects will be sent + // + m_sceneViewer.Reset(); + + m_isChildAgent = false; + + // send the animations of the other presences to me + m_scene.ForEachScenePresence(delegate(ScenePresence presence) + { + if (presence != this) + presence.Animator.SendAnimPackToClient(ControllingClient); + }); + + m_scene.EventManager.TriggerOnMakeRootAgent(this); + } + + /// + /// This turns a root agent into a child agent + /// when an agent departs this region for a neighbor, this gets called. + /// + /// It doesn't get called for a teleport. Reason being, an agent that + /// teleports out may not end up anywhere near this region + /// + public void MakeChildAgent() + { + // It looks like m_animator is set to null somewhere, and MakeChild + // is called after that. Probably in aborted teleports. + if (m_animator == null) + m_animator = new ScenePresenceAnimator(this); + else + Animator.ResetAnimations(); + +// m_log.DebugFormat( +// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", +// Name, UUID, m_scene.RegionInfo.RegionName); + + // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing, + // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated. + //Velocity = new Vector3(0, 0, 0); + + m_isChildAgent = true; + m_scene.SwapRootAgentCount(true); + RemoveFromPhysicalScene(); + + // FIXME: Set m_rootRegionHandle to the region handle of the scene this agent is moving into + + m_scene.EventManager.TriggerOnMakeChildAgent(this); + } + + /// + /// Removes physics plugin scene representation of this agent if it exists. + /// + private void RemoveFromPhysicalScene() + { + if (PhysicsActor != null) + { + m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; + m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; + m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); + m_physicsActor.UnSubscribeEvents(); + m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; + PhysicsActor = null; + } + } + + /// + /// + /// + /// + public void Teleport(Vector3 pos) + { + bool isFlying = false; + + if (m_physicsActor != null) + isFlying = m_physicsActor.Flying; + + RemoveFromPhysicalScene(); + Velocity = Vector3.Zero; + AbsolutePosition = pos; + AddToPhysicalScene(isFlying); + if (m_appearance != null) + { + if (m_appearance.AvatarHeight > 0) + SetHeight(m_appearance.AvatarHeight); + } + + SendTerseUpdateToAllClients(); + + } + + public void TeleportWithMomentum(Vector3 pos) + { + bool isFlying = false; + if (m_physicsActor != null) + isFlying = m_physicsActor.Flying; + + RemoveFromPhysicalScene(); + AbsolutePosition = pos; + AddToPhysicalScene(isFlying); + if (m_appearance != null) + { + if (m_appearance.AvatarHeight > 0) + SetHeight(m_appearance.AvatarHeight); + } + + SendTerseUpdateToAllClients(); + } + + /// + /// + /// + public void StopMovement() + { + } + + public void StopFlying() + { + ControllingClient.StopFlying(this); + } + + public void AddNeighbourRegion(ulong regionHandle, string cap) + { + lock (m_knownChildRegions) + { + if (!m_knownChildRegions.ContainsKey(regionHandle)) + { + uint x, y; + Utils.LongToUInts(regionHandle, out x, out y); + m_knownChildRegions.Add(regionHandle, cap); + } + } + } + + public void RemoveNeighbourRegion(ulong regionHandle) + { + lock (m_knownChildRegions) + { + if (m_knownChildRegions.ContainsKey(regionHandle)) + { + m_knownChildRegions.Remove(regionHandle); + //m_log.Debug(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); + } + } + } + + public void DropOldNeighbours(List oldRegions) + { + foreach (ulong handle in oldRegions) + { + RemoveNeighbourRegion(handle); + Scene.CapsModule.DropChildSeed(UUID, handle); + } + } + + public List GetKnownRegionList() + { + return new List(m_knownChildRegions.Keys); + } + + #endregion + + #region Event Handlers + + /// + /// Sets avatar height in the phyiscs plugin + /// + internal void SetHeight(float height) + { + m_avHeight = height; + if (PhysicsActor != null && !IsChildAgent) + { + Vector3 SetSize = new Vector3(0.45f, 0.6f, m_avHeight); + PhysicsActor.Size = SetSize; + } + } + + /// + /// Complete Avatar's movement into the region. + /// This is called upon a very important packet sent from the client, + /// so it's client-controlled. Never call this method directly. + /// + public void CompleteMovement(IClientAPI client) + { + //m_log.Debug("[SCENE PRESENCE]: CompleteMovement"); + + Vector3 look = Velocity; + if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) + { + look = new Vector3(0.99f, 0.042f, 0); + } + + // Prevent teleporting to an underground location + // (may crash client otherwise) + // + Vector3 pos = AbsolutePosition; + float ground = m_scene.GetGroundHeight(pos.X, pos.Y); + if (pos.Z < ground + 1.5f) + { + pos.Z = ground + 1.5f; + AbsolutePosition = pos; + } + m_isChildAgent = false; + bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + MakeRootAgent(AbsolutePosition, m_flying); + + if ((m_callbackURI != null) && !m_callbackURI.Equals("")) + { + m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI); + Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); + m_callbackURI = null; + } + + //m_log.DebugFormat("Completed movement"); + + m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); + SendInitialData(); + + // Create child agents in neighbouring regions + if (!m_isChildAgent) + { + IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); + if (m_agentTransfer != null) + m_agentTransfer.EnableChildAgents(this); + else + m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active"); + + IFriendsModule friendsModule = m_scene.RequestModuleInterface(); + if (friendsModule != null) + friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); + } + + } + + /// + /// Callback for the Camera view block check. Gets called with the results of the camera view block test + /// hitYN is true when there's something in the way. + /// + /// + /// + /// + /// + public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) + { + const float POSITION_TOLERANCE = 0.02f; + const float VELOCITY_TOLERANCE = 0.02f; + const float ROTATION_TOLERANCE = 0.02f; + + if (m_followCamAuto) + { + if (hitYN) + { + CameraConstraintActive = true; + //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance); + + Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint); + ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint))); + } + else + { + if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || + !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || + !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) + { + if (CameraConstraintActive) + { + ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f)); + CameraConstraintActive = false; + } + } + } + } + } + + /// + /// This is the event handler for client movement. If a client is moving, this event is triggering. + /// + public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) + { + //if (m_isChildAgent) + //{ + // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent"); + // return; + //} + + m_perfMonMS = Util.EnvironmentTickCount(); + + ++m_movementUpdateCount; + if (m_movementUpdateCount < 1) + m_movementUpdateCount = 1; + + #region Sanity Checking + + // This is irritating. Really. + if (!AbsolutePosition.IsFinite()) + { + RemoveFromPhysicalScene(); + m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); + + m_pos = m_LastFinitePos; + + if (!m_pos.IsFinite()) + { + m_pos.X = 127f; + m_pos.Y = 127f; + m_pos.Z = 127f; + m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); + } + + AddToPhysicalScene(false); + } + else + { + m_LastFinitePos = m_pos; + } + + #endregion Sanity Checking + + #region Inputs + + AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags; + Quaternion bodyRotation = agentData.BodyRotation; + + // Camera location in world. We'll need to raytrace + // from this location from time to time. + m_CameraCenter = agentData.CameraCenter; + if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance) + { + ReprioritizeUpdates(); + m_lastCameraCenter = m_CameraCenter; + } + + // Use these three vectors to figure out what the agent is looking at + // Convert it to a Matrix and/or Quaternion + m_CameraAtAxis = agentData.CameraAtAxis; + m_CameraLeftAxis = agentData.CameraLeftAxis; + m_CameraUpAxis = agentData.CameraUpAxis; + + // The Agent's Draw distance setting + m_DrawDistance = agentData.Far; + + // Check if Client has camera in 'follow cam' or 'build' mode. + Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation); + + m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f) + && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false; + + m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; + m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; + + #endregion Inputs + + if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) + { + StandUp(); + } + + //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto); + // Raycast from the avatar's head to the camera to see if there's anything blocking the view + if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast()) + { + if (m_followCamAuto) + { + Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; + m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); + } + } + lock (scriptedcontrols) + { + if (scriptedcontrols.Count > 0) + { + SendControlToScripts((uint)flags); + flags = RemoveIgnoredControls(flags, IgnoredControls); + } + } + + if (m_autopilotMoving) + CheckAtSitTarget(); + + if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) + { + m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. + Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); + + // TODO: This doesn't prevent the user from walking yet. + // Setting parent ID would fix this, if we knew what value + // to use. Or we could add a m_isSitting variable. + //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); + SitGround = true; + } + + // In the future, these values might need to go global. + // Here's where you get them. + m_AgentControlFlags = flags; + m_headrotation = agentData.HeadRotation; + m_state = agentData.State; + + PhysicsActor actor = PhysicsActor; + if (actor == null) + { + return; + } + + bool update_movementflag = false; + + if (m_allowMovement && !SitGround) + { + if (agentData.UseClientAgentPosition) + { + m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; + m_moveToPositionTarget = agentData.ClientAgentPosition; + } + + int i = 0; + + bool update_rotation = false; + bool DCFlagKeyPressed = false; + Vector3 agent_control_v3 = Vector3.Zero; + Quaternion q = bodyRotation; + + bool oldflying = PhysicsActor.Flying; + + if (m_forceFly) + actor.Flying = true; + else if (m_flyDisabled) + actor.Flying = false; + else + actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + + if (actor.Flying != oldflying) + update_movementflag = true; + + if (q != m_bodyRot) + { + m_bodyRot = q; + update_rotation = true; + } + + //guilty until proven innocent.. + bool Nudging = true; + //Basically, if there is at least one non-nudge control then we don't need + //to worry about stopping the avatar + + if (m_parentID == 0) + { + bool bAllowUpdateMoveToPosition = false; + bool bResetMoveToPosition = false; + + Vector3[] dirVectors; + + // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying + // this prevents 'jumping' in inappropriate situations. + if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying)) + dirVectors = GetWalkDirectionVectors(); + else + dirVectors = Dir_Vectors; + + bool[] isNudge = GetDirectionIsNudge(); + + + + + + foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) + { + if (((uint)flags & (uint)DCF) != 0) + { + bResetMoveToPosition = true; + DCFlagKeyPressed = true; + try + { + agent_control_v3 += dirVectors[i]; + if (isNudge[i] == false) + { + Nudging = false; + } + } + catch (IndexOutOfRangeException) + { + // Why did I get this? + } + + if ((m_movementflag & (uint)DCF) == 0) + { + m_movementflag += (byte)(uint)DCF; + update_movementflag = true; + } + } + else + { + if ((m_movementflag & (uint)DCF) != 0) + { + m_movementflag -= (byte)(uint)DCF; + update_movementflag = true; + } + else + { + bAllowUpdateMoveToPosition = true; + } + } + i++; + } + //Paupaw:Do Proper PID for Autopilot here + if (bResetMoveToPosition) + { + m_moveToPositionTarget = Vector3.Zero; + m_moveToPositionInProgress = false; + update_movementflag = true; + bAllowUpdateMoveToPosition = false; + } + + if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) + { + //Check the error term of the current position in relation to the target position + if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) + { + // we are close enough to the target + m_moveToPositionTarget = Vector3.Zero; + m_moveToPositionInProgress = false; + update_movementflag = true; + } + else + { + try + { + // move avatar in 2D at one meter/second towards target, in avatar coordinate frame. + // This movement vector gets added to the velocity through AddNewMovement(). + // Theoretically we might need a more complex PID approach here if other + // unknown forces are acting on the avatar and we need to adaptively respond + // to such forces, but the following simple approach seems to works fine. + Vector3 LocalVectorToTarget3D = + (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords + * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords + // Ignore z component of vector + Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); + LocalVectorToTarget2D.Normalize(); + + //We're not nudging + Nudging = false; + agent_control_v3 += LocalVectorToTarget2D; + + // update avatar movement flags. the avatar coordinate system is as follows: + // + // +X (forward) + // + // ^ + // | + // | + // | + // | + // (left) +Y <--------o--------> -Y + // avatar + // | + // | + // | + // | + // v + // -X + // + + // based on the above avatar coordinate system, classify the movement into + // one of left/right/back/forward. + if (LocalVectorToTarget2D.Y > 0)//MoveLeft + { + m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; + //AgentControlFlags + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; + update_movementflag = true; + } + else if (LocalVectorToTarget2D.Y < 0) //MoveRight + { + m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; + update_movementflag = true; + } + if (LocalVectorToTarget2D.X < 0) //MoveBack + { + m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; + update_movementflag = true; + } + else if (LocalVectorToTarget2D.X > 0) //Move Forward + { + m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; + AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; + update_movementflag = true; + } + } + catch (Exception e) + { + //Avoid system crash, can be slower but... + m_log.DebugFormat("Crash! {0}", e.ToString()); + } + } + } + } + + // Cause the avatar to stop flying if it's colliding + // with something with the down arrow pressed. + + // Only do this if we're flying + if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly) + { + // Landing detection code + + // Are the landing controls requirements filled? + bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || + ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); + + // Are the collision requirements fulfilled? + bool colliding = (m_physicsActor.IsColliding == true); + + if (m_physicsActor.Flying && colliding && controlland) + { + // nesting this check because LengthSquared() is expensive and we don't + // want to do it every step when flying. + if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX)) + StopFlying(); + } + } + + if (update_movementflag || (update_rotation && DCFlagKeyPressed)) + { + // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed)); + // m_log.DebugFormat( + // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); + + AddNewMovement(agent_control_v3, q, Nudging); + + + } + } + + if (update_movementflag && !SitGround) + Animator.UpdateMovementAnimations(); + + m_scene.EventManager.TriggerOnClientMovement(this); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client) + { + m_autopilotMoving = true; + m_autoPilotTarget = Pos; + m_sitAtAutoTarget = false; + PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; + //proxy.PCode = (byte)PCode.ParticleSystem; + proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); + proxyObjectGroup.AttachToScene(m_scene); + + // Commented out this code since it could never have executed, but might still be informative. +// if (proxyObjectGroup != null) +// { + proxyObjectGroup.SendGroupFullUpdate(); + remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); + m_scene.DeleteSceneObject(proxyObjectGroup, false); +// } +// else +// { +// m_autopilotMoving = false; +// m_autoPilotTarget = Vector3.Zero; +// ControllingClient.SendAlertMessage("Autopilot cancelled"); +// } + } + + public void DoMoveToPosition(Object sender, string method, List args) + { + try + { + float locx = 0f; + float locy = 0f; + float locz = 0f; + uint regionX = 0; + uint regionY = 0; + try + { + Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY); + locx = Convert.ToSingle(args[0]) - (float)regionX; + locy = Convert.ToSingle(args[1]) - (float)regionY; + locz = Convert.ToSingle(args[2]); + } + catch (InvalidCastException) + { + m_log.Error("[CLIENT]: Invalid autopilot request"); + return; + } + m_moveToPositionInProgress = true; + m_moveToPositionTarget = new Vector3(locx, locy, locz); + } + catch (Exception ex) + { + //Why did I get this error? + m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex); + } + } + + private void CheckAtSitTarget() + { + //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString()); + if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5) + { + if (m_sitAtAutoTarget) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID); + if (part != null) + { + AbsolutePosition = part.AbsolutePosition; + Velocity = Vector3.Zero; + SendFullUpdateToAllClients(); + + HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ?? + } + //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); + m_requestedSitTargetUUID = UUID.Zero; + } + /* + else + { + //ControllingClient.SendAlertMessage("Autopilot cancelled"); + //SendTerseUpdateToAllClients(); + //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; + //proxy.PCode = (byte)PCode.ParticleSystem; + ////uint nextUUID = m_scene.NextLocalId; + + //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy); + //if (proxyObjectGroup != null) + //{ + //proxyObjectGroup.SendGroupFullUpdate(); + //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false); + //m_scene.DeleteSceneObject(proxyObjectGroup); + //} + } + */ + m_autoPilotTarget = Vector3.Zero; + m_autopilotMoving = false; + } + } + /// + /// Perform the logic necessary to stand the avatar up. This method also executes + /// the stand animation. + /// + public void StandUp() + { + SitGround = false; + + if (m_parentID != 0) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); + if (part != null) + { + part.TaskInventory.LockItemsForRead(true); + TaskInventoryDictionary taskIDict = part.TaskInventory; + if (taskIDict != null) + { + foreach (UUID taskID in taskIDict.Keys) + { + UnRegisterControlEventsToScript(LocalId, taskID); + taskIDict[taskID].PermsMask &= ~( + 2048 | //PERMISSION_CONTROL_CAMERA + 4); // PERMISSION_TAKE_CONTROLS + } + } + part.TaskInventory.LockItemsForRead(false); + // Reset sit target. + if (part.GetAvatarOnSitTarget() == UUID) + part.SetAvatarOnSitTarget(UUID.Zero); + m_parentPosition = part.GetWorldPosition(); + ControllingClient.SendClearFollowCamProperties(part.ParentUUID); + } + // part.GetWorldRotation() is the rotation of the object being sat on + // Rotation is the sittiing Av's rotation + + Quaternion partRot; +// if (part.LinkNum == 1) +// { // Root prim of linkset +// partRot = part.ParentGroup.RootPart.RotationOffset; +// } +// else +// { // single or child prim + +// } + if (part == null) //CW: Part may be gone. llDie() for example. + { + partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + } + else + { + partRot = part.GetWorldRotation(); + } + + Quaternion partIRot = Quaternion.Inverse(partRot); + + Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av + Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av + + + if (m_physicsActor == null) + { + AddToPhysicalScene(false); + } + //CW: If the part isn't null then we can set the current position + if (part != null) + { + Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset! + AbsolutePosition = avWorldStandUp; //KF: Fix stand up. + part.IsOccupied = false; + part.ParentGroup.DeleteAvatar(ControllingClient.AgentId); + } + else + { + //CW: Since the part doesn't exist, a coarse standup position isn't an issue + AbsolutePosition = m_lastWorldPosition; + } + + m_parentPosition = Vector3.Zero; + m_parentID = 0; + m_linkedPrim = UUID.Zero; + m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); + SendFullUpdateToAllClients(); + m_requestedSitTargetID = 0; + + if ((m_physicsActor != null) && (m_avHeight > 0)) + { + SetHeight(m_avHeight); + } + } + Animator.TrySetMovementAnimation("STAND"); + } + + private SceneObjectPart FindNextAvailableSitTarget(UUID targetID) + { + SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID); + if (targetPart == null) + return null; + + // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used. + // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used. + + // Get our own copy of the part array, and sort into the order we want to test + SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts(); + Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2) + { + // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1) + int linkNum1 = p1==targetPart ? -1 : p1.LinkNum; + int linkNum2 = p2==targetPart ? -1 : p2.LinkNum; + return linkNum1 - linkNum2; + } + ); + + //look for prims with explicit sit targets that are available + foreach (SceneObjectPart part in partArray) + { + // Is a sit target available? + Vector3 avSitOffSet = part.SitTargetPosition; + Quaternion avSitOrientation = part.SitTargetOrientation; + UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); + bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero); + bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. + if (SitTargetisSet && !SitTargetOccupied) + { + //switch the target to this prim + return part; + } + } + + // no explicit sit target found - use original target + return targetPart; + } + + private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) + { + bool autopilot = true; + Vector3 autopilotTarget = new Vector3(); + Quaternion sitOrientation = Quaternion.Identity; + Vector3 pos = new Vector3(); + Vector3 cameraEyeOffset = Vector3.Zero; + Vector3 cameraAtOffset = Vector3.Zero; + bool forceMouselook = false; + + //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); + SceneObjectPart part = FindNextAvailableSitTarget(targetID); + if (part == null) return; + + // TODO: determine position to sit at based on scene geometry; don't trust offset from client + // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it + + // part is the prim to sit on + // offset is the world-ref vector distance from that prim center to the click-spot + // UUID is the UUID of the Avatar doing the clicking + + m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation + + // Is a sit target available? + Vector3 avSitOffSet = part.SitTargetPosition; + Quaternion avSitOrientation = part.SitTargetOrientation; + + bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored. + // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation()); + Quaternion partRot; +// if (part.LinkNum == 1) +// { // Root prim of linkset +// partRot = part.ParentGroup.RootPart.RotationOffset; +// } +// else +// { // single or child prim + partRot = part.GetWorldRotation(); +// } + Quaternion partIRot = Quaternion.Inverse(partRot); +//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet); + // Sit analysis rewritten by KF 091125 + if (SitTargetisSet) // scipted sit + { + if (!part.IsOccupied) + { +//Console.WriteLine("Scripted, unoccupied"); + part.SetAvatarOnSitTarget(UUID); // set that Av will be on it + offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one + + Quaternion nrot = avSitOrientation; + if (!part.IsRoot) + { + nrot = part.RotationOffset * avSitOrientation; + } + sitOrientation = nrot; // Change rotatione to the scripted one + OffsetRotation = nrot; + autopilot = false; // Jump direct to scripted llSitPos() + } + else + { +//Console.WriteLine("Scripted, occupied"); + return; + } + } + else // Not Scripted + { + if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) + { + // large prim & offset, ignore if other Avs sitting +// offset.Z -= 0.05f; + m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked + autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point + +//Console.WriteLine(" offset ={0}", offset); +//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos); +//Console.WriteLine(" autopilotTarget={0}", autopilotTarget); + + } + else // small offset + { +//Console.WriteLine("Small offset"); + if (!part.IsOccupied) + { + m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center + autopilotTarget = part.AbsolutePosition; +//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget); + } + else return; // occupied small + } // end large/small + } // end Scripted/not + cameraAtOffset = part.GetCameraAtOffset(); + cameraEyeOffset = part.GetCameraEyeOffset(); + forceMouselook = part.GetForceMouselook(); + if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); // + if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); // + + if (m_physicsActor != null) + { + // If we're not using the client autopilot, we're immediately warping the avatar to the location + // We can remove the physicsActor until they stand up. + m_sitAvatarHeight = m_physicsActor.Size.Z; + if (autopilot) + { // its not a scripted sit +// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5) + if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) ) + { + autopilot = false; // close enough + m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup. + Not using the part's position because returning the AV to the last known standing + position is likely to be more friendly, isn't it? */ + RemoveFromPhysicalScene(); + Velocity = Vector3.Zero; + AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target + } // else the autopilot will get us close + } + else + { // its a scripted sit + m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup. + I *am* using the part's position this time because we have no real idea how far away + the avatar is from the sit target. */ + RemoveFromPhysicalScene(); + Velocity = Vector3.Zero; + } + } + else return; // physactor is null! + + Vector3 offsetr; // = offset * partIRot; + // KF: In a linkset, offsetr needs to be relative to the group root! 091208 + // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot); + // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error. + // { // Single, or Root prim of linkset, target is ClickOffset * RootRot + //offsetr = offset * partIRot; +// + // else + // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot) + // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + + // (offset * partRot); + // } + +//Console.WriteLine(" "); +//Console.WriteLine("link number ={0}", part.LinkNum); +//Console.WriteLine("Prim offset ={0}", part.OffsetPosition ); +//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset); +//Console.WriteLine("Click offst ={0}", offset); +//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation()); +//Console.WriteLine("offsetr ={0}", offsetr); +//Console.WriteLine("Camera At ={0}", cameraAtOffset); +//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset); + + //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child + ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); + + m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target + // This calls HandleAgentSit twice, once from here, and the client calls + // HandleAgentSit itself after it gets to the location + // It doesn't get to the location until we've moved them there though + // which happens in HandleAgentSit :P + m_autopilotMoving = autopilot; + m_autoPilotTarget = autopilotTarget; + m_sitAtAutoTarget = autopilot; + m_initialSitTarget = autopilotTarget; + if (!autopilot) + HandleAgentSit(remoteClient, UUID); + } + + public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset) + { + if (m_parentID != 0) + { + StandUp(); + } + m_nextSitAnimation = "SIT"; + + //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); + SceneObjectPart part = FindNextAvailableSitTarget(targetID); + + if (part != null) + { + if (!String.IsNullOrEmpty(part.SitAnimation)) + { + m_nextSitAnimation = part.SitAnimation; + } + m_requestedSitTargetID = part.LocalId; + //m_requestedSitOffset = offset; + m_requestedSitTargetUUID = targetID; + + m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); + + if (m_scene.PhysicsScene.SupportsRayCast()) + { + //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback()); + //SitRayCastAvatarPosition(part); + //return; + } + } + else + { + + m_log.Warn("Sit requested on unknown object: " + targetID.ToString()); + } + + + + SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity); + } + /* + public void SitRayCastAvatarPosition(SceneObjectPart part) + { + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = AbsolutePosition; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse); + } + + public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) + { + SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); + if (part != null) + { + if (hitYN) + { + if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) + { + SitRaycastFindEdge(collisionPoint, normal); + m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); + } + else + { + SitRayCastAvatarPositionCameraZ(part); + } + } + else + { + SitRayCastAvatarPositionCameraZ(part); + } + } + else + { + ControllingClient.SendAlertMessage("Sit position no longer exists"); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + + } + + public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part) + { + // Next, try to raycast from the camera Z position + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse); + } + + public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) + { + SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); + if (part != null) + { + if (hitYN) + { + if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) + { + SitRaycastFindEdge(collisionPoint, normal); + m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal); + } + else + { + SitRayCastCameraPosition(part); + } + } + else + { + SitRayCastCameraPosition(part); + } + } + else + { + ControllingClient.SendAlertMessage("Sit position no longer exists"); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + + } + + public void SitRayCastCameraPosition(SceneObjectPart part) + { + // Next, try to raycast from the camera position + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = CameraPosition; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse); + } + + public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) + { + SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); + if (part != null) + { + if (hitYN) + { + if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) + { + SitRaycastFindEdge(collisionPoint, normal); + m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); + } + else + { + SitRayHorizontal(part); + } + } + else + { + SitRayHorizontal(part); + } + } + else + { + ControllingClient.SendAlertMessage("Sit position no longer exists"); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + + } + + public void SitRayHorizontal(SceneObjectPart part) + { + // Next, try to raycast from the avatar position to fwd + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = CameraPosition; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse); + } + + public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) + { + SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); + if (part != null) + { + if (hitYN) + { + if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) + { + SitRaycastFindEdge(collisionPoint, normal); + m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); + // Next, try to raycast from the camera position + Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; + Vector3 StartRayCastPosition = CameraPosition; + Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); + float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); + //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition); + } + else + { + ControllingClient.SendAlertMessage("Sit position not accessable."); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + } + else + { + ControllingClient.SendAlertMessage("Sit position not accessable."); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + } + else + { + ControllingClient.SendAlertMessage("Sit position no longer exists"); + m_requestedSitTargetUUID = UUID.Zero; + m_requestedSitTargetID = 0; + m_requestedSitOffset = Vector3.Zero; + } + + } + + private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal) + { + int i = 0; + //throw new NotImplementedException(); + //m_requestedSitTargetUUID = UUID.Zero; + //m_requestedSitTargetID = 0; + //m_requestedSitOffset = Vector3.Zero; + + SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity); + } + */ + public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation) + { + if (m_parentID != 0) + { + StandUp(); + } + if (!String.IsNullOrEmpty(sitAnimation)) + { + m_nextSitAnimation = sitAnimation; + } + else + { + m_nextSitAnimation = "SIT"; + } + + //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); + SceneObjectPart part = FindNextAvailableSitTarget(targetID); + if (part != null) + { + m_requestedSitTargetID = part.LocalId; + //m_requestedSitOffset = offset; + m_requestedSitTargetUUID = targetID; + + m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); + + if (m_scene.PhysicsScene.SupportsRayCast()) + { + //SitRayCastAvatarPosition(part); + //return; + } + } + else + { + m_log.Warn("Sit requested on unknown object: " + targetID); + } + + SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity); + } + + public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) + { + if (!String.IsNullOrEmpty(m_nextSitAnimation)) + { + HandleAgentSit(remoteClient, agentID, m_nextSitAnimation); + } + else + { + HandleAgentSit(remoteClient, agentID, "SIT"); + } + } + + public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation) + { + SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); + + if (m_sitAtAutoTarget || !m_autopilotMoving) + { + if (part != null) + { +//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation()); + if (part.GetAvatarOnSitTarget() == UUID) + { +//Console.WriteLine("Scripted Sit"); + // Scripted sit + Vector3 sitTargetPos = part.SitTargetPosition; + Quaternion sitTargetOrient = part.SitTargetOrientation; + m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); + m_pos += SIT_TARGET_ADJUSTMENT; + if (!part.IsRoot) + { + m_pos *= part.RotationOffset; + } + m_bodyRot = sitTargetOrient; + m_parentPosition = part.AbsolutePosition; + part.IsOccupied = true; + part.ParentGroup.AddAvatar(agentID); + } + else + { + // if m_avUnscriptedSitPos is zero then Av sits above center + // Else Av sits at m_avUnscriptedSitPos + + // Non-scripted sit by Kitto Flora 21Nov09 + // Calculate angle of line from prim to Av + Quaternion partIRot; +// if (part.LinkNum == 1) +// { // Root prim of linkset +// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); +// } +// else +// { // single or child prim + partIRot = Quaternion.Inverse(part.GetWorldRotation()); +// } + Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos; + float y_diff = (m_avInitialPos.Y - sitTargetPos.Y); + float x_diff = ( m_avInitialPos.X - sitTargetPos.X); + if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0 + if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0 + float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff); + // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'. + // Av sits at world euler <0,0, z>, translated by part rotation + m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click + + m_parentPosition = part.AbsolutePosition; + part.IsOccupied = true; + part.ParentGroup.AddAvatar(agentID); + m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation + (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center + (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) + + m_avUnscriptedSitPos; // adds click offset, if any + //Set up raytrace to find top surface of prim + Vector3 size = part.Scale; + float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z)); + Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag); + Vector3 down = new Vector3(0f, 0f, -1f); +//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag); + m_scene.PhysicsScene.RaycastWorld( + start, // Vector3 position, + down, // Vector3 direction, + mag, // float length, + SitAltitudeCallback); // retMethod + } // end scripted/not + } + else // no Av + { + return; + } + } + + //We want our offsets to reference the root prim, not the child we may have sat on + if (!part.IsRoot) + { + m_parentID = part.ParentGroup.RootPart.LocalId; + m_pos += part.OffsetPosition; + } + else + { + m_parentID = m_requestedSitTargetID; + } + + m_linkedPrim = part.UUID; + if (part.GetAvatarOnSitTarget() != UUID) + { + m_offsetRotation = m_offsetRotation / part.RotationOffset; + } + Velocity = Vector3.Zero; + RemoveFromPhysicalScene(); + Animator.TrySetMovementAnimation(sitAnimation); + SendFullUpdateToAllClients(); + SendTerseUpdateToAllClients(); + } + + public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal) + { + // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer + // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height. + if(hitYN) + { + // m_pos = Av offset from prim center to make look like on center + // m_parentPosition = Actual center pos of prim + // collisionPoint = spot on prim where we want to sit + // collisionPoint.Z = global sit surface height + SceneObjectPart part = m_scene.GetSceneObjectPart(localid); + Quaternion partIRot; +// if (part.LinkNum == 1) +/// { // Root prim of linkset +// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset); +// } +// else +// { // single or child prim + partIRot = Quaternion.Inverse(part.GetWorldRotation()); +// } + if (m_initialSitTarget != null) + { + float offZ = collisionPoint.Z - m_initialSitTarget.Z; + Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction + //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset); + m_pos += offset; + // ControllingClient.SendClearFollowCamProperties(part.UUID); + } + + } + } // End SitAltitudeCallback KF. + + /// + /// Event handler for the 'Always run' setting on the client + /// Tells the physics plugin to increase speed of movement. + /// + public void HandleSetAlwaysRun(IClientAPI remoteClient, bool pSetAlwaysRun) + { + m_setAlwaysRun = pSetAlwaysRun; + if (PhysicsActor != null) + { + PhysicsActor.SetAlwaysRun = pSetAlwaysRun; + } + } + + public void HandleStartAnim(IClientAPI remoteClient, UUID animID) + { + Animator.AddAnimation(animID, UUID.Zero); + } + + public void HandleStopAnim(IClientAPI remoteClient, UUID animID) + { + Animator.RemoveAnimation(animID); + } + + /// + /// Rotate the avatar to the given rotation and apply a movement in the given relative vector + /// + /// The vector in which to move. This is relative to the rotation argument + /// The direction in which this avatar should now face. + public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging) + { + if (m_isChildAgent) + { + // WHAT??? + m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); + + // we have to reset the user's child agent connections. + // Likely, here they've lost the eventqueue for other regions so border + // crossings will fail at this point unless we reset them. + + List regions = new List(KnownChildRegionHandles); + regions.Remove(m_scene.RegionInfo.RegionHandle); + + MakeRootAgent(new Vector3(127f, 127f, 127f), true); + + // Async command + if (m_scene.SceneGridService != null) + { + m_scene.SceneGridService.SendCloseChildAgentConnections(UUID, regions); + + // Give the above command some time to try and close the connections. + // this is really an emergency.. so sleep, or we'll get all discombobulated. + System.Threading.Thread.Sleep(500); + } + + if (m_scene.SceneGridService != null) + { + IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); + if (m_agentTransfer != null) + m_agentTransfer.EnableChildAgents(this); + } + + return; + } + + m_perfMonMS = Util.EnvironmentTickCount(); + + Rotation = rotation; + Vector3 direc = vec * rotation; + direc.Normalize(); + PhysicsActor actor = m_physicsActor; + if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up. + + direc *= 0.03f * 128f * m_speedModifier; + + if (actor != null) + { + if (actor.Flying) + { + direc *= 4.0f; + //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); + //bool colliding = (m_physicsActor.IsColliding==true); + //if (controlland) + // m_log.Info("[AGENT]: landCommand"); + //if (colliding) + // m_log.Info("[AGENT]: colliding"); + //if (m_physicsActor.Flying && colliding && controlland) + //{ + // StopFlying(); + // m_log.Info("[AGENT]: Stop FLying"); + //} + } + else if (!actor.Flying && actor.IsColliding) + { + if (direc.Z > 2.0f) + { + if(m_animator.m_animTickJump == -1) + { + direc.Z *= 3.0f; // jump + } + else + { + direc.Z *= 0.1f; // prejump + } + /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs + Animator.TrySetMovementAnimation("PREJUMP"); + Animator.TrySetMovementAnimation("JUMP"); + */ + } + } + } + + // TODO: Add the force instead of only setting it to support multiple forces per frame? + m_forceToApply = direc; + m_isNudging = Nudging; + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + #endregion + + #region Overridden Methods + + public override void Update() + { + const float ROTATION_TOLERANCE = 0.01f; + const float VELOCITY_TOLERANCE = 0.001f; + const float POSITION_TOLERANCE = 0.05f; + //const int TIME_MS_TOLERANCE = 3000; + + + + if (m_isChildAgent == false) + { +// PhysicsActor actor = m_physicsActor; + + // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to + // grab the latest PhysicsActor velocity, whereas m_velocity is often + // storing a requested force instead of an actual traveling velocity + + // Throw away duplicate or insignificant updates + if (!m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || + !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || + !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) + //Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) + { + SendTerseUpdateToAllClients(); + + // Update the "last" values + m_lastPosition = m_pos; + m_lastRotation = m_bodyRot; + m_lastVelocity = Velocity; + //m_lastTerseSent = Environment.TickCount; + } + + // followed suggestion from mic bowman. reversed the two lines below. + if (m_parentID == 0 && m_physicsActor != null || m_parentID != 0) // Check that we have a physics actor or we're sitting on something + CheckForBorderCrossing(); + CheckForSignificantMovement(); // sends update to the modules. + } + + //Sending prim updates AFTER the avatar terse updates are sent + SendPrimUpdates(); + } + + #endregion + + #region Update Client(s) + + /// + /// Sends a location update to the client connected to this scenePresence + /// + /// + public void SendTerseUpdateToClient(IClientAPI remoteClient) + { + // If the client is inactive, it's getting its updates from another + // server. + if (remoteClient.IsActive) + { + m_perfMonMS = Util.EnvironmentTickCount(); + + PhysicsActor actor = m_physicsActor; + Vector3 velocity = (actor != null) ? actor.Velocity : Vector3.Zero; + + Vector3 pos = m_pos; + pos.Z += m_appearance.HipOffset; + + //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); + + remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + m_scene.StatsReporter.AddAgentUpdates(1); + } + } + + /// + /// Send a location/velocity/accelleration update to all agents in scene + /// + public void SendTerseUpdateToAllClients() + { + m_perfMonMS = Util.EnvironmentTickCount(); + + m_scene.ForEachClient(SendTerseUpdateToClient); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + public void SendCoarseLocations(List coarseLocations, List avatarUUIDs) + { + SendCourseLocationsMethod d = m_sendCourseLocationsMethod; + if (d != null) + { + d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); + } + } + + public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) + { + if (d != null) + m_sendCourseLocationsMethod = d; + } + + public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs) + { + m_perfMonMS = Util.EnvironmentTickCount(); + m_controllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + /// + /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar) + /// + /// + public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar) + { + // 2 stage check is needed. + if (remoteAvatar == null) + return; + IClientAPI cl=remoteAvatar.ControllingClient; + if (cl == null) + return; + if (m_appearance.Texture == null) + return; + + Vector3 pos = m_pos; + pos.Z += m_appearance.HipOffset; + + remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this); + m_scene.StatsReporter.AddAgentUpdates(1); + } + + /// + /// Tell *ALL* agents about this agent + /// + public void SendInitialFullUpdateToAllClients() + { + m_perfMonMS = Util.EnvironmentTickCount(); + int avUpdates = 0; + m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + ++avUpdates; + // only send if this is the root (children are only "listening posts" in a foreign region) + if (!IsChildAgent) + { + SendFullUpdateToOtherClient(avatar); + } + + if (avatar.LocalId != LocalId) + { + if (!avatar.IsChildAgent) + { + avatar.SendFullUpdateToOtherClient(this); + avatar.SendAppearanceToOtherAgent(this); + avatar.Animator.SendAnimPackToClient(ControllingClient); + } + } + }); + + m_scene.StatsReporter.AddAgentUpdates(avUpdates); + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + + //Animator.SendAnimPack(); + } + + public void SendFullUpdateToAllClients() + { + m_perfMonMS = Util.EnvironmentTickCount(); + + // only send update from root agents to other clients; children are only "listening posts" + int count = 0; + m_scene.ForEachScenePresence(delegate(ScenePresence sp) + { + if (sp.IsChildAgent) + return; + SendFullUpdateToOtherClient(sp); + ++count; + }); + m_scene.StatsReporter.AddAgentUpdates(count); + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + + Animator.SendAnimPack(); + } + + /// + /// Do everything required once a client completes its movement into a region + /// + public void SendInitialData() + { + // Moved this into CompleteMovement to ensure that m_appearance is initialized before + // the inventory arrives + // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); + + Vector3 pos = m_pos; + pos.Z += m_appearance.HipOffset; + + m_controllingClient.SendAvatarDataImmediate(this); + + SendInitialFullUpdateToAllClients(); + SendAppearanceToAllOtherAgents(); + } + + /// + /// Tell the client for this scene presence what items it should be wearing now + /// + public void SendWearables() + { + m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name); + + ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); + } + + /// + /// + /// + public void SendAppearanceToAllOtherAgents() + { + m_perfMonMS = Util.EnvironmentTickCount(); + + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + if (scenePresence.UUID != UUID) + { + SendAppearanceToOtherAgent(scenePresence); + } + }); + + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); + } + + /// + /// Send appearance data to an agent that isn't this one. + /// + /// + public void SendAppearanceToOtherAgent(ScenePresence avatar) + { + avatar.ControllingClient.SendAppearance( + m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes()); + } + + /// + /// Set appearance data (textureentry and slider settings) received from the client + /// + /// + /// + public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams) + { + if (m_physicsActor != null) + { + if (!IsChildAgent) + { + // This may seem like it's redundant, remove the avatar from the physics scene + // just to add it back again, but it saves us from having to update + // 3 variables 10 times a second. + bool flyingTemp = m_physicsActor.Flying; + RemoveFromPhysicalScene(); + //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor); + + //PhysicsActor = null; + + AddToPhysicalScene(flyingTemp); + } + } + + #region Bake Cache Check + + if (textureEntry != null) + { + for (int i = 0; i < BAKE_INDICES.Length; i++) + { + int j = BAKE_INDICES[i]; + Primitive.TextureEntryFace face = textureEntry.FaceTextures[j]; + + if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) + { + if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) + { + m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name); + this.ControllingClient.SendRebakeAvatarTextures(face.TextureID); + } + } + } + + } + + + #endregion Bake Cache Check + + m_appearance.SetAppearance(textureEntry, visualParams); + if (m_appearance.AvatarHeight > 0) + SetHeight(m_appearance.AvatarHeight); + + // This is not needed, because only the transient data changed + //AvatarData adata = new AvatarData(m_appearance); + //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); + + SendAppearanceToAllOtherAgents(); + if (!m_startAnimationSet) + { + Animator.UpdateMovementAnimations(); + m_startAnimationSet = true; + } + + Vector3 pos = m_pos; + pos.Z += m_appearance.HipOffset; + + m_controllingClient.SendAvatarDataImmediate(this); + } + + public void SetWearable(int wearableId, AvatarWearable wearable) + { + m_appearance.SetWearable(wearableId, wearable); + AvatarData adata = new AvatarData(m_appearance); + m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); + m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++); + } + + // Because appearance setting is in a module, we actually need + // to give it access to our appearance directly, otherwise we + // get a synchronization issue. + public AvatarAppearance Appearance + { + get { return m_appearance; } + set { m_appearance = value; } + } + + #endregion + + #region Significant Movement Method + + /// + /// This checks for a significant movement and sends a courselocationchange update + /// + protected void CheckForSignificantMovement() + { + // Movement updates for agents in neighboring regions are sent directly to clients. + // This value only affects how often agent positions are sent to neighbor regions + // for things such as distance-based update prioritization + const float SIGNIFICANT_MOVEMENT = 2.0f; + + if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT) + { + posLastSignificantMove = AbsolutePosition; + m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient); + } + + // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m + if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || + Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance) + { + m_lastChildAgentUpdatePosition = AbsolutePosition; + m_lastChildAgentUpdateCamPosition = CameraPosition; + + ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); + cadu.ActiveGroupID = UUID.Zero.Guid; + cadu.AgentID = UUID.Guid; + cadu.alwaysrun = m_setAlwaysRun; + cadu.AVHeight = m_avHeight; + Vector3 tempCameraCenter = m_CameraCenter; + cadu.cameraPosition = tempCameraCenter; + cadu.drawdistance = m_DrawDistance; + cadu.GroupAccess = 0; + cadu.Position = AbsolutePosition; + cadu.regionHandle = m_rootRegionHandle; + float multiplier = 1; + int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); + if (innacurateNeighbors != 0) + { + multiplier = 1f / (float)innacurateNeighbors; + } + if (multiplier <= 0f) + { + multiplier = 0.25f; + } + + //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); + cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); + cadu.Velocity = Velocity; + + AgentPosition agentpos = new AgentPosition(); + agentpos.CopyFrom(cadu); + + m_scene.SendOutChildAgentUpdates(agentpos, this); + } + } + + #endregion + + #region Border Crossing Methods + + /// + /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion + /// + protected void CheckForBorderCrossing() + { + if (IsChildAgent) + return; + + Vector3 pos2 = AbsolutePosition; + Vector3 vel = Velocity; + int neighbor = 0; + int[] fix = new int[2]; + + float timeStep = 0.1f; + pos2.X = pos2.X + (vel.X*timeStep); + pos2.Y = pos2.Y + (vel.Y*timeStep); + pos2.Z = pos2.Z + (vel.Z*timeStep); + + if (!IsInTransit) + { + // Checks if where it's headed exists a region + + bool needsTransit = false; + if (m_scene.TestBorderCross(pos2, Cardinals.W)) + { + if (m_scene.TestBorderCross(pos2, Cardinals.S)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.SW, ref fix); + } + else if (m_scene.TestBorderCross(pos2, Cardinals.N)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.NW, ref fix); + } + else + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.W, ref fix); + } + } + else if (m_scene.TestBorderCross(pos2, Cardinals.E)) + { + if (m_scene.TestBorderCross(pos2, Cardinals.S)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.SE, ref fix); + } + else if (m_scene.TestBorderCross(pos2, Cardinals.N)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.NE, ref fix); + } + else + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.E, ref fix); + } + } + else if (m_scene.TestBorderCross(pos2, Cardinals.S)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.S, ref fix); + } + else if (m_scene.TestBorderCross(pos2, Cardinals.N)) + { + needsTransit = true; + neighbor = HaveNeighbor(Cardinals.N, ref fix); + } + + + // Makes sure avatar does not end up outside region + if (neighbor <= 0) + { + if (!needsTransit) + { + if (m_requestedSitTargetUUID == UUID.Zero) + { + Vector3 pos = AbsolutePosition; + if (AbsolutePosition.X < 0) + pos.X += Velocity.X; + else if (AbsolutePosition.X > Constants.RegionSize) + pos.X -= Velocity.X; + if (AbsolutePosition.Y < 0) + pos.Y += Velocity.Y; + else if (AbsolutePosition.Y > Constants.RegionSize) + pos.Y -= Velocity.Y; + AbsolutePosition = pos; + } + } + } + else if (neighbor > 0) + CrossToNewRegion(); + } + else + { + RemoveFromPhysicalScene(); + // This constant has been inferred from experimentation + // I'm not sure what this value should be, so I tried a few values. + timeStep = 0.04f; + pos2 = AbsolutePosition; + pos2.X = pos2.X + (vel.X * timeStep); + pos2.Y = pos2.Y + (vel.Y * timeStep); + pos2.Z = pos2.Z + (vel.Z * timeStep); + m_pos = pos2; + } + } + + protected int HaveNeighbor(Cardinals car, ref int[] fix) + { + uint neighbourx = m_regionInfo.RegionLocX; + uint neighboury = m_regionInfo.RegionLocY; + + int dir = (int)car; + + if (dir > 1 && dir < 5) //Heading East + neighbourx++; + else if (dir > 5) // Heading West + neighbourx--; + + if (dir < 3 || dir == 8) // Heading North + neighboury++; + else if (dir > 3 && dir < 7) // Heading Sout + neighboury--; + + int x = (int)(neighbourx * Constants.RegionSize); + int y = (int)(neighboury * Constants.RegionSize); + GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y); + + if (neighbourRegion == null) + { + fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx); + fix[1] = (int)(m_regionInfo.RegionLocY - neighboury); + return dir * (-1); + } + else + return dir; + } + + /// + /// Moves the agent outside the region bounds + /// Tells neighbor region that we're crossing to it + /// If the neighbor accepts, remove the agent's viewable avatar from this scene + /// set them to a child agent. + /// + protected void CrossToNewRegion() + { + InTransit(); + try + { + m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying); + } + catch + { + m_scene.CrossAgentToNewRegion(this, false); + } + } + + public void InTransit() + { + m_inTransit = true; + + if ((m_physicsActor != null) && m_physicsActor.Flying) + m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY; + else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) + m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY; + } + + public void NotInTransit() + { + m_inTransit = false; + } + + public void RestoreInCurrentScene() + { + AddToPhysicalScene(false); // not exactly false + } + + public void Reset() + { + // Put the child agent back at the center + AbsolutePosition + = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70); + Animator.ResetAnimations(); + } + + /// + /// Computes which child agents to close when the scene presence moves to another region. + /// Removes those regions from m_knownRegions. + /// + /// The new region's x on the map + /// The new region's y on the map + /// + public void CloseChildAgents(uint newRegionX, uint newRegionY) + { + List byebyeRegions = new List(); + m_log.DebugFormat( + "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", + m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName); + //DumpKnownRegions(); + + lock (m_knownChildRegions) + { + foreach (ulong handle in m_knownChildRegions.Keys) + { + // Don't close the agent on this region yet + if (handle != Scene.RegionInfo.RegionHandle) + { + uint x, y; + Utils.LongToUInts(handle, out x, out y); + x = x / Constants.RegionSize; + y = y / Constants.RegionSize; + + //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX))); + //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY))); + if (Util.IsOutsideView(x, newRegionX, y, newRegionY)) + { + byebyeRegions.Add(handle); + } + } + } + } + + if (byebyeRegions.Count > 0) + { + m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); + m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions); + } + + foreach (ulong handle in byebyeRegions) + { + RemoveNeighbourRegion(handle); + } + } + + #endregion + + /// + /// This allows the Sim owner the abiility to kick users from their sim currently. + /// It tells the client that the agent has permission to do so. + /// + public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) + { + if (godStatus) + { + // For now, assign god level 200 to anyone + // who is granted god powers, but has no god level set. + // + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID); + if (account != null) + { + if (account.UserLevel > 0) + m_godLevel = account.UserLevel; + else + m_godLevel = 200; + } + } + else + { + m_godLevel = 0; + } + + ControllingClient.SendAdminResponse(token, (uint)m_godLevel); + } + + #region Child Agent Updates + + public void ChildAgentDataUpdate(AgentData cAgentData) + { + //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); + if (!IsChildAgent) + return; + + CopyFrom(cAgentData); + } + + /// + /// This updates important decision making data about a child agent + /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region + /// + public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) + { + if (!IsChildAgent) + return; + + //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY); + int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize; + int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize; + + Vector3 offset = new Vector3(shiftx, shifty, 0f); + + m_DrawDistance = cAgentData.Far; + if (cAgentData.Position != new Vector3(-1f, -1f, -1f)) // UGH!! + m_pos = cAgentData.Position + offset; + + if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance) + { + posLastSignificantMove = AbsolutePosition; + ReprioritizeUpdates(); + } + + m_CameraCenter = cAgentData.Center + offset; + + m_avHeight = cAgentData.Size.Z; + //SetHeight(cAgentData.AVHeight); + + if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) + ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); + + // Sends out the objects in the user's draw distance if m_sendTasksToChild is true. + if (m_scene.m_seeIntoRegionFromNeighbor) + m_sceneViewer.Reset(); + + //cAgentData.AVHeight; + m_rootRegionHandle = cAgentData.RegionHandle; + //m_velocity = cAgentData.Velocity; + } + + public void CopyTo(AgentData cAgent) + { + cAgent.AgentID = UUID; + cAgent.RegionID = Scene.RegionInfo.RegionID; + + cAgent.Position = AbsolutePosition; + cAgent.Velocity = m_velocity; + cAgent.Center = m_CameraCenter; + // Don't copy the size; it is inferred from apearance parameters + //cAgent.Size = new Vector3(0, 0, m_avHeight); + cAgent.AtAxis = m_CameraAtAxis; + cAgent.LeftAxis = m_CameraLeftAxis; + cAgent.UpAxis = m_CameraUpAxis; + + cAgent.Far = m_DrawDistance; + + // Throttles + float multiplier = 1; + int innacurateNeighbors = m_scene.GetInaccurateNeighborCount(); + if (innacurateNeighbors != 0) + { + multiplier = 1f / innacurateNeighbors; + } + if (multiplier <= 0f) + { + multiplier = 0.25f; + } + //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString()); + cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier); + + cAgent.HeadRotation = m_headrotation; + cAgent.BodyRotation = m_bodyRot; + cAgent.ControlFlags = (uint)m_AgentControlFlags; + + if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) + cAgent.GodLevel = (byte)m_godLevel; + else + cAgent.GodLevel = (byte) 0; + + cAgent.AlwaysRun = m_setAlwaysRun; + + try + { + // We might not pass the Wearables in all cases... + // They're only needed so that persistent changes to the appearance + // are preserved in the new region where the user is moving to. + // But in Hypergrid we might not let this happen. + int i = 0; + UUID[] wears = new UUID[m_appearance.Wearables.Length * 2]; + foreach (AvatarWearable aw in m_appearance.Wearables) + { + if (aw != null) + { + wears[i++] = aw.ItemID; + wears[i++] = aw.AssetID; + } + else + { + wears[i++] = UUID.Zero; + wears[i++] = UUID.Zero; + } + } + cAgent.Wearables = wears; + + cAgent.VisualParams = m_appearance.VisualParams; + + if (m_appearance.Texture != null) + cAgent.AgentTextures = m_appearance.Texture.GetBytes(); + } + catch (Exception e) + { + m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message); + } + + //Attachments + List attPoints = m_appearance.GetAttachedPoints(); + if (attPoints != null) + { + //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count); + int i = 0; + AttachmentData[] attachs = new AttachmentData[attPoints.Count]; + foreach (int point in attPoints) + { + attachs[i++] = new AttachmentData(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point)); + } + cAgent.Attachments = attachs; + } + + lock (scriptedcontrols) + { + ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; + int i = 0; + + foreach (ScriptControllers c in scriptedcontrols.Values) + { + controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); + } + cAgent.Controllers = controls; + } + + // Animations + try + { + cAgent.Anims = Animator.Animations.ToArray(); + } + catch { } + + // cAgent.GroupID = ?? + // Groups??? + + } + + public void CopyFrom(AgentData cAgent) + { + m_originRegionID = cAgent.RegionID; + + m_callbackURI = cAgent.CallbackURI; + + m_pos = cAgent.Position; + + m_velocity = cAgent.Velocity; + m_CameraCenter = cAgent.Center; + //m_avHeight = cAgent.Size.Z; + m_CameraAtAxis = cAgent.AtAxis; + m_CameraLeftAxis = cAgent.LeftAxis; + m_CameraUpAxis = cAgent.UpAxis; + + m_DrawDistance = cAgent.Far; + + if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) + ControllingClient.SetChildAgentThrottle(cAgent.Throttles); + + m_headrotation = cAgent.HeadRotation; + m_bodyRot = cAgent.BodyRotation; + m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags; + + if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID))) + m_godLevel = cAgent.GodLevel; + m_setAlwaysRun = cAgent.AlwaysRun; + + uint i = 0; + try + { + if (cAgent.Wearables == null) + cAgent.Wearables = new UUID[0]; + AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2]; + for (uint n = 0; n < cAgent.Wearables.Length; n += 2) + { + UUID itemId = cAgent.Wearables[n]; + UUID assetId = cAgent.Wearables[n + 1]; + wears[i++] = new AvatarWearable(itemId, assetId); + } + m_appearance.Wearables = wears; + Primitive.TextureEntry te; + if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1) + te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length); + else + te = AvatarAppearance.GetDefaultTexture(); + if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT)) + cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams(); + m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone()); + } + catch (Exception e) + { + m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message); + } + + // Attachments + try + { + if (cAgent.Attachments != null) + { + m_appearance.ClearAttachments(); + foreach (AttachmentData att in cAgent.Attachments) + { + m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); + } + } + } + catch { } + + try + { + lock (scriptedcontrols) + { + if (cAgent.Controllers != null) + { + scriptedcontrols.Clear(); + + foreach (ControllerData c in cAgent.Controllers) + { + ScriptControllers sc = new ScriptControllers(); + sc.itemID = c.ItemID; + sc.ignoreControls = (ScriptControlled)c.IgnoreControls; + sc.eventControls = (ScriptControlled)c.EventControls; + + scriptedcontrols[sc.itemID] = sc; + } + } + } + } + catch { } + // Animations + try + { + Animator.ResetAnimations(); + Animator.Animations.FromArray(cAgent.Anims); + } + catch { } + + //cAgent.GroupID = ?? + //Groups??? + } + + public bool CopyAgent(out IAgentData agent) + { + agent = new CompleteAgentData(); + CopyTo((AgentData)agent); + return true; + } + + #endregion Child Agent Updates + + /// + /// Handles part of the PID controller function for moving an avatar. + /// + public override void UpdateMovement() + { + if (m_forceToApply.HasValue) + { + + Vector3 force = m_forceToApply.Value; + m_updateflag = true; + Velocity = force; + + m_forceToApply = null; + } + else + { + if (m_isNudging) + { + Vector3 force = Vector3.Zero; + + m_updateflag = true; + Velocity = force; + m_isNudging = false; + m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND" + } + } + } + + public override void SetText(string text, Vector3 color, double alpha) + { + throw new Exception("Can't set Text on avatar."); + } + + /// + /// Adds a physical representation of the avatar to the Physics plugin + /// + public void AddToPhysicalScene(bool isFlying) + { + PhysicsScene scene = m_scene.PhysicsScene; + + Vector3 pVec = AbsolutePosition; + + // Old bug where the height was in centimeters instead of meters + if (m_avHeight == 127.0f) + { + m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new Vector3(0f, 0f, 1.56f), + isFlying); + } + else + { + m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, + new Vector3(0f, 0f, m_avHeight), isFlying); + } + scene.AddPhysicsActorTaint(m_physicsActor); + //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; + m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; + m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong + m_physicsActor.SubscribeEvents(500); + m_physicsActor.LocalID = LocalId; + } + + private void OutOfBoundsCall(Vector3 pos) + { + //bool flying = m_physicsActor.Flying; + //RemoveFromPhysicalScene(); + + //AddToPhysicalScene(flying); + if (ControllingClient != null) + ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); + } + + // Event called by the physics plugin to tell the avatar about a collision. + private void PhysicsCollisionUpdate(EventArgs e) + { + if (e == null) + return; + + // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents( + // as of this comment the interval is set in AddToPhysicalScene + if (Animator!=null) + { + if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper, + { // else its will lock out other animation changes, like ground sit. + Animator.UpdateMovementAnimations(); + m_updateCount--; + } + } + + CollisionEventUpdate collisionData = (CollisionEventUpdate)e; + Dictionary coldata = collisionData.m_objCollisionList; + + CollisionPlane = Vector4.UnitW; + + if (m_lastColCount != coldata.Count) + { + m_updateCount = UPDATE_COUNT; + m_lastColCount = coldata.Count; + } + + if (coldata.Count != 0 && Animator != null) + { + switch (Animator.CurrentMovementAnimation) + { + case "STAND": + case "WALK": + case "RUN": + case "CROUCH": + case "CROUCHWALK": + { + ContactPoint lowest; + lowest.SurfaceNormal = Vector3.Zero; + lowest.Position = Vector3.Zero; + lowest.Position.Z = Single.NaN; + + foreach (ContactPoint contact in coldata.Values) + { + if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z) + { + lowest = contact; + } + } + + CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal)); + } + break; + } + } + + List thisHitColliders = new List(); + List endedColliders = new List(); + List startedColliders = new List(); + + foreach (uint localid in coldata.Keys) + { + thisHitColliders.Add(localid); + if (!m_lastColliders.Contains(localid)) + { + startedColliders.Add(localid); + } + //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString()); + } + + // calculate things that ended colliding + foreach (uint localID in m_lastColliders) + { + if (!thisHitColliders.Contains(localID)) + { + endedColliders.Add(localID); + } + } + //add the items that started colliding this time to the last colliders list. + foreach (uint localID in startedColliders) + { + m_lastColliders.Add(localID); + } + // remove things that ended colliding from the last colliders list + foreach (uint localID in endedColliders) + { + m_lastColliders.Remove(localID); + } + + // do event notification + if (startedColliders.Count > 0) + { + ColliderArgs StartCollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in startedColliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = Scene.GetSceneObjectPart(localId); + string data = ""; + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + } + + if (colliding.Count > 0) + { + StartCollidingMessage.Colliders = colliding; + + foreach (SceneObjectGroup att in Attachments) + Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage); + } + } + + if (endedColliders.Count > 0) + { + ColliderArgs EndCollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in endedColliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = Scene.GetSceneObjectPart(localId); + string data = ""; + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + } + + if (colliding.Count > 0) + { + EndCollidingMessage.Colliders = colliding; + + foreach (SceneObjectGroup att in Attachments) + Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage); + } + } + + if (thisHitColliders.Count > 0) + { + ColliderArgs CollidingMessage = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in thisHitColliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = Scene.GetSceneObjectPart(localId); + string data = ""; + if (obj != null) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + colliding.Add(detobj); + } + } + + if (colliding.Count > 0) + { + CollidingMessage.Colliders = colliding; + + lock (m_attachments) + { + foreach (SceneObjectGroup att in m_attachments) + Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage); + } + } + } + + if (m_invulnerable) + return; + + float starthealth = Health; + uint killerObj = 0; + foreach (uint localid in coldata.Keys) + { + SceneObjectPart part = Scene.GetSceneObjectPart(localid); + + if (part != null && part.ParentGroup.Damage != -1.0f) + Health -= part.ParentGroup.Damage; + else + { + if (coldata[localid].PenetrationDepth >= 0.10f) + Health -= coldata[localid].PenetrationDepth * 5.0f; + } + + if (Health <= 0.0f) + { + if (localid != 0) + killerObj = localid; + } + //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString()); + } + //Health = 100; + if (!m_invulnerable) + { + if (starthealth != Health) + { + ControllingClient.SendHealth(Health); + } + if (m_health <= 0) + m_scene.EventManager.TriggerAvatarKill(killerObj, this); + } + } + + public void setHealthWithUpdate(float health) + { + Health = health; + ControllingClient.SendHealth(Health); + } + + public void Close() + { + lock (m_attachments) + { + // Delete attachments from scene + // Don't try to save, as this thread won't live long + // enough to complete the save. This would cause no copy + // attachments to poof! + // + foreach (SceneObjectGroup grp in m_attachments) + { + m_scene.DeleteSceneObject(grp, false); + } + m_attachments.Clear(); + } + + lock (m_knownChildRegions) + { + m_knownChildRegions.Clear(); + } + + lock (m_reprioritization_timer) + { + m_reprioritization_timer.Enabled = false; + m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize); + } + + // I don't get it but mono crashes when you try to dispose of this timer, + // unsetting the elapsed callback should be enough to allow for cleanup however. + // m_reprioritizationTimer.Dispose(); + + m_sceneViewer.Close(); + + RemoveFromPhysicalScene(); + m_animator.Close(); + m_animator = null; + } + + public void AddAttachment(SceneObjectGroup gobj) + { + lock (m_attachments) + { + m_attachments.Add(gobj); + } + } + + public bool HasAttachments() + { + return m_attachments.Count > 0; + } + + public bool HasScriptedAttachments() + { + lock (m_attachments) + { + foreach (SceneObjectGroup gobj in m_attachments) + { + if (gobj != null) + { + if (gobj.RootPart.Inventory.ContainsScripts()) + return true; + } + } + } + return false; + } + + public void RemoveAttachment(SceneObjectGroup gobj) + { + lock (m_attachments) + { + if (m_attachments.Contains(gobj)) + { + m_attachments.Remove(gobj); + } + } + } + + public bool ValidateAttachments() + { + lock (m_attachments) + { + // Validate + foreach (SceneObjectGroup gobj in m_attachments) + { + if (gobj == null) + return false; + + if (gobj.IsDeleted) + return false; + } + } + return true; + } + + /// + /// Send a script event to this scene presence's attachments + /// + /// The name of the event + /// The arguments for the event + public void SendScriptEventToAttachments(string eventName, Object[] args) + { + if (m_scriptEngines != null) + { + lock (m_attachments) + { + foreach (SceneObjectGroup grp in m_attachments) + { + // 16384 is CHANGED_ANIMATION + // + // Send this to all attachment root prims + // + foreach (IScriptModule m in m_scriptEngines) + { + if (m == null) // No script engine loaded + continue; + + m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION }); + } + } + } + } + } + + + public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene) + { + m_controllingClient = client; + m_regionInfo = region; + m_scene = scene; + + RegisterToEvents(); + if (m_controllingClient != null) + { + m_controllingClient.ProcessPendingPackets(); + } + /* + AbsolutePosition = client.StartPos; + + Animations = new AvatarAnimations(); + Animations.LoadAnims(); + + m_animations = new List(); + m_animations.Add(Animations.AnimsUUID["STAND"]); + m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber); + + SetDirectionVectors(); + */ + } + + internal void PushForce(Vector3 impulse) + { + if (PhysicsActor != null) + { + PhysicsActor.AddForce(impulse,true); + } + } + + public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) + { + ScriptControllers obj = new ScriptControllers(); + obj.ignoreControls = ScriptControlled.CONTROL_ZERO; + obj.eventControls = ScriptControlled.CONTROL_ZERO; + + obj.itemID = Script_item_UUID; + if (pass_on == 0 && accept == 0) + { + IgnoredControls |= (ScriptControlled)controls; + obj.ignoreControls = (ScriptControlled)controls; + } + + if (pass_on == 0 && accept == 1) + { + IgnoredControls |= (ScriptControlled)controls; + obj.ignoreControls = (ScriptControlled)controls; + obj.eventControls = (ScriptControlled)controls; + } + if (pass_on == 1 && accept == 1) + { + IgnoredControls = ScriptControlled.CONTROL_ZERO; + obj.eventControls = (ScriptControlled)controls; + obj.ignoreControls = ScriptControlled.CONTROL_ZERO; + } + + lock (scriptedcontrols) + { + if (pass_on == 1 && accept == 0) + { + IgnoredControls &= ~(ScriptControlled)controls; + if (scriptedcontrols.ContainsKey(Script_item_UUID)) + scriptedcontrols.Remove(Script_item_UUID); + } + else + { + scriptedcontrols[Script_item_UUID] = obj; + } + } + ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); + } + + public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID) + { + IgnoredControls = ScriptControlled.CONTROL_ZERO; + lock (scriptedcontrols) + { + scriptedcontrols.Clear(); + } + ControllingClient.SendTakeControls(int.MaxValue, false, false); + } + + public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) + { + ScriptControllers takecontrols; + + lock (scriptedcontrols) + { + if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols)) + { + ScriptControlled sctc = takecontrols.eventControls; + + ControllingClient.SendTakeControls((int)sctc, false, false); + ControllingClient.SendTakeControls((int)sctc, true, false); + + scriptedcontrols.Remove(Script_item_UUID); + IgnoredControls = ScriptControlled.CONTROL_ZERO; + foreach (ScriptControllers scData in scriptedcontrols.Values) + { + IgnoredControls |= scData.ignoreControls; + } + } + } + } + + internal void SendControlToScripts(uint flags) + { + ScriptControlled allflags = ScriptControlled.CONTROL_ZERO; + + if (MouseDown) + { + allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0) + { + allflags = ScriptControlled.CONTROL_ZERO; + MouseDown = true; + } + } + + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0) + { + allflags |= ScriptControlled.CONTROL_ML_LBUTTON; + MouseDown = true; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0) + { + allflags |= ScriptControlled.CONTROL_LBUTTON; + MouseDown = true; + } + + // find all activated controls, whether the scripts are interested in them or not + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0) + { + allflags |= ScriptControlled.CONTROL_FWD; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0) + { + allflags |= ScriptControlled.CONTROL_BACK; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0) + { + allflags |= ScriptControlled.CONTROL_UP; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0) + { + allflags |= ScriptControlled.CONTROL_DOWN; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0) + { + allflags |= ScriptControlled.CONTROL_LEFT; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0) + { + allflags |= ScriptControlled.CONTROL_RIGHT; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) + { + allflags |= ScriptControlled.CONTROL_ROT_RIGHT; + } + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) + { + allflags |= ScriptControlled.CONTROL_ROT_LEFT; + } + // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that + if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands) + { + lock (scriptedcontrols) + { + foreach (KeyValuePair kvp in scriptedcontrols) + { + UUID scriptUUID = kvp.Key; + ScriptControllers scriptControlData = kvp.Value; + + ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us + ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle + ScriptControlled localChange = localHeld ^ localLast; // the changed bits + if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO) + { + // only send if still pressed or just changed + m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange); + } + } + } + } + + LastCommands = allflags; + } + + internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored) + { + if (ignored == ScriptControlled.CONTROL_ZERO) + return flags; + + if ((ignored & ScriptControlled.CONTROL_BACK) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); + if ((ignored & ScriptControlled.CONTROL_FWD) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS); + if ((ignored & ScriptControlled.CONTROL_DOWN) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG); + if ((ignored & ScriptControlled.CONTROL_UP) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS); + if ((ignored & ScriptControlled.CONTROL_LEFT) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); + if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG); + if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG); + if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS); + if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN); + if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0) + flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN); + + //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, + //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, + //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS, + //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG, + //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, + //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, + //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG + + return flags; + } + + /// + /// RezAttachments. This should only be called upon login on the first region. + /// Attachment rezzings on crossings and TPs are done in a different way. + /// + public void RezAttachments() + { + if (null == m_appearance) + { + m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID); + return; + } + + XmlDocument doc = new XmlDocument(); + string stateData = String.Empty; + + IAttachmentsService attServ = m_scene.RequestModuleInterface(); + if (attServ != null) + { + m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service"); + stateData = attServ.Get(ControllingClient.AgentId.ToString()); + if (stateData != String.Empty) + { + try + { + doc.LoadXml(stateData); + } + catch { } + } + } + + Dictionary itemData = new Dictionary(); + + XmlNodeList nodes = doc.GetElementsByTagName("Attachment"); + if (nodes.Count > 0) + { + foreach (XmlNode n in nodes) + { + XmlElement elem = (XmlElement)n; + string itemID = elem.GetAttribute("ItemID"); + string xml = elem.InnerXml; + + itemData[new UUID(itemID)] = xml; + } + } + + List attPoints = m_appearance.GetAttachedPoints(); + foreach (int p in attPoints) + { + if (m_isDeleted) + return; + + UUID itemID = m_appearance.GetAttachedItem(p); + UUID assetID = m_appearance.GetAttachedAsset(p); + + // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down + // But they're not used anyway, the item is being looked up for now, so let's proceed. + //if (UUID.Zero == assetID) + //{ + // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID); + // continue; + //} + + try + { + string xmlData; + XmlDocument d = new XmlDocument(); + UUID asset; + if (itemData.TryGetValue(itemID, out xmlData)) + { + d.LoadXml(xmlData); + m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID); + + // Rez from inventory + asset + = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d); + + } + else + { + // Rez from inventory (with a null doc to let + // CHANGED_OWNER happen) + asset + = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null); + } + + m_log.InfoFormat( + "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", + p, itemID, assetID, asset); + } + catch (Exception e) + { + m_log.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}", e.ToString()); + } + } + } + + private void ReprioritizeUpdates() + { + if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time) + { + lock (m_reprioritization_timer) + { + if (!m_reprioritizing) + m_reprioritization_timer.Enabled = m_reprioritizing = true; + else + m_reprioritization_called = true; + } + } + } + + private void Reprioritize(object sender, ElapsedEventArgs e) + { + m_controllingClient.ReprioritizeUpdates(); + + lock (m_reprioritization_timer) + { + m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called; + m_reprioritization_called = false; + } + } + + private Vector3 Quat2Euler(Quaternion rot){ + float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) , + (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z))); + float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W))); + float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) , + (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z))); + return(new Vector3(x,y,z)); + } + + + } +} -- cgit v1.1 From 24b9a2885f1204d32cd032aa8ea9905fa9ce19b1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 10 Aug 2010 20:11:55 +0100 Subject: Resolve merge issues --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 68 +++++++++++++++------- 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a0f267c..b179646 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1838,6 +1838,26 @@ namespace OpenSim.Region.Framework.Scenes dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; + if (userExposed) + dupe.m_rootPart.TrimPermissions(); + + /// may need to create a new Physics actor. + if (dupe.RootPart.PhysActor != null && userExposed) + { + PrimitiveBaseShape pbs = dupe.RootPart.Shape; + + dupe.RootPart.PhysActor = m_scene.PhysicsScene.AddPrimShape( + dupe.RootPart.Name, + pbs, + dupe.RootPart.AbsolutePosition, + dupe.RootPart.Scale, + dupe.RootPart.RotationOffset, + dupe.RootPart.PhysActor.IsPhysical); + + dupe.RootPart.PhysActor.LocalID = dupe.RootPart.LocalId; + dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); + } + lockPartsForRead(true); List partList; @@ -1860,34 +1880,37 @@ namespace OpenSim.Region.Framework.Scenes newPart.LinkNum = part.LinkNum; } - } + // Need to duplicate the physics actor as well + if (part.PhysActor != null && userExposed) + { + PrimitiveBaseShape pbs = part.Shape; + + part.PhysActor + = m_scene.PhysicsScene.AddPrimShape( + part.Name, + pbs, + part.AbsolutePosition, + part.Scale, + part.RotationOffset, + part.PhysActor.IsPhysical); + + part.PhysActor.LocalID = part.LocalId; + part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); + } + + } if (userExposed) { - SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); - newPart.LinkNum = part.LinkNum; + dupe.UpdateParentIDs(); + dupe.HasGroupChanged = true; + dupe.AttachToBackup(); + + ScheduleGroupForFullUpdate(); } - // Need to duplicate the physics actor as well - if (part.PhysActor != null && userExposed) - { - PrimitiveBaseShape pbs = part.Shape; - - part.PhysActor - = m_scene.PhysicsScene.AddPrimShape( - part.Name, - pbs, - part.AbsolutePosition, - part.Scale, - part.RotationOffset, - part.PhysActor.IsPhysical); - - part.PhysActor.LocalID = part.LocalId; - part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); - } } - - if (userExposed) + finally { m_dupeInProgress = false; } @@ -1905,6 +1928,7 @@ namespace OpenSim.Region.Framework.Scenes SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed)); } + public void ScriptSetPhysicsStatus(bool UsePhysics) { bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0); bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0); -- cgit v1.1 From d0a22fb359b8c911bff5a892d35e67ae9bb777a6 Mon Sep 17 00:00:00 2001 From: sacha Date: Tue, 10 Aug 2010 19:35:17 +0000 Subject: fixed ground texture issues ( it seems ) --- .../Region/CoreModules/World/Estate/EstateManagementModule.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index ee151da..849daea 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -148,6 +148,7 @@ namespace OpenSim.Region.CoreModules.World.Estate public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int corner, UUID texture) { + m_log.DebugFormat("[ESTATE]: sacha setting terrain texture change {0}, corner {1}",texture,corner); if (texture == UUID.Zero) return; @@ -166,8 +167,11 @@ namespace OpenSim.Region.CoreModules.World.Estate m_scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; break; } + m_log.DebugFormat("[ESTATE]: sacha step 2 {0}",texture); m_scene.RegionInfo.RegionSettings.Save(); + m_log.DebugFormat("[ESTATE]: sacha step 3 {0}",texture); TriggerRegionInfoChange(); + m_log.DebugFormat("[ESTATE]: sacha step 4 {0}",texture); sendRegionInfoPacketToAll(); } @@ -199,6 +203,7 @@ namespace OpenSim.Region.CoreModules.World.Estate private void handleCommitEstateTerrainTextureRequest(IClientAPI remoteClient) { + m_log.Debug("[ESTATE]: sacha Commit terrain texture change"); sendRegionHandshakeToAll(); } @@ -949,7 +954,8 @@ namespace OpenSim.Region.CoreModules.World.Estate break; } m_scene.RegionInfo.RegionSettings.Save(); - TriggerRegionInfoChange(); + //TriggerRegionInfoChange(); + TriggerEstateInfoChange(); sendRegionInfoPacketToAll(); } @@ -995,7 +1001,8 @@ namespace OpenSim.Region.CoreModules.World.Estate break; } m_scene.RegionInfo.RegionSettings.Save(); - TriggerRegionInfoChange(); + //TriggerRegionInfoChange(); + TriggerEstateInfoChange(); sendRegionHandshakeToAll(); } } -- cgit v1.1 From 7fead01786a6bc406081d026c5909f8277b77aa5 Mon Sep 17 00:00:00 2001 From: sacha Date: Tue, 10 Aug 2010 19:43:32 +0000 Subject: remoning debug messages --- OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 849daea..c6a1614 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -148,7 +148,6 @@ namespace OpenSim.Region.CoreModules.World.Estate public void setEstateTerrainBaseTexture(IClientAPI remoteClient, int corner, UUID texture) { - m_log.DebugFormat("[ESTATE]: sacha setting terrain texture change {0}, corner {1}",texture,corner); if (texture == UUID.Zero) return; @@ -167,11 +166,8 @@ namespace OpenSim.Region.CoreModules.World.Estate m_scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; break; } - m_log.DebugFormat("[ESTATE]: sacha step 2 {0}",texture); m_scene.RegionInfo.RegionSettings.Save(); - m_log.DebugFormat("[ESTATE]: sacha step 3 {0}",texture); TriggerRegionInfoChange(); - m_log.DebugFormat("[ESTATE]: sacha step 4 {0}",texture); sendRegionInfoPacketToAll(); } @@ -203,7 +199,6 @@ namespace OpenSim.Region.CoreModules.World.Estate private void handleCommitEstateTerrainTextureRequest(IClientAPI remoteClient) { - m_log.Debug("[ESTATE]: sacha Commit terrain texture change"); sendRegionHandshakeToAll(); } -- cgit v1.1 From fb14390fb0446e225bca08ec2dc25960d1441728 Mon Sep 17 00:00:00 2001 From: meta7 Date: Tue, 10 Aug 2010 09:17:30 -0700 Subject: Note to self: don't break the build --- OpenSim/Framework/TaskInventoryDictionary.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 6b65fba..a8a53f2 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs @@ -99,7 +99,7 @@ namespace OpenSim.Framework // write call stack method names foreach (StackFrame stackFrame in stackFrames) { - m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name); // write method name + m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name } } catch diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ffe2094..20a2abc 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -145,7 +145,7 @@ namespace OpenSim.Region.Framework.Scenes // write call stack method names foreach (StackFrame stackFrame in stackFrames) { - m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name); // write method name + m_log.Error("[SceneObjectGroup.m_parts] "+(stackFrame.GetMethod().Name)); // write method name } m_partsLock.ExitReadLock(); -- cgit v1.1 From 48c52d6e4868640ac87fc748ac9ac533051a1e62 Mon Sep 17 00:00:00 2001 From: meta7 Date: Tue, 10 Aug 2010 09:50:18 -0700 Subject: Fix a dangling lock issue in llRemoveInventory --- .../Shared/Api/Implementation/LSL_Api.cs | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 71d63bb..1486e2a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4200,21 +4200,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - m_host.TaskInventory.LockItemsForRead(true); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + try { - if (item.Name == name) + m_host.TaskInventory.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - if (item.ItemID == m_itemID) - throw new ScriptDeleteException(); - else - m_host.Inventory.RemoveInventoryItem(item.ItemID); - - m_host.TaskInventory.LockItemsForRead(false); - return; + if (item.Name == name) + { + if (item.ItemID == m_itemID) + throw new ScriptDeleteException(); + else + m_host.Inventory.RemoveInventoryItem(item.ItemID); + return; + } } } - m_host.TaskInventory.LockItemsForRead(false); + finally + { + m_host.TaskInventory.LockItemsForRead(false); + } } public void llSetText(string text, LSL_Vector color, double alpha) -- cgit v1.1 From 1582e05ac78ac46708de84f5d35f79c935febd5b Mon Sep 17 00:00:00 2001 From: meta7 Date: Tue, 10 Aug 2010 09:55:40 -0700 Subject: Fix a nullref issue in the AgentSetAppearance packet handler when removing the physactor from the scene --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 3154872..4064339 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1090,12 +1090,17 @@ namespace OpenSim.Region.Framework.Scenes { if (PhysicsActor != null) { - m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; - m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; - m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); - m_physicsActor.UnSubscribeEvents(); - m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; - PhysicsActor = null; + try + { + m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; + m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; + m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; + m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); + m_physicsActor.UnSubscribeEvents(); + PhysicsActor = null; + } + catch + { } } } -- cgit v1.1 From af60b8ac16361f7b60318a93bf51f094375d0c26 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 10 Aug 2010 22:52:51 +0200 Subject: Set triggering the texture and height update on a two second timer. This fixes the texture rubberbanding. --- .../CoreModules/World/Estate/EstateManagementModule.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index c6a1614..27e492b 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -29,6 +29,7 @@ using System.Collections.Generic; using System.IO; using System.Reflection; using System.Security; +using System.Timers; using log4net; using Nini.Config; using OpenMetaverse; @@ -45,6 +46,7 @@ namespace OpenSim.Region.CoreModules.World.Estate private delegate void LookupUUIDS(List uuidLst); private Scene m_scene; + private Timer m_regionChangeTimer = new Timer(); private EstateTerrainXferHandler TerrainUploader; @@ -898,6 +900,9 @@ namespace OpenSim.Region.CoreModules.World.Estate m_scene.RegisterModuleInterface(this); m_scene.EventManager.OnNewClient += EventManager_OnNewClient; m_scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight; + m_regionChangeTimer.AutoReset = false; + m_regionChangeTimer.Interval = 2000; + m_regionChangeTimer.Elapsed += RaiseRegionInfoChange; m_scene.AddCommand(this, "set terrain texture", "set terrain texture [] []", @@ -949,8 +954,7 @@ namespace OpenSim.Region.CoreModules.World.Estate break; } m_scene.RegionInfo.RegionSettings.Save(); - //TriggerRegionInfoChange(); - TriggerEstateInfoChange(); + TriggerRegionInfoChange(); sendRegionInfoPacketToAll(); } @@ -996,8 +1000,7 @@ namespace OpenSim.Region.CoreModules.World.Estate break; } m_scene.RegionInfo.RegionSettings.Save(); - //TriggerRegionInfoChange(); - TriggerEstateInfoChange(); + TriggerRegionInfoChange(); sendRegionHandshakeToAll(); } } @@ -1170,6 +1173,12 @@ namespace OpenSim.Region.CoreModules.World.Estate protected void TriggerRegionInfoChange() { + m_regionChangeTimer.Stop(); + m_regionChangeTimer.Start(); + } + + protected void RaiseRegionInfoChange(object sender, ElapsedEventArgs e) + { ChangeDelegate change = OnRegionInfoChange; if (change != null) -- cgit v1.1 From a5a60df6879acfb5efc1f1f4a8c2cb257a4ef89d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 11 Aug 2010 02:52:52 +0200 Subject: Change chat packets to bypass the throttles. This should alleviate chat lag --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 800de8a..48465d9 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -787,7 +787,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP reply.ChatData.OwnerID = fromAgentID; reply.ChatData.SourceID = fromAgentID; - OutPacket(reply, ThrottleOutPacketType.Task); + OutPacket(reply, ThrottleOutPacketType.Unknown); } /// -- cgit v1.1 From d00a954d35c21581dfb7d06122ae329891bc7103 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 11 Aug 2010 03:09:56 +0200 Subject: Log the state of the prejump flag --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7e83634..7a97669 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -728,6 +728,8 @@ namespace OpenSim.Region.Framework.Scenes // TODO: Change default to true once the feature is supported m_usePreJump = startupConfig.GetBoolean("enableprejump", true); m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); + + m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF"); if (RegionInfo.NonphysPrimMax > 0) { m_maxNonphys = RegionInfo.NonphysPrimMax; -- cgit v1.1 From fa393cb13a6008ed82c13d9f2bcec96dd8e21cae Mon Sep 17 00:00:00 2001 From: meta7 Date: Wed, 11 Aug 2010 13:39:36 -0700 Subject: Fix Omega getting overwritten on startup. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index fbe1da9..dd780b7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1827,7 +1827,7 @@ namespace OpenSim.Region.Framework.Scenes // which stops client-side interpolation of deactivated joint proxy objects. } - if (!UsePhysics) + if (!UsePhysics && !isNew) { // reset velocity to 0 on physics switch-off. Without that, the client thinks the // prim still has velocity and continues to interpolate its position along the old -- cgit v1.1 From 24577876be9affa844f0361058bd9f93e244bdc0 Mon Sep 17 00:00:00 2001 From: meta7 Date: Wed, 11 Aug 2010 14:10:47 -0700 Subject: Add some console debug to help fix a threadlock issue. --- OpenSim/Region/Framework/Scenes/Scene.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7a97669..7c89e65 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3335,7 +3335,9 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); } + m_log.Debug("[Scene] Beginning ClientClosed"); m_eventManager.TriggerClientClosed(agentID, this); + m_log.Debug("[Scene] Finished ClientClosed"); } catch (NullReferenceException) { @@ -3343,7 +3345,9 @@ namespace OpenSim.Region.Framework.Scenes // Avatar is already disposed :/ } + m_log.Debug("[Scene] Beginning OnRemovePresence"); m_eventManager.TriggerOnRemovePresence(agentID); + m_log.Debug("[Scene] Finished OnRemovePresence"); ForEachClient( delegate(IClientAPI client) { @@ -3359,8 +3363,11 @@ namespace OpenSim.Region.Framework.Scenes } // Remove the avatar from the scene + m_log.Debug("[Scene] Begin RemoveScenePresence"); m_sceneGraph.RemoveScenePresence(agentID); + m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager"); m_clientManager.Remove(agentID); + m_log.Debug("[Scene] Removed the client manager. Firing avatar.close"); try { @@ -3374,9 +3381,9 @@ namespace OpenSim.Region.Framework.Scenes { m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); } - + m_log.Debug("[Scene] Done. Firing RemoveCircuit"); m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); - + m_log.Debug("[Scene] The avatar has left the building"); //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); } -- cgit v1.1 From 7aac4d650f1e9d8b5ac071872f28b39e83143ccf Mon Sep 17 00:00:00 2001 From: meta7 Date: Wed, 11 Aug 2010 14:30:09 -0700 Subject: Fix the llRemoveInventory recursive lock error (again) --- .../Shared/Api/Implementation/LSL_Api.cs | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1486e2a..9bece31 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4200,25 +4200,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); + List inv; try { m_host.TaskInventory.LockItemsForRead(true); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) - { - if (item.Name == name) - { - if (item.ItemID == m_itemID) - throw new ScriptDeleteException(); - else - m_host.Inventory.RemoveInventoryItem(item.ItemID); - return; - } - } + inv = new List(m_host.TaskInventory.Values); } finally { m_host.TaskInventory.LockItemsForRead(false); } + foreach (TaskInventoryItem item in inv) + { + if (item.Name == name) + { + if (item.ItemID == m_itemID) + throw new ScriptDeleteException(); + else + m_host.Inventory.RemoveInventoryItem(item.ItemID); + return; + } + } } public void llSetText(string text, LSL_Vector color, double alpha) -- cgit v1.1 From df9521caf3aa983fd1d7e1c92b6b51e0c82cf7ac Mon Sep 17 00:00:00 2001 From: meta7 Date: Wed, 11 Aug 2010 15:30:42 -0700 Subject: Add ini.example section for the MOTD module. --- bin/OpenSim.ini.example | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 466da93..00a8569 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -1278,6 +1278,10 @@ UseSafetyCommit = true ; Enable media on a prim facilities Enabled = true; +[MOTD] +Enabled = false +Message = "The MOTD module is working!" + ;; ;; These are defaults that are overwritten below in [Architecture]. -- cgit v1.1 From b43a731beb24dccf273aefc0e601841ea59b6fd4 Mon Sep 17 00:00:00 2001 From: meta7 Date: Thu, 12 Aug 2010 05:40:41 -0700 Subject: Fix a nullref exception in the prioritizer --- OpenSim/Region/Framework/Scenes/Prioritizer.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index 8cd0160..c6db7af 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -134,6 +134,7 @@ namespace OpenSim.Region.Framework.Scenes private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) { + if (entity == null) return double.NaN; ScenePresence presence = m_scene.GetScenePresence(client.AgentId); if (presence != null) { @@ -144,7 +145,17 @@ namespace OpenSim.Region.Framework.Scenes // Use group position for child prims Vector3 entityPos = entity.AbsolutePosition; if (entity is SceneObjectPart) - entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition; + { + SceneObjectGroup group = m_scene.GetGroupByPrim(entity.LocalId); + if (group == null) + { + entityPos = entity.AbsolutePosition; + } + else + { + entityPos = group.AbsolutePosition; + } + } else entityPos = entity.AbsolutePosition; -- cgit v1.1 From 042eb80a62c4a4d74e00a59b6aeed679e35d519e Mon Sep 17 00:00:00 2001 From: sacha Date: Sat, 14 Aug 2010 08:59:57 +0000 Subject: clearing some debugmessages --- .../CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs | 2 +- OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs index e1bc243..fb2edb9 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts if (account != null) m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, DateTime.Now + TimeSpan.FromMinutes(2.0d)); - m_log.DebugFormat("[USER CACHE]: cached user {0}", userID); + // m_log.DebugFormat("[USER CACHE]: cached user {0}", userID); } public UserAccount Get(UUID userID, out bool inCache) diff --git a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs index 38c191a..67c482b 100644 --- a/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/UserAccounts/UserAccountServiceConnector.cs @@ -113,7 +113,7 @@ namespace OpenSim.Services.Connectors public virtual UserAccount GetUserAccount(UUID scopeID, UUID userID) { - m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetUserAccount {0}", userID); + // m_log.DebugFormat("[ACCOUNTS CONNECTOR]: GetUserAccount {0}", userID); Dictionary sendData = new Dictionary(); //sendData["SCOPEID"] = scopeID.ToString(); sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); -- cgit v1.1 From a32b0ce0ae28ff42d30e25530dc286401188b89c Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 14 Aug 2010 13:59:36 +0200 Subject: Fix a possible nullref in BestAvatarResponsiveness policy --- OpenSim/Region/Framework/Scenes/Prioritizer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index 8cd0160..7c3746b 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -186,9 +186,9 @@ namespace OpenSim.Region.Framework.Scenes return 0.0; // Use group position for child prims - Vector3 entityPos = entity.AbsolutePosition; + Vector3 entityPos; if (entity is SceneObjectPart) - entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition; + entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition; else entityPos = entity.AbsolutePosition; -- cgit v1.1 From 810840b8624886a615f303baf74f7b72fb1ca66a Mon Sep 17 00:00:00 2001 From: meta7 Date: Wed, 18 Aug 2010 04:23:56 -0700 Subject: Fix a typecasting issue in llList2Float. This addresses mantis #262 --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e3a69a8..76ade1f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5108,7 +5108,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else if (src.Data[index] is LSL_Float) return Convert.ToDouble(((LSL_Float) src.Data[index]).value); else if (src.Data[index] is LSL_String) - return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); + return Convert.ToDouble(Regex.Replace(((LSL_String)src.Data[index]).m_string, "[^0-9]", "")); return Convert.ToDouble(src.Data[index]); } catch (FormatException) -- cgit v1.1 From fb2deb0d452c67c9c0b30c32223ef91b844e5e68 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 18 Aug 2010 20:17:20 +0200 Subject: Prevent a bad cast in llCreateLink(). --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 76ade1f..97dd2e1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3780,6 +3780,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); UUID invItemID = InventorySelf(); + UUID targetID; + + if (!UUID.TryParse(target, out targetID)) + return; TaskInventoryItem item; m_host.TaskInventory.LockItemsForRead(true); @@ -3798,7 +3802,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (sp != null) client = sp.ControllingClient; - SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)target); + SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID); if (targetPart.ParentGroup.RootPart.AttachmentPoint != 0) return; // Fail silently if attached -- cgit v1.1 From 7c673c79d4c52fa14ed803754a18d56bcf54ad87 Mon Sep 17 00:00:00 2001 From: sacha Date: Thu, 19 Aug 2010 08:31:51 +0000 Subject: Adding Group managment to the offline system Sending a group invite is offlined now --- OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index feeb9e6..d3db5b7 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -215,6 +215,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if (im.dialog != (byte)InstantMessageDialog.MessageFromObject && im.dialog != (byte)InstantMessageDialog.MessageFromAgent && im.dialog != (byte)InstantMessageDialog.GroupNotice && + im.dialog != (byte)InstantMessageDialog.GroupInvitation && im.dialog != (byte)InstantMessageDialog.InventoryOffered) { return; -- cgit v1.1 From 0344395776c22cbef6392129cd11feaf34ad4218 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 19 Aug 2010 12:01:40 +0200 Subject: Skip conversion if fields that are null in the database. This may uncover errors elsewhere. --- OpenSim/Data/MySQL/MySQLGenericTableHandler.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index 6cbb2ee..7c23a47 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -148,6 +148,10 @@ namespace OpenSim.Data.MySQL foreach (string name in m_Fields.Keys) { + if (reader[name] is DBNull) + { + continue; + } if (m_Fields[name].FieldType == typeof(bool)) { int v = Convert.ToInt32(reader[name]); -- cgit v1.1 From 1a8a11140cd5e0dee12f5145986fd090fa829d2b Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 19 Aug 2010 12:04:46 +0200 Subject: Revert "Adding Group managment to the offline system" This reverts commit 7c673c79d4c52fa14ed803754a18d56bcf54ad87. That module only handles text IM --- OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index d3db5b7..feeb9e6 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -215,7 +215,6 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if (im.dialog != (byte)InstantMessageDialog.MessageFromObject && im.dialog != (byte)InstantMessageDialog.MessageFromAgent && im.dialog != (byte)InstantMessageDialog.GroupNotice && - im.dialog != (byte)InstantMessageDialog.GroupInvitation && im.dialog != (byte)InstantMessageDialog.InventoryOffered) { return; -- cgit v1.1 From a1074cad5c6da38a67f79e3498574c5a7e0d3dbb Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 19 Aug 2010 20:41:55 +0200 Subject: Short-circuit the grid server lookup for RequestSimulatorData if the region info is requested for is the local region --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 97dd2e1..22a81ac 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9147,7 +9147,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string reply = String.Empty; - GridRegion info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); + GridRegion info; + + if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) + info = new GridRegion(m_ScriptEngine.World.RegionInfo); + else + info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); switch (data) { -- cgit v1.1 From 47838e5fb39596effd4d0f7e1021ab68e69cd9d8 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 20 Aug 2010 08:46:46 +0200 Subject: Add some maptile options, change maptile generation from OpenSimBase to Scene to make it more configurable. --- OpenSim/Region/Application/OpenSimBase.cs | 13 ------- OpenSim/Region/Framework/Scenes/Scene.cs | 61 +++++++++++++++++++++++++++---- bin/OpenSim.ini.example | 6 +++ 3 files changed, 59 insertions(+), 21 deletions(-) diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index c08da18..4ef0b1b 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -390,19 +390,6 @@ namespace OpenSim // Prims have to be loaded after module configuration since some modules may be invoked during the load scene.LoadPrimsFromStorage(regionInfo.originRegionID); - if (scene.SnmpService != null) - { - scene.SnmpService.BootInfo("Creating region texture", scene); - } - - // moved these here as the map texture has to be created after the modules are initialized - // and has to happen before the region is registered with the grid. - IWorldMapModule mapModule = scene.RequestModuleInterface(); - if (mapModule != null) - mapModule.GenerateMaptile(); - else - m_log.WarnFormat("[STARTUP]: No map module available to generate map tile"); - // TODO : Try setting resource for region xstats here on scene MainServer.Instance.AddStreamHandler(new Region.Framework.Scenes.RegionStatsHandler(regionInfo)); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 73472a9..98c46bd 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -411,6 +411,9 @@ namespace OpenSim.Region.Framework.Scenes private double m_rootReprioritizationDistance = 10.0; private double m_childReprioritizationDistance = 20.0; + private Timer m_mapGenerationTimer = new Timer(); + bool m_generateMaptiles = false; + #endregion #region Properties @@ -665,6 +668,29 @@ namespace OpenSim.Region.Framework.Scenes m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); + + m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); + if (m_generateMaptiles) + { + int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0); + if (maptileRefresh != 0) + { + m_mapGenerationTimer.Interval = maptileRefresh * 1000; + m_mapGenerationTimer.Elapsed += RegenerateMaptile; + m_mapGenerationTimer.AutoReset = true; + m_mapGenerationTimer.Start(); + } + } + else + { + string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString()); + UUID tileID; + + if (UUID.TryParse(tile, out tileID)) + { + RegionInfo.RegionSettings.TerrainImageID = tileID; + } + } } catch { @@ -1694,16 +1720,21 @@ namespace OpenSim.Region.Framework.Scenes m_sceneGridService.SetScene(this); - // These two 'commands' *must be* next to each other or sim rebooting fails. - //m_sceneGridService.RegisterRegion(m_interregionCommsOut, RegionInfo); - - GridRegion region = new GridRegion(RegionInfo); - string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); - if (error != String.Empty) + // If we generate maptiles internally at all, the maptile generator + // will register the region. If not, do it here + if (m_generateMaptiles) { - throw new Exception(error); + RegenerateMaptile(null, null); + } + else + { + GridRegion region = new GridRegion(RegionInfo); + string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); + if (error != String.Empty) + { + throw new Exception(error); + } } - } #endregion @@ -4995,5 +5026,19 @@ namespace OpenSim.Region.Framework.Scenes return offsets.ToArray(); } + + public void RegenerateMaptile(object sender, ElapsedEventArgs e) + { + IWorldMapModule mapModule = RequestModuleInterface(); + if (mapModule != null) + { + mapModule.GenerateMaptile(); + + string error = GridService.RegisterRegion(RegionInfo.ScopeID, new GridRegion(RegionInfo)); + + if (error != String.Empty) + throw new Exception(error); + } + } } } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 00a8569..cf9e217 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -225,6 +225,12 @@ ;WorldMapModule = "WorldMap" ;MapImageModule = "MapImageModule" + ; Set to false to not generate any maptiles + ;GenerateMaptiles = "true" + ; Refreah (in seconds) the map tile periodically + ;MaptileRefresh = 0 + ; If not generating maptiles, use this static texture asset ID + ;MaptileStaticUUID = "00000000-0000-0000-0000-000000000000" ; ## ; ## EMAIL MODULE -- cgit v1.1 From cc8864b0e3ae0ee594813eb0a1115eeb5765291e Mon Sep 17 00:00:00 2001 From: meta7 Date: Fri, 20 Aug 2010 11:00:14 -0700 Subject: Get maturity level from access number. This addresses mantis #269 --- OpenSim/Services/Interfaces/IGridService.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index ac234dc..cce8f2c 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -324,6 +324,12 @@ namespace OpenSim.Services.Interfaces if (kvp.ContainsKey("regionName")) RegionName = (string)kvp["regionName"]; + if (kvp.ContainsKey("access")) + { + byte access = Convert.ToByte((string)kvp["access"]); + Maturity = (int)Util.ConvertAccessLevelToMaturity(access); + } + if (kvp.ContainsKey("serverIP")) { //int port = 0; -- cgit v1.1 From b1790ba56ec4ee61a2df6747b1fa42ae0c37da15 Mon Sep 17 00:00:00 2001 From: meta7 Date: Fri, 20 Aug 2010 11:25:31 -0700 Subject: Delete items as well as folders in XInventoryService.PurgeFolder - this should make emptying the trash work properly. --- OpenSim/Services/InventoryService/XInventoryService.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 26c5b33..e3f0a19 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -342,6 +342,17 @@ namespace OpenSim.Services.InventoryService m_Database.DeleteFolders("folderID", x.folderID.ToString()); } + XInventoryItem[] items = m_Database.GetItems( + new string[] { "parentFolderID" }, + new string[] { folder.ID.ToString() }); + + List itemlist = new List(); + foreach (XInventoryItem i in items) + { + itemlist.Add(i.inventoryID); + } + + DeleteItems(folder.Owner, itemlist); return true; } -- cgit v1.1 From 47080834346b2528a65e5b4d5e59130206b0cb83 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 20 Aug 2010 18:53:33 +0200 Subject: Use the database mthod directly to delete items in a single sql swoop --- OpenSim/Services/InventoryService/XInventoryService.cs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index e3f0a19..3efdce4 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -342,17 +342,7 @@ namespace OpenSim.Services.InventoryService m_Database.DeleteFolders("folderID", x.folderID.ToString()); } - XInventoryItem[] items = m_Database.GetItems( - new string[] { "parentFolderID" }, - new string[] { folder.ID.ToString() }); - - List itemlist = new List(); - foreach (XInventoryItem i in items) - { - itemlist.Add(i.inventoryID); - } - - DeleteItems(folder.Owner, itemlist); + m_Database.DeleteItems("parentFolderID", folder.id.ToString()); return true; } -- cgit v1.1 From c448151f6b8f30bd0361db0b0f8f8075f7192618 Mon Sep 17 00:00:00 2001 From: meta7 Date: Fri, 20 Aug 2010 11:38:59 -0700 Subject: Someone from germany broke the build :P mentioning no names --- OpenSim/Services/InventoryService/XInventoryService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 3efdce4..f63ab16 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -342,7 +342,7 @@ namespace OpenSim.Services.InventoryService m_Database.DeleteFolders("folderID", x.folderID.ToString()); } - m_Database.DeleteItems("parentFolderID", folder.id.ToString()); + m_Database.DeleteItems("parentFolderID", folder.ID.ToString()); return true; } -- cgit v1.1 From f7c4be1fa194323554128b6aee82dfa68448a5ef Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 21 Aug 2010 00:46:16 +0200 Subject: Forward-port a small improvement to the land out connector --- .../ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs index 2386060..252d9e7 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/RemoteLandServiceConnector.cs @@ -102,7 +102,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land public void RegionLoaded(Scene scene) { - m_GridService = scene.GridService; + if (m_Enabled) + m_GridService = scene.GridService; } -- cgit v1.1 From 839b08c32be1dcfee9c89f31a2dd5358e2ab6e88 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 21 Aug 2010 06:30:53 -0700 Subject: Removed the NotImplementedException from llSetSoundQueueing, because the function not working won't actually stop the script from working, firing an exception will. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 22a81ac..37f2433 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5797,7 +5797,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetSoundQueueing(int queue) { m_host.AddScriptLPS(1); - NotImplemented("llSetSoundQueueing"); } public void llSetSoundRadius(double radius) -- cgit v1.1 From 3ffdadef7014334666d0d42ff8bd9bd83b3c6505 Mon Sep 17 00:00:00 2001 From: meta7 Date: Sat, 21 Aug 2010 07:22:41 -0700 Subject: Add support for attached avatars in llGetLinkKey() --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 37f2433..9615d08 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3985,6 +3985,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { + if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1)) + { + linknum -= (m_host.ParentGroup.PrimCount) + 1; + if (linknum > 0) linknum--; //for linksets + + List avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET); + if (avatars.Count > linknum) + { + return avatars[linknum].UUID.ToString(); + } + } return UUID.Zero.ToString(); } } -- cgit v1.1 From 8613336674141c223eee464575f1df239056c338 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sat, 21 Aug 2010 17:48:49 +0200 Subject: Don't allow oversized search reply packets --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 59 +++++++++++++++------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index d41df3d..fa72410 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -2734,32 +2734,57 @@ namespace OpenSim.Region.ClientStack.LindenUDP packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); - packet.QueryReplies = - new DirPlacesReplyPacket.QueryRepliesBlock[data.Length]; - - packet.StatusData = new DirPlacesReplyPacket.StatusDataBlock[ - data.Length]; - packet.AgentData.AgentID = AgentId; packet.QueryData[0].QueryID = queryID; + DirPlacesReplyPacket.QueryRepliesBlock[] replies = + new DirPlacesReplyPacket.QueryRepliesBlock[0]; + DirPlacesReplyPacket.StatusDataBlock[] status = + new DirPlacesReplyPacket.StatusDataBlock[0]; + int i = 0; foreach (DirPlacesReplyData d in data) { - packet.QueryReplies[i] = - new DirPlacesReplyPacket.QueryRepliesBlock(); - packet.StatusData[i] = new DirPlacesReplyPacket.StatusDataBlock(); - packet.QueryReplies[i].ParcelID = d.parcelID; - packet.QueryReplies[i].Name = Utils.StringToBytes(d.name); - packet.QueryReplies[i].ForSale = d.forSale; - packet.QueryReplies[i].Auction = d.auction; - packet.QueryReplies[i].Dwell = d.dwell; - packet.StatusData[i].Status = d.Status; - i++; + int idx = replies.Length; + Array.Resize(ref replies, idx + 1); + Array.Resize(ref status, idx + 1); + + replies[idx] = new DirPlacesReplyPacket.QueryRepliesBlock(); + status[idx] = new DirPlacesReplyPacket.StatusDataBlock(); + replies[idx].ParcelID = d.parcelID; + replies[idx].Name = Utils.StringToBytes(d.name); + replies[idx].ForSale = d.forSale; + replies[idx].Auction = d.auction; + replies[idx].Dwell = d.dwell; + status[idx].Status = d.Status; + + packet.QueryReplies = replies; + packet.StatusData = status; + + if (packet.Length >= 1000) + { + OutPacket(packet, ThrottleOutPacketType.Task); + + packet = (DirPlacesReplyPacket)PacketPool.Instance.GetPacket(PacketType.DirPlacesReply); + + packet.AgentData = new DirPlacesReplyPacket.AgentDataBlock(); + + packet.QueryData = new DirPlacesReplyPacket.QueryDataBlock[1]; + packet.QueryData[0] = new DirPlacesReplyPacket.QueryDataBlock(); + + packet.AgentData.AgentID = AgentId; + + packet.QueryData[0].QueryID = queryID; + + replies = new DirPlacesReplyPacket.QueryRepliesBlock[0]; + status = new DirPlacesReplyPacket.StatusDataBlock[0]; + + } } - OutPacket(packet, ThrottleOutPacketType.Task); + if (replies.Length > 0) + OutPacket(packet, ThrottleOutPacketType.Task); } public void SendDirPeopleReply(UUID queryID, DirPeopleReplyData[] data) -- cgit v1.1 From a0a25bb8ca846c87b3e8e0de74d4fbcc985ae456 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 22 Aug 2010 13:42:29 +0200 Subject: A stab at making a better bounding box calculation --- .../Shared/Api/Implementation/LSL_Api.cs | 105 +++++++++++++++------ 1 file changed, 74 insertions(+), 31 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 9615d08..d856464 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7829,55 +7829,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); UUID objID = UUID.Zero; LSL_List result = new LSL_List(); + + // If the ID is not valid, return null result if (!UUID.TryParse(obj, out objID)) { result.Add(new LSL_Vector()); result.Add(new LSL_Vector()); return result; } + + // Check if this is an attached prim. If so, replace + // the UUID with the avatar UUID and report it's bounding box + SceneObjectPart part = World.GetSceneObjectPart(objID); + if (part != null && part.ParentGroup.IsAttachment) + objID = part.ParentGroup.RootPart.AttachedAvatar; + + // Find out if this is an avatar ID. If so, return it's box ScenePresence presence = World.GetScenePresence(objID); if (presence != null) { - if (presence.ParentID == 0) // not sat on an object + // As per LSL Wiki, there is no difference between sitting + // and standing avatar since server 1.36 + LSL_Vector lower; + LSL_Vector upper; + if (presence.Animator.Animations.DefaultAnimation.AnimID + == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) { - LSL_Vector lower; - LSL_Vector upper; - if (presence.Animator.Animations.DefaultAnimation.AnimID - == AnimationSet.Animations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) - { - // This is for ground sitting avatars - float height = presence.Appearance.AvatarHeight / 2.66666667f; - lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f); - upper = new LSL_Vector(0.3375f, 0.45f, 0.0f); - } - else - { - // This is for standing/flying avatars - float height = presence.Appearance.AvatarHeight / 2.0f; - lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); - upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); - } - result.Add(lower); - result.Add(upper); - return result; + // This is for ground sitting avatars + float height = presence.Appearance.AvatarHeight / 2.66666667f; + lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f); + upper = new LSL_Vector(0.3375f, 0.45f, 0.0f); } else { - // sitting on an object so we need the bounding box of that - // which should include the avatar so set the UUID to the - // UUID of the object the avatar is sat on and allow it to fall through - // to processing an object - SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID); - objID = p.UUID; + // This is for standing/flying avatars + float height = presence.Appearance.AvatarHeight / 2.0f; + lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); + upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); } + + // Adjust to the documented error offsets (see LSL Wiki) + lower += new LSL_Vector(0.05f, 0.05f, 0.05f); + upper -= new LSL_Vector(0.05f, 0.05f, 0.05f); + + if (lower.x > upper.x) + lower.x = upper.x; + if (lower.y > upper.y) + lower.y = upper.y; + if (lower.z > upper.z) + lower.z = upper.z; + + result.Add(lower); + result.Add(upper); + return result; } - SceneObjectPart part = World.GetSceneObjectPart(objID); + + part = World.GetSceneObjectPart(objID); // Currently only works for single prims without a sitting avatar if (part != null) { - Vector3 halfSize = part.Scale / 2.0f; - LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); - LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); + float minX; + float maxX; + float minY; + float maxY; + float minZ; + float maxZ; + + // This BBox is in sim coordinates, with the offset being + // a contained point. + Vector3[] offsets = World.GetCombinedBoundingBox(new List { part.ParentGroup }, + out minX, out maxX, out minY, out maxY, out minZ, out maxZ); + + minX -= offsets[0].X; + maxX -= offsets[0].X; + minY -= offsets[0].Y; + maxY -= offsets[0].Y; + minZ -= offsets[0].Z; + maxZ -= offsets[0].Z; + + LSL_Vector lower; + LSL_Vector upper; + + // Adjust to the documented error offsets (see LSL Wiki) + lower = new LSL_Vector(minX + 0.05f, minY + 0.05f, minZ + 0.05f); + upper = new LSL_Vector(maxX - 0.05f, maxY - 0.05f, maxZ - 0.05f); + + if (lower.x > upper.x) + lower.x = upper.x; + if (lower.y > upper.y) + lower.y = upper.y; + if (lower.z > upper.z) + lower.z = upper.z; + result.Add(lower); result.Add(upper); return result; -- cgit v1.1 From 071edaff491c318ba4164b4c4783e425222dc570 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 22 Aug 2010 13:51:15 +0200 Subject: Suppress error messages about scripts not foind if they're in fact disabled --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index abb4de6..a7003c4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -422,6 +422,9 @@ namespace OpenSim.Region.Framework.Scenes public void ResumeScripts() { + if (m_scene.RegionInfo.RegionSettings.DisableScripts) + return; + foreach (SceneObjectPart part in m_parts.Values) { part.Inventory.ResumeScripts(); -- cgit v1.1 From 32ddeab5e37b6ba11eaa8322ad6473b52f21d55b Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 22 Aug 2010 14:26:58 +0200 Subject: Add printing the default script engine name. Report real exceptions when there is an issue with the config file, as a typo could cause configuration to silently fail. --- OpenSim/Region/Framework/Scenes/Scene.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 32211c4..957c4e8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -658,6 +658,7 @@ namespace OpenSim.Region.Framework.Scenes m_persistAfter *= 10000000; m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); + m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); IConfig packetConfig = m_config.Configs["PacketPool"]; if (packetConfig != null) @@ -692,9 +693,9 @@ namespace OpenSim.Region.Framework.Scenes } } } - catch + catch (Exception e) { - m_log.Warn("[SCENE]: Failed to load StartupConfig"); + m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString()); } #endregion Region Config -- cgit v1.1 From 98b2d3a7f2f95ee26de76147d0d43468d8c5ad71 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 22 Aug 2010 15:55:23 +0200 Subject: Revert "Fix a typecasting issue in llList2Float. This addresses mantis #262" This reverts commit 810840b8624886a615f303baf74f7b72fb1ca66a. This breaks llList2Float in horrible ways. 12 hours 14 minutes becomes 1214.0 and 023.145 becomes 23145.0 Could just add the dot to fix the latter issue but that would not help the first part. Another solution is needed. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d856464..5caade6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5123,7 +5123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else if (src.Data[index] is LSL_Float) return Convert.ToDouble(((LSL_Float) src.Data[index]).value); else if (src.Data[index] is LSL_String) - return Convert.ToDouble(Regex.Replace(((LSL_String)src.Data[index]).m_string, "[^0-9]", "")); + return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); return Convert.ToDouble(src.Data[index]); } catch (FormatException) -- cgit v1.1 From 0ca771c1850780d0be87b5f16f282b46f9bd4936 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 22 Aug 2010 16:23:36 +0200 Subject: Provide a better implementation of llList2Float --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5caade6..ca09705 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5123,7 +5123,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else if (src.Data[index] is LSL_Float) return Convert.ToDouble(((LSL_Float) src.Data[index]).value); else if (src.Data[index] is LSL_String) - return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); + { + string str = ((LSL_String) src.Data[index]).m_string; + Match m = Regex.Match(str, "^\\s*(-?+?[0-9,]+\\.?[0-9]*)"); + if (m != Match.Empty) + { + str = m.Value; + double d = 0.0; + if (!Double.TryParse(str, out d)) + return 0.0; + + return d; + } + return 0.0; + } return Convert.ToDouble(src.Data[index]); } catch (FormatException) -- cgit v1.1 From 5c368c8d380e623185f74d32505b841f8496e510 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 22 Aug 2010 16:44:22 +0200 Subject: Refix the fix --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ca09705..5717086 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5125,7 +5125,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else if (src.Data[index] is LSL_String) { string str = ((LSL_String) src.Data[index]).m_string; - Match m = Regex.Match(str, "^\\s*(-?+?[0-9,]+\\.?[0-9]*)"); + Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)"); if (m != Match.Empty) { str = m.Value; -- cgit v1.1 From 46412f49313472f1665f864e3b631fcdeeff70da Mon Sep 17 00:00:00 2001 From: meta7 Date: Sun, 22 Aug 2010 09:32:40 -0700 Subject: Fix llGetLinkKey and llGetNumberOfPrims to play nice with avatars in the linkset (emulated) --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 9615d08..b4134a4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3988,7 +3988,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (linknum > m_host.ParentGroup.PrimCount || (linknum == 1 && m_host.ParentGroup.PrimCount == 1)) { linknum -= (m_host.ParentGroup.PrimCount) + 1; - if (linknum > 0) linknum--; //for linksets List avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET); if (avatars.Count > linknum) @@ -7807,13 +7806,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llGetNumberOfPrims() { m_host.AddScriptLPS(1); - int avatarCount = 0; - World.ForEachScenePresence(delegate(ScenePresence presence) - { - if (!presence.IsChildAgent && presence.ParentID != 0 && m_host.ParentGroup.HasChildPrim(presence.ParentID)) - avatarCount++; - }); - + int avatarCount = m_host.ParentGroup.GetLinkedAvatars().Count; + return m_host.ParentGroup.PrimCount + avatarCount; } -- cgit v1.1 From b9e12ed3b7e6f33a824129ce6e79519140a34aa2 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 24 Aug 2010 18:20:24 +0200 Subject: Add a method to delete left over / dropped attachments --- OpenSim/Region/Framework/Scenes/Scene.cs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 957c4e8..d0619d7 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5040,5 +5040,37 @@ namespace OpenSim.Region.Framework.Scenes throw new Exception(error); } } + + public void CleanDroppedAttachments() + { + List objectsToDelete = + new List(); + + ForEachSOG(delegate (SceneObjectGroup grp) + { + if (grp.RootPart.Shape.State != 0) + { + UUID agentID = grp.OwnerID; + if (agentID == UUID.Zero) + { + objectsToDelete.Add(grp); + return; + } + + ScenePresence sp = GetScenePresence(agentID); + if (sp == null) + { + objectsToDelete.Add(grp); + return; + } + } + }); + + foreach (SceneObjectGroup grp in objectsToDelete) + { + m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); + DeleteSceneObject(grp, true); + } + } } } -- cgit v1.1 From 5a05de0eec5cba9500fd4803e2bf2ffb54d92265 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 24 Aug 2010 18:38:54 +0200 Subject: Call attachment cleanup when an agent crosses out --- .../Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 0ba67d3..ee07f30 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -446,6 +446,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // Now let's make it officially a child agent sp.MakeChildAgent(); + sp.Scene.CleanDroppedAttachments(); + // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) -- cgit v1.1 From 512a13dbe7a8dfa36a662f64caf573f467173b95 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 24 Aug 2010 18:52:00 +0200 Subject: Call the Cleanup when an agent logs out, when an agent leaves and just before an agent logs in directly. Intentionally not calling this from MakeRoot as that would mess up attachment transfer in teleport --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index d0619d7..6452dfe 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3199,6 +3199,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.Debug("[Scene] Beginning ClientClosed"); m_eventManager.TriggerClientClosed(agentID, this); m_log.Debug("[Scene] Finished ClientClosed"); + CleanDroppedAttachments(); } catch (NullReferenceException) { @@ -3442,6 +3443,8 @@ namespace OpenSim.Region.Framework.Scenes if (vialogin) { + CleanDroppedAttachments(); + if (TestBorderCross(agent.startpos, Cardinals.E)) { Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); -- cgit v1.1 From 4e324ae3cbf5c4ce16900bd5e57d8671c1de0cfc Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 24 Aug 2010 19:07:42 +0200 Subject: Call the cleanup after saving attachment states, so that the attachments don't get killed before they can be saved --- OpenSim/Region/Framework/Scenes/Scene.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 6452dfe..37d797e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3199,7 +3199,6 @@ namespace OpenSim.Region.Framework.Scenes m_log.Debug("[Scene] Beginning ClientClosed"); m_eventManager.TriggerClientClosed(agentID, this); m_log.Debug("[Scene] Finished ClientClosed"); - CleanDroppedAttachments(); } catch (NullReferenceException) { @@ -3210,6 +3209,9 @@ namespace OpenSim.Region.Framework.Scenes m_log.Debug("[Scene] Beginning OnRemovePresence"); m_eventManager.TriggerOnRemovePresence(agentID); m_log.Debug("[Scene] Finished OnRemovePresence"); + + CleanDroppedAttachments(); + ForEachClient( delegate(IClientAPI client) { -- cgit v1.1 From 314d1171efd6d45686ad54944e9bf53ec8cd0b7f Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 25 Aug 2010 16:06:06 +0200 Subject: Lock the attachment cleanup so it doesn't go into an endless deletion frenzy --- OpenSim/Region/Framework/Scenes/Scene.cs | 36 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 37d797e..2324f7a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -399,6 +399,7 @@ namespace OpenSim.Region.Framework.Scenes private bool m_firstHeartbeat = true; private object m_deleting_scene_object = new object(); + private object m_cleaningAttachments = new object(); // the minimum time that must elapse before a changed object will be considered for persisted public long m_dontPersistBefore = DEFAULT_MIN_TIME_FOR_PERSISTENCE * 10000000L; @@ -5051,26 +5052,29 @@ namespace OpenSim.Region.Framework.Scenes List objectsToDelete = new List(); - ForEachSOG(delegate (SceneObjectGroup grp) - { - if (grp.RootPart.Shape.State != 0) + lock (m_cleaningAttachments) + { + ForEachSOG(delegate (SceneObjectGroup grp) { - UUID agentID = grp.OwnerID; - if (agentID == UUID.Zero) + if (grp.RootPart.Shape.State != 0 || objectsToDelete.Contains(grp)) { - objectsToDelete.Add(grp); - return; + UUID agentID = grp.OwnerID; + if (agentID == UUID.Zero) + { + objectsToDelete.Add(grp); + return; + } + + ScenePresence sp = GetScenePresence(agentID); + if (sp == null) + { + objectsToDelete.Add(grp); + return; + } } + }); + } - ScenePresence sp = GetScenePresence(agentID); - if (sp == null) - { - objectsToDelete.Add(grp); - return; - } - } - }); - foreach (SceneObjectGroup grp in objectsToDelete) { m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); -- cgit v1.1 From c13045b25e6424c90642613d400ab6ebf2744064 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 25 Aug 2010 20:11:47 +0200 Subject: Correct a logic error in attachment cleanup --- OpenSim/Region/Framework/Scenes/Scene.cs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2324f7a..c7b38a1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5056,7 +5056,7 @@ namespace OpenSim.Region.Framework.Scenes { ForEachSOG(delegate (SceneObjectGroup grp) { - if (grp.RootPart.Shape.State != 0 || objectsToDelete.Contains(grp)) + if (grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp))) { UUID agentID = grp.OwnerID; if (agentID == UUID.Zero) @@ -5075,10 +5075,15 @@ namespace OpenSim.Region.Framework.Scenes }); } - foreach (SceneObjectGroup grp in objectsToDelete) + if (objectsToDelete.Count > 0) { - m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); - DeleteSceneObject(grp, true); + m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count); + foreach (SceneObjectGroup grp in objectsToDelete) + { + m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); + DeleteSceneObject(grp, true); + } + m_log.Debug("[SCENE]: Finished dropped attachment deletion"); } } } -- cgit v1.1 From 1bcb2e788fd895a7d8165797c29e6f2a652eff8b Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 25 Aug 2010 23:04:12 +0200 Subject: Change some e.Message to e.ToString. Don't use e.Message, it doesn't carry any useful information. Error messages are useless without location information. It looks more elegant, but is totally pointless. --- OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs index 92a6caa..e9ae3a3 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs @@ -81,7 +81,7 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (Exception e) { - m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: {1}", requestUrl, e.Message); + m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: " + e.ToString(), requestUrl); } finally { @@ -112,7 +112,7 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (Exception e) { - m_log.DebugFormat("[FORMS]: exception occured on receiving reply {0}", e.Message); + m_log.DebugFormat("[FORMS]: exception occured on receiving reply " + e.ToString()); } finally { -- cgit v1.1 From dc1baf802545329fc78d5fa36174e27025629527 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 25 Aug 2010 23:11:00 +0200 Subject: Change object cleanup again. Make scene object directories more robust and prevent deleted SOP's from sticking around --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 46 +++++++++++++++++---------- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c7b38a1..eb5c3cb 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3211,8 +3211,6 @@ namespace OpenSim.Region.Framework.Scenes m_eventManager.TriggerOnRemovePresence(agentID); m_log.Debug("[Scene] Finished OnRemovePresence"); - CleanDroppedAttachments(); - ForEachClient( delegate(IClientAPI client) { @@ -3248,6 +3246,7 @@ namespace OpenSim.Region.Framework.Scenes } m_log.Debug("[Scene] Done. Firing RemoveCircuit"); m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); + CleanDroppedAttachments(); m_log.Debug("[Scene] The avatar has left the building"); //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 94ec534..1268259 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Scenes protected internal Dictionary SceneObjectGroupsByLocalID = new Dictionary(); protected internal Dictionary SceneObjectGroupsByFullID = new Dictionary(); - private readonly Object m_dictionary_lock = new Object(); private Object m_updateLock = new Object(); @@ -150,11 +149,10 @@ namespace OpenSim.Region.Framework.Scenes m_scenePresencesLock.ExitWriteLock(); } - lock (m_dictionary_lock) - { + lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID.Clear(); + lock (SceneObjectGroupsByLocalID) SceneObjectGroupsByLocalID.Clear(); - } Entities.Clear(); } @@ -385,15 +383,17 @@ namespace OpenSim.Region.Framework.Scenes OnObjectCreate(sceneObject); } - lock (m_dictionary_lock) + lock (SceneObjectGroupsByFullID) { SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; - SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; foreach (SceneObjectPart part in sceneObject.Children.Values) - { SceneObjectGroupsByFullID[part.UUID] = sceneObject; + } + lock (SceneObjectGroupsByLocalID) + { + SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; + foreach (SceneObjectPart part in sceneObject.Children.Values) SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; - } } } @@ -408,24 +408,32 @@ namespace OpenSim.Region.Framework.Scenes { if (Entities.ContainsKey(uuid)) { + SceneObjectGroup grp = (SceneObjectGroup)Entities[uuid]; + if (!resultOfObjectLinked) { m_numPrim -= ((SceneObjectGroup) Entities[uuid]).Children.Count; - if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) - { - RemovePhysicalPrim(((SceneObjectGroup)Entities[uuid]).Children.Count); - } + if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) + RemovePhysicalPrim(grp.Children.Count); } if (OnObjectRemove != null) OnObjectRemove(Entities[uuid]); - lock (m_dictionary_lock) + lock (SceneObjectGroupsByFullID) { - SceneObjectGroupsByFullID.Remove(uuid); - SceneObjectGroupsByLocalID.Remove(((SceneObjectGroup)Entities[uuid]).LocalId); + foreach (SceneObjectPart part in grp.Children.Values) + SceneObjectGroupsByFullID.Remove(part.UUID); + SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); } + lock (SceneObjectGroupsByLocalID) + { + foreach (SceneObjectPart part in grp.Children.Values) + SceneObjectGroupsByLocalID.Remove(part.LocalId); + SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); + } + Entities.Remove(uuid); //SceneObjectGroup part; //((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) @@ -884,7 +892,9 @@ namespace OpenSim.Region.Framework.Scenes { if (SceneObjectGroupsByLocalID.TryGetValue(localID, out sog)) { - return sog; + if (sog.HasChildPrim(localID)) + return sog; + SceneObjectGroupsByLocalID.Remove(localID); } } @@ -920,7 +930,9 @@ namespace OpenSim.Region.Framework.Scenes { if (SceneObjectGroupsByFullID.TryGetValue(fullID, out sog)) { - return sog; + if (sog.Children.ContainsKey(fullID)) + return sog; + SceneObjectGroupsByFullID.Remove(fullID); } } -- cgit v1.1 From 1096f43f0d3db628b463d4494c98ad496cf1f039 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 25 Aug 2010 23:34:39 +0200 Subject: Prevent an object disposed exception that made forms comms unreliable. After starting an asynchronous write, one should not close the channel it will be written to synchrnously, that leads to grief. --- .../Servers/HttpServer/SynchronousRestFormsRequester.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs index e9ae3a3..f955df7 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs @@ -85,8 +85,13 @@ namespace OpenSim.Framework.Servers.HttpServer } finally { - if (requestStream != null) - requestStream.Close(); + // If this is closed, it will be disposed internally, + // but the above write is asynchronous and may hit after + // we're through here. So the thread handling that will + // throw and put us back into the catch above. Isn't + // .NET great? + //if (requestStream != null) + // requestStream.Close(); // Let's not close this //buffer.Close(); -- cgit v1.1 From 4b47008d30a42bd836ab3efeb399beb672a2446d Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 26 Aug 2010 00:37:54 +0200 Subject: Correct whitespace --- .../Shared/Api/Implementation/LS_Api.cs | 510 --------------------- 1 file changed, 510 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index 91e2c3b..665b39f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -1,512 +1,3 @@ -<<<<<<< HEAD:OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Reflection; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.Remoting.Lifetime; -using OpenMetaverse; -using Nini.Config; -using OpenSim; -using OpenSim.Framework; -using OpenSim.Region.CoreModules.World.LightShare; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenSim.Region.ScriptEngine.Interfaces; -using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; - -using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; -using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; -using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; -using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; - -namespace OpenSim.Region.ScriptEngine.Shared.Api -{ - [Serializable] - public class LS_Api : MarshalByRefObject, ILS_Api, IScriptApi - { - internal IScriptEngine m_ScriptEngine; - internal SceneObjectPart m_host; - internal uint m_localID; - internal UUID m_itemID; - internal bool m_LSFunctionsEnabled = false; - internal IScriptModuleComms m_comms = null; - - public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) - { - m_ScriptEngine = ScriptEngine; - m_host = host; - m_localID = localID; - m_itemID = itemID; - - if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) - m_LSFunctionsEnabled = true; - - if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false)) - m_LSFunctionsEnabled = true; - - m_comms = m_ScriptEngine.World.RequestModuleInterface(); - if (m_comms == null) - m_LSFunctionsEnabled = false; - } - - public override Object InitializeLifetimeService() - { - ILease lease = (ILease)base.InitializeLifetimeService(); - - if (lease.CurrentState == LeaseState.Initial) - { - lease.InitialLeaseTime = TimeSpan.FromMinutes(0); - // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); - // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); - } - return lease; - } - - public Scene World - { - get { return m_ScriptEngine.World; } - } - - // - //Dumps an error message on the debug console. - // - - internal void LSShoutError(string message) - { - if (message.Length > 1023) - message = message.Substring(0, 1023); - - World.SimChat(Utils.StringToBytes(message), - ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); - - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); - } - - /// - /// Get the current Windlight scene - /// - /// List of windlight parameters - public LSL_List lsGetWindlightScene(LSL_List rules) - { - if (!m_LSFunctionsEnabled) - { - LSShoutError("LightShare functions are not enabled."); - return new LSL_List(); - } - m_host.AddScriptLPS(1); - RegionLightShareData wl = m_host.ParentGroup.Scene.RegionInfo.WindlightSettings; - - LSL_List values = new LSL_List(); - int idx = 0; - while (idx < rules.Length) - { - uint rule = (uint)rules.GetLSLIntegerItem(idx); - LSL_List toadd = new LSL_List(); - - switch (rule) - { - case (int)ScriptBaseClass.WL_AMBIENT: - toadd.Add(new LSL_Rotation(wl.ambient.X, wl.ambient.Y, wl.ambient.Z, wl.ambient.W)); - break; - case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: - toadd.Add(new LSL_Vector(wl.bigWaveDirection.X, wl.bigWaveDirection.Y, 0.0f)); - break; - case (int)ScriptBaseClass.WL_BLUE_DENSITY: - toadd.Add(new LSL_Rotation(wl.blueDensity.X, wl.blueDensity.Y, wl.blueDensity.Z, wl.blueDensity.W)); - break; - case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: - toadd.Add(new LSL_Float(wl.blurMultiplier)); - break; - case (int)ScriptBaseClass.WL_CLOUD_COLOR: - toadd.Add(new LSL_Rotation(wl.cloudColor.X, wl.cloudColor.Y, wl.cloudColor.Z, wl.cloudColor.W)); - break; - case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: - toadd.Add(new LSL_Float(wl.cloudCoverage)); - break; - case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: - toadd.Add(new LSL_Vector(wl.cloudDetailXYDensity.X, wl.cloudDetailXYDensity.Y, wl.cloudDetailXYDensity.Z)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCALE: - toadd.Add(new LSL_Float(wl.cloudScale)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: - toadd.Add(new LSL_Float(wl.cloudScrollX)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: - toadd.Add(new LSL_Integer(wl.cloudScrollXLock ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: - toadd.Add(new LSL_Float(wl.cloudScrollY)); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: - toadd.Add(new LSL_Integer(wl.cloudScrollYLock ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: - toadd.Add(new LSL_Vector(wl.cloudXYDensity.X, wl.cloudXYDensity.Y, wl.cloudXYDensity.Z)); - break; - case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: - toadd.Add(new LSL_Float(wl.densityMultiplier)); - break; - case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: - toadd.Add(new LSL_Float(wl.distanceMultiplier)); - break; - case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: - toadd.Add(new LSL_Integer(wl.drawClassicClouds ? 1 : 0)); - break; - case (int)ScriptBaseClass.WL_EAST_ANGLE: - toadd.Add(new LSL_Float(wl.eastAngle)); - break; - case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: - toadd.Add(new LSL_Float(wl.fresnelOffset)); - break; - case (int)ScriptBaseClass.WL_FRESNEL_SCALE: - toadd.Add(new LSL_Float(wl.fresnelScale)); - break; - case (int)ScriptBaseClass.WL_HAZE_DENSITY: - toadd.Add(new LSL_Float(wl.hazeDensity)); - break; - case (int)ScriptBaseClass.WL_HAZE_HORIZON: - toadd.Add(new LSL_Float(wl.hazeHorizon)); - break; - case (int)ScriptBaseClass.WL_HORIZON: - toadd.Add(new LSL_Rotation(wl.horizon.X, wl.horizon.Y, wl.horizon.Z, wl.horizon.W)); - break; - case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: - toadd.Add(new LSL_Vector(wl.littleWaveDirection.X, wl.littleWaveDirection.Y, 0.0f)); - break; - case (int)ScriptBaseClass.WL_MAX_ALTITUDE: - toadd.Add(new LSL_Integer(wl.maxAltitude)); - break; - case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: - toadd.Add(new LSL_Key(wl.normalMapTexture.ToString())); - break; - case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: - toadd.Add(new LSL_Vector(wl.reflectionWaveletScale.X, wl.reflectionWaveletScale.Y, wl.reflectionWaveletScale.Z)); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: - toadd.Add(new LSL_Float(wl.refractScaleAbove)); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: - toadd.Add(new LSL_Float(wl.refractScaleBelow)); - break; - case (int)ScriptBaseClass.WL_SCENE_GAMMA: - toadd.Add(new LSL_Float(wl.sceneGamma)); - break; - case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: - toadd.Add(new LSL_Float(wl.starBrightness)); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: - toadd.Add(new LSL_Float(wl.sunGlowFocus)); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: - toadd.Add(new LSL_Float(wl.sunGlowSize)); - break; - case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: - toadd.Add(new LSL_Rotation(wl.sunMoonColor.X, wl.sunMoonColor.Y, wl.sunMoonColor.Z, wl.sunMoonColor.W)); - break; - case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: - toadd.Add(new LSL_Float(wl.underwaterFogModifier)); - break; - case (int)ScriptBaseClass.WL_WATER_COLOR: - toadd.Add(new LSL_Vector(wl.waterColor.X, wl.waterColor.Y, wl.waterColor.Z)); - break; - case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: - toadd.Add(new LSL_Float(wl.waterFogDensityExponent)); - break; - } - - if (toadd.Length > 0) - { - values.Add(new LSL_Integer(rule)); - values.Add(toadd.Data[0]); - } - idx++; - } - - - return values; - - } - - private RegionLightShareData getWindlightProfileFromRules(LSL_List rules) - { - RegionLightShareData wl = (RegionLightShareData)m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.Clone(); - - LSL_List values = new LSL_List(); - int idx = 0; - while (idx < rules.Length) - { - uint rule = (uint)rules.GetLSLIntegerItem(idx); - LSL_Types.Quaternion iQ; - LSL_Types.Vector3 iV; - switch (rule) - { - case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: - idx++; - wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_AMBIENT: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_BLUE_DENSITY: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: - idx++; - wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: - idx++; - wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCALE: - idx++; - wl.cloudScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: - idx++; - wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: - idx++; - wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: - idx++; - wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: - idx++; - wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: - idx++; - iV = rules.GetVector3Item(idx); - wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: - idx++; - wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: - idx++; - wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: - idx++; - wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; - break; - case (int)ScriptBaseClass.WL_EAST_ANGLE: - idx++; - wl.eastAngle = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: - idx++; - wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_FRESNEL_SCALE: - idx++; - wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_DENSITY: - idx++; - wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HAZE_HORIZON: - idx++; - wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_HORIZON: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: - idx++; - iV = rules.GetVector3Item(idx); - wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); - break; - case (int)ScriptBaseClass.WL_MAX_ALTITUDE: - idx++; - wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; - break; - case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: - idx++; - wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); - break; - case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: - idx++; - iV = rules.GetVector3Item(idx); - wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: - idx++; - wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: - idx++; - wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SCENE_GAMMA: - idx++; - wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: - idx++; - wl.starBrightness = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: - idx++; - wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: - idx++; - wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: - idx++; - iQ = rules.GetQuaternionItem(idx); - wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); - break; - case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: - idx++; - wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); - break; - case (int)ScriptBaseClass.WL_WATER_COLOR: - idx++; - iV = rules.GetVector3Item(idx); - wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); - break; - case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: - idx++; - wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); - break; - } - idx++; - } - return wl; - } - /// - /// Set the current Windlight scene - /// - /// - /// success: true or false - public int lsSetWindlightScene(LSL_List rules) - { - if (!m_LSFunctionsEnabled) - { - LSShoutError("LightShare functions are not enabled."); - return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); - return 0; - } - int success = 0; - m_host.AddScriptLPS(1); - if (LightShareModule.EnableWindlight) - { - RegionLightShareData wl = getWindlightProfileFromRules(rules); - m_host.ParentGroup.Scene.StoreWindlightProfile(wl); - success = 1; - } - else - { - LSShoutError("Windlight module is disabled"); - return 0; - } - return success; - } - /// - /// Set the current Windlight scene to a target avatar - /// - /// - /// success: true or false - public int lsSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) - { - if (!m_LSFunctionsEnabled) - { - LSShoutError("LightShare functions are not enabled."); - return 0; - } - if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) - { - LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); - return 0; - } - int success = 0; - m_host.AddScriptLPS(1); - if (LightShareModule.EnableWindlight) - { - RegionLightShareData wl = getWindlightProfileFromRules(rules); - World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); - success = 1; - } - else - { - LSShoutError("Windlight module is disabled"); - return 0; - } - return success; - } - - } -} -======= /* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. @@ -1009,4 +500,3 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } ->>>>>>> master:OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs -- cgit v1.1 From 47818a2db303eefaf59f7c98d03112bfb1371379 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 26 Aug 2010 01:06:50 +0200 Subject: Fix a horrible bug in SG, where iteration of scene objects is carried out in a fashion that causes the delegate to be invoked once per child prim for a given group. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 9c5ee60..1d952c4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1140,9 +1140,11 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void ForEachSOG(Action action) { - List objlist = new List(SceneObjectGroupsByFullID.Values); - foreach (SceneObjectGroup obj in objlist) + List objlist = Entities.GetAllByType(); + foreach (EntityBase ent in objlist) { + SceneObjectGroup obj = (SceneObjectGroup)ent; + try { action(obj); -- cgit v1.1 From 8ee31d97a84632e4b6144cf81c4fdcd1e764df7c Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 30 Aug 2010 02:19:21 +0100 Subject: Remove CRLF endings --- .../Region/CoreModules/World/Land/LandObject.cs | 2090 ++++++++++---------- 1 file changed, 1045 insertions(+), 1045 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index fcd993c..9e9934e 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -1,1045 +1,1045 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; - -namespace OpenSim.Region.CoreModules.World.Land -{ - /// - /// Keeps track of a specific piece of land's information - /// - public class LandObject : ILandObject - { - #region Member Variables - - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - #pragma warning disable 0429 - private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64; - #pragma warning restore 0429 - private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax]; - - private int m_lastSeqId = 0; - - protected LandData m_landData = new LandData(); - protected Scene m_scene; - protected List primsOverMe = new List(); - - public bool[,] LandBitmap - { - get { return m_landBitmap; } - set { m_landBitmap = value; } - } - - #endregion - - #region ILandObject Members - - public LandData LandData - { - get { return m_landData; } - - set { m_landData = value; } - } - - public UUID RegionUUID - { - get { return m_scene.RegionInfo.RegionID; } - } - - #region Constructors - - public LandObject(UUID owner_id, bool is_group_owned, Scene scene) - { - m_scene = scene; - LandData.OwnerID = owner_id; - if (is_group_owned) - LandData.GroupID = owner_id; - else - LandData.GroupID = UUID.Zero; - LandData.IsGroupOwned = is_group_owned; - } - - #endregion - - #region Member Functions - - #region General Functions - - /// - /// Checks to see if this land object contains a point - /// - /// - /// - /// Returns true if the piece of land contains the specified point - public bool ContainsPoint(int x, int y) - { - if (x >= 0 && y >= 0 && x <= Constants.RegionSize && y <= Constants.RegionSize) - { - return (LandBitmap[x / 4, y / 4] == true); - } - else - { - return false; - } - } - - public ILandObject Copy() - { - ILandObject newLand = new LandObject(LandData.OwnerID, LandData.IsGroupOwned, m_scene); - - //Place all new variables here! - newLand.LandBitmap = (bool[,]) (LandBitmap.Clone()); - newLand.LandData = LandData.Copy(); - - return newLand; - } - - static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount; - static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount; - - public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) - { - overrideParcelMaxPrimCount = overrideDel; - } - public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) - { - overrideSimulatorMaxPrimCount = overrideDel; - } - - public int GetParcelMaxPrimCount(ILandObject thisObject) - { - if (overrideParcelMaxPrimCount != null) - { - return overrideParcelMaxPrimCount(thisObject); - } - else - { - // Normal Calculations - return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); - } - } - public int GetSimulatorMaxPrimCount(ILandObject thisObject) - { - if (overrideSimulatorMaxPrimCount != null) - { - return overrideSimulatorMaxPrimCount(thisObject); - } - else - { - //Normal Calculations - return m_scene.RegionInfo.ObjectCapacity; - } - } - #endregion - - #region Packet Request Handling - - public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) - { - IEstateModule estateModule = m_scene.RequestModuleInterface(); - uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); - if (estateModule != null) - regionFlags = estateModule.GetRegionFlags(); - - // In a perfect world, this would have worked. - // -// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0) -// regionFlags |= (uint)RegionFlags.AllowLandmark; -// if (landData.OwnerID == remote_client.AgentId) -// regionFlags |= (uint)RegionFlags.AllowSetHome; - - int seq_id; - if (snap_selection && (sequence_id == 0)) - { - seq_id = m_lastSeqId; - } - else - { - seq_id = sequence_id; - m_lastSeqId = seq_id; - } - - remote_client.SendLandProperties(seq_id, - snap_selection, request_result, LandData, - (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, - GetParcelMaxPrimCount(this), - GetSimulatorMaxPrimCount(this), regionFlags); - } - - public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) - { - if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this)) - { - //Needs later group support - bool snap_selection = false; - LandData newData = LandData.Copy(); - - if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice) - { - if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this)) - { - newData.AuthBuyerID = args.AuthBuyerID; - newData.SalePrice = args.SalePrice; - snap_selection = true; - } - } - newData.Category = args.Category; - newData.Description = args.Desc; - newData.GroupID = args.GroupID; - newData.LandingType = args.LandingType; - newData.MediaAutoScale = args.MediaAutoScale; - newData.MediaID = args.MediaID; - newData.MediaURL = args.MediaURL; - newData.MusicURL = args.MusicURL; - newData.Name = args.Name; - newData.Flags = args.ParcelFlags; - newData.PassHours = args.PassHours; - newData.PassPrice = args.PassPrice; - newData.SnapshotID = args.SnapshotID; - newData.UserLocation = args.UserLocation; - newData.UserLookAt = args.UserLookAt; - - m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - - SendLandUpdateToAvatarsOverMe(snap_selection); - } - } - - public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) - { - LandData newData = LandData.Copy(); - newData.OwnerID = avatarID; - newData.GroupID = groupID; - newData.IsGroupOwned = groupOwned; - //newData.auctionID = AuctionID; - newData.ClaimDate = Util.UnixTimeSinceEpoch(); - newData.ClaimPrice = claimprice; - newData.SalePrice = 0; - newData.AuthBuyerID = UUID.Zero; - newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); - m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - - SendLandUpdateToAvatarsOverMe(true); - } - - public void DeedToGroup(UUID groupID) - { - LandData newData = LandData.Copy(); - newData.OwnerID = groupID; - newData.GroupID = groupID; - newData.IsGroupOwned = true; - - // Reset show in directory flag on deed - newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); - - m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - - SendLandUpdateToAvatarsOverMe(true); - } - - public bool IsEitherBannedOrRestricted(UUID avatar) - { - if (IsBannedFromLand(avatar)) - { - return true; - } - else if (IsRestrictedFromLand(avatar)) - { - return true; - } - return false; - } - - public bool HasGroupAccess(UUID avatar) - { - if ((LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) - { - IGroupsModule groupsModule = - m_scene.RequestModuleInterface(); - - List agentGroups = new List(); - if (groupsModule != null) - { - GroupMembershipData[] GroupMembership = - groupsModule.GetMembershipData(avatar); - - if (GroupMembership != null) - { - for (int i = 0; i < GroupMembership.Length; i++) - { - if (LandData.GroupID == GroupMembership[i].GroupID) - { - return true; - } - } - } - } - } - return false; - } - - public bool IsBannedFromLand(UUID avatar) - { - if (m_scene.Permissions.IsAdministrator(avatar)) - return false; - - if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = avatar; - entry.Flags = AccessList.Ban; - entry.Time = new DateTime(); - //See if they are on the list, but make sure the owner isn't banned - if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) - { - //They are banned, so lets send them a notice about this parcel - return true; - } - } - return false; - } - - public bool IsRestrictedFromLand(UUID avatar) - { - if (m_scene.Permissions.IsAdministrator(avatar)) - return false; - - if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) - { - ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); - entry.AgentID = avatar; - entry.Flags = AccessList.Access; - entry.Time = new DateTime(); - - //If they are not on the access list and are not the owner - if (!LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) - { - if (!HasGroupAccess(avatar)) - { - //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel - return true; - } - } - } - - return false; - } - - public void SendLandUpdateToClient(IClientAPI remote_client) - { - SendLandProperties(0, false, 0, remote_client); - } - - public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client) - { - SendLandProperties(0, snap_selection, 0, remote_client); - } - - public void SendLandUpdateToAvatarsOverMe() - { - SendLandUpdateToAvatarsOverMe(false); - } - - public void SendLandUpdateToAvatarsOverMe(bool snap_selection) - { - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) - { - if (avatar.IsChildAgent) - return; - - ILandObject over = null; - try - { - over = - m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)), - Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1))); - } - catch (Exception) - { - m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " + - Math.Round(avatar.AbsolutePosition.Y)); - } - - if (over != null) - { - if (over.LandData.LocalID == LandData.LocalID) - { - if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) && - m_scene.RegionInfo.RegionSettings.AllowDamage) - avatar.Invulnerable = false; - else - avatar.Invulnerable = true; - - SendLandUpdateToClient(snap_selection, avatar.ControllingClient); - } - } - }); - } - - #endregion - - #region AccessList Functions - - public List CreateAccessListArrayByFlag(AccessList flag) - { - List list = new List(); - foreach (ParcelManager.ParcelAccessEntry entry in LandData.ParcelAccessList) - { - if (entry.Flags == flag) - { - list.Add(entry.AgentID); - } - } - if (list.Count == 0) - { - list.Add(UUID.Zero); - } - - return list; - } - - public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID, - IClientAPI remote_client) - { - - if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both) - { - List avatars = CreateAccessListArrayByFlag(AccessList.Access); - remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,LandData.LocalID); - } - - if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both) - { - List avatars = CreateAccessListArrayByFlag(AccessList.Ban); - remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, LandData.LocalID); - } - } - - public void UpdateAccessList(uint flags, List entries, IClientAPI remote_client) - { - LandData newData = LandData.Copy(); - - if (entries.Count == 1 && entries[0].AgentID == UUID.Zero) - { - entries.Clear(); - } - - List toRemove = new List(); - foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList) - { - if (entry.Flags == (AccessList)flags) - { - toRemove.Add(entry); - } - } - - foreach (ParcelManager.ParcelAccessEntry entry in toRemove) - { - newData.ParcelAccessList.Remove(entry); - } - foreach (ParcelManager.ParcelAccessEntry entry in entries) - { - ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry(); - temp.AgentID = entry.AgentID; - temp.Time = new DateTime(); //Pointless? Yes. - temp.Flags = (AccessList)flags; - - if (!newData.ParcelAccessList.Contains(temp)) - { - newData.ParcelAccessList.Add(temp); - } - } - - m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); - } - - #endregion - - #region Update Functions - - public void UpdateLandBitmapByteArray() - { - LandData.Bitmap = ConvertLandBitmapToBytes(); - } - - /// - /// Update all settings in land such as area, bitmap byte array, etc - /// - public void ForceUpdateLandInfo() - { - UpdateAABBAndAreaValues(); - UpdateLandBitmapByteArray(); - } - - public void SetLandBitmapFromByteArray() - { - LandBitmap = ConvertBytesToLandBitmap(); - } - - /// - /// Updates the AABBMin and AABBMax values after area/shape modification of the land object - /// - private void UpdateAABBAndAreaValues() - { - int min_x = 64; - int min_y = 64; - int max_x = 0; - int max_y = 0; - int tempArea = 0; - int x, y; - for (x = 0; x < 64; x++) - { - for (y = 0; y < 64; y++) - { - if (LandBitmap[x, y] == true) - { - if (min_x > x) min_x = x; - if (min_y > y) min_y = y; - if (max_x < x) max_x = x; - if (max_y < y) max_y = y; - tempArea += 16; //16sqm peice of land - } - } - } - int tx = min_x * 4; - if (tx > ((int)Constants.RegionSize - 1)) - tx = ((int)Constants.RegionSize - 1); - int ty = min_y * 4; - if (ty > ((int)Constants.RegionSize - 1)) - ty = ((int)Constants.RegionSize - 1); - LandData.AABBMin = - new Vector3((float) (min_x * 4), (float) (min_y * 4), - (float) m_scene.Heightmap[tx, ty]); - - tx = max_x * 4; - if (tx > ((int)Constants.RegionSize - 1)) - tx = ((int)Constants.RegionSize - 1); - ty = max_y * 4; - if (ty > ((int)Constants.RegionSize - 1)) - ty = ((int)Constants.RegionSize - 1); - LandData.AABBMax = - new Vector3((float) (max_x * 4), (float) (max_y * 4), - (float) m_scene.Heightmap[tx, ty]); - LandData.Area = tempArea; - } - - #endregion - - #region Land Bitmap Functions - - /// - /// Sets the land's bitmap manually - /// - /// 64x64 block representing where this land is on a map - public void SetLandBitmap(bool[,] bitmap) - { - if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - //throw new Exception("Error: Invalid Parcel Bitmap"); - } - else - { - //Valid: Lets set it - LandBitmap = bitmap; - ForceUpdateLandInfo(); - } - } - - /// - /// Gets the land's bitmap manually - /// - /// - public bool[,] GetLandBitmap() - { - return LandBitmap; - } - - /// - /// Full sim land object creation - /// - /// - public bool[,] BasicFullRegionLandBitmap() - { - return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); - } - - /// - /// Used to modify the bitmap between the x and y points. Points use 64 scale - /// - /// - /// - /// - /// - /// - public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) - { - bool[,] tempBitmap = new bool[64,64]; - tempBitmap.Initialize(); - - tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); - return tempBitmap; - } - - /// - /// Change a land bitmap at within a square and set those points to a specific value - /// - /// - /// - /// - /// - /// - /// - /// - public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, - bool set_value) - { - if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()"); - } - - int x, y; - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - if (x >= start_x / 4 && x < end_x / 4 - && y >= start_y / 4 && y < end_y / 4) - { - land_bitmap[x, y] = set_value; - } - } - } - return land_bitmap; - } - - /// - /// Join the true values of 2 bitmaps together - /// - /// - /// - /// - public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) - { - if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); - } - if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) - { - //Throw an exception - The bitmap is not 64x64 - throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps"); - } - - int x, y; - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - if (bitmap_add[x, y]) - { - bitmap_base[x, y] = true; - } - } - } - return bitmap_base; - } - - /// - /// Converts the land bitmap to a packet friendly byte array - /// - /// - private byte[] ConvertLandBitmapToBytes() - { - byte[] tempConvertArr = new byte[512]; - byte tempByte = 0; - int x, y, i, byteNum = 0; - i = 0; - for (y = 0; y < 64; y++) - { - for (x = 0; x < 64; x++) - { - tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); - if (i % 8 == 0) - { - tempConvertArr[byteNum] = tempByte; - tempByte = (byte) 0; - i = 0; - byteNum++; - } - } - } - return tempConvertArr; - } - - private bool[,] ConvertBytesToLandBitmap() - { - bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax]; - tempConvertMap.Initialize(); - byte tempByte = 0; - int x = 0, y = 0, i = 0, bitNum = 0; - for (i = 0; i < 512; i++) - { - tempByte = LandData.Bitmap[i]; - for (bitNum = 0; bitNum < 8; bitNum++) - { - bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); - tempConvertMap[x, y] = bit; - x++; - if (x > 63) - { - x = 0; - y++; - } - } - } - return tempConvertMap; - } - - #endregion - - #region Object Select and Object Owner Listing - - public void SendForceObjectSelect(int local_id, int request_type, List returnIDs, IClientAPI remote_client) - { - if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) - { - List resultLocalIDs = new List(); - try - { - lock (primsOverMe) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.LocalId > 0) - { - if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID) - { - resultLocalIDs.Add(obj.LocalId); - } - else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero) - { - resultLocalIDs.Add(obj.LocalId); - } - else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER && - obj.OwnerID != remote_client.AgentId) - { - resultLocalIDs.Add(obj.LocalId); - } - else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID)) - { - resultLocalIDs.Add(obj.LocalId); - } - } - } - } - } catch (InvalidOperationException) - { - m_log.Error("[LAND]: Unable to force select the parcel objects. Arr."); - } - - remote_client.SendForceClientSelectObjects(resultLocalIDs); - } - } - - /// - /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes - /// aggreagete details such as the number of prims. - /// - /// - /// - /// A - /// - public void SendLandObjectOwners(IClientAPI remote_client) - { - if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) - { - Dictionary primCount = new Dictionary(); - List groups = new List(); - - lock (primsOverMe) - { - try - { - - foreach (SceneObjectGroup obj in primsOverMe) - { - try - { - if (!primCount.ContainsKey(obj.OwnerID)) - { - primCount.Add(obj.OwnerID, 0); - } - } - catch (NullReferenceException) - { - m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel"); - } - try - { - primCount[obj.OwnerID] += obj.PrimCount; - } - catch (KeyNotFoundException) - { - m_log.Error("[LAND]: Unable to match a prim with it's owner."); - } - if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID))) - groups.Add(obj.OwnerID); - } - } - catch (InvalidOperationException) - { - m_log.Error("[LAND]: Unable to Enumerate Land object arr."); - } - } - - remote_client.SendLandObjectOwners(LandData, groups, primCount); - } - } - - public Dictionary GetLandObjectOwners() - { - Dictionary ownersAndCount = new Dictionary(); - lock (primsOverMe) - { - try - { - - foreach (SceneObjectGroup obj in primsOverMe) - { - if (!ownersAndCount.ContainsKey(obj.OwnerID)) - { - ownersAndCount.Add(obj.OwnerID, 0); - } - ownersAndCount[obj.OwnerID] += obj.PrimCount; - } - } - catch (InvalidOperationException) - { - m_log.Error("[LAND]: Unable to enumerate land owners. arr."); - } - - } - return ownersAndCount; - } - - #endregion - - #region Object Returning - - public void ReturnObject(SceneObjectGroup obj) - { - SceneObjectGroup[] objs = new SceneObjectGroup[1]; - objs[0] = obj; - m_scene.returnObjects(objs, obj.OwnerID); - } - - public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) - { - Dictionary> returns = - new Dictionary>(); - - lock (primsOverMe) - { - if (type == (uint)ObjectReturnType.Owner) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.OwnerID == m_landData.OwnerID) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.GroupID == m_landData.GroupID) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - else if (type == (uint)ObjectReturnType.Other) - { - foreach (SceneObjectGroup obj in primsOverMe) - { - if (obj.OwnerID != m_landData.OwnerID && - (obj.GroupID != m_landData.GroupID || - m_landData.GroupID == UUID.Zero)) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - else if (type == (uint)ObjectReturnType.List) - { - List ownerlist = new List(owners); - - foreach (SceneObjectGroup obj in primsOverMe) - { - if (ownerlist.Contains(obj.OwnerID)) - { - if (!returns.ContainsKey(obj.OwnerID)) - returns[obj.OwnerID] = - new List(); - returns[obj.OwnerID].Add(obj); - } - } - } - } - - foreach (List ol in returns.Values) - { - if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) - m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); - } - } - - #endregion - - #region Object Adding/Removing from Parcel - - public void ResetLandPrimCounts() - { - LandData.GroupPrims = 0; - LandData.OwnerPrims = 0; - LandData.OtherPrims = 0; - LandData.SelectedPrims = 0; - - - lock (primsOverMe) - primsOverMe.Clear(); - } - - public void AddPrimToCount(SceneObjectGroup obj) - { - - UUID prim_owner = obj.OwnerID; - int prim_count = obj.PrimCount; - - if (obj.IsSelected) - { - LandData.SelectedPrims += prim_count; - } - else - { - if (prim_owner == LandData.OwnerID) - { - LandData.OwnerPrims += prim_count; - } - else if ((obj.GroupID == LandData.GroupID || - prim_owner == LandData.GroupID) && - LandData.GroupID != UUID.Zero) - { - LandData.GroupPrims += prim_count; - } - else - { - LandData.OtherPrims += prim_count; - } - } - - lock (primsOverMe) - primsOverMe.Add(obj); - } - - public void RemovePrimFromCount(SceneObjectGroup obj) - { - lock (primsOverMe) - { - if (primsOverMe.Contains(obj)) - { - UUID prim_owner = obj.OwnerID; - int prim_count = obj.PrimCount; - - if (prim_owner == LandData.OwnerID) - { - LandData.OwnerPrims -= prim_count; - } - else if (obj.GroupID == LandData.GroupID || - prim_owner == LandData.GroupID) - { - LandData.GroupPrims -= prim_count; - } - else - { - LandData.OtherPrims -= prim_count; - } - - primsOverMe.Remove(obj); - } - } - } - - #endregion - - #endregion - - #endregion - - /// - /// Set the media url for this land parcel - /// - /// - public void SetMediaUrl(string url) - { - LandData.MediaURL = url; - SendLandUpdateToAvatarsOverMe(); - } - - /// - /// Set the music url for this land parcel - /// - /// - public void SetMusicUrl(string url) - { - LandData.MusicURL = url; - SendLandUpdateToAvatarsOverMe(); - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Land +{ + /// + /// Keeps track of a specific piece of land's information + /// + public class LandObject : ILandObject + { + #region Member Variables + + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + #pragma warning disable 0429 + private const int landArrayMax = ((int)((int)Constants.RegionSize / 4) >= 64) ? (int)((int)Constants.RegionSize / 4) : 64; + #pragma warning restore 0429 + private bool[,] m_landBitmap = new bool[landArrayMax,landArrayMax]; + + private int m_lastSeqId = 0; + + protected LandData m_landData = new LandData(); + protected Scene m_scene; + protected List primsOverMe = new List(); + + public bool[,] LandBitmap + { + get { return m_landBitmap; } + set { m_landBitmap = value; } + } + + #endregion + + #region ILandObject Members + + public LandData LandData + { + get { return m_landData; } + + set { m_landData = value; } + } + + public UUID RegionUUID + { + get { return m_scene.RegionInfo.RegionID; } + } + + #region Constructors + + public LandObject(UUID owner_id, bool is_group_owned, Scene scene) + { + m_scene = scene; + LandData.OwnerID = owner_id; + if (is_group_owned) + LandData.GroupID = owner_id; + else + LandData.GroupID = UUID.Zero; + LandData.IsGroupOwned = is_group_owned; + } + + #endregion + + #region Member Functions + + #region General Functions + + /// + /// Checks to see if this land object contains a point + /// + /// + /// + /// Returns true if the piece of land contains the specified point + public bool ContainsPoint(int x, int y) + { + if (x >= 0 && y >= 0 && x <= Constants.RegionSize && y <= Constants.RegionSize) + { + return (LandBitmap[x / 4, y / 4] == true); + } + else + { + return false; + } + } + + public ILandObject Copy() + { + ILandObject newLand = new LandObject(LandData.OwnerID, LandData.IsGroupOwned, m_scene); + + //Place all new variables here! + newLand.LandBitmap = (bool[,]) (LandBitmap.Clone()); + newLand.LandData = LandData.Copy(); + + return newLand; + } + + static overrideParcelMaxPrimCountDelegate overrideParcelMaxPrimCount; + static overrideSimulatorMaxPrimCountDelegate overrideSimulatorMaxPrimCount; + + public void SetParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) + { + overrideParcelMaxPrimCount = overrideDel; + } + public void SetSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) + { + overrideSimulatorMaxPrimCount = overrideDel; + } + + public int GetParcelMaxPrimCount(ILandObject thisObject) + { + if (overrideParcelMaxPrimCount != null) + { + return overrideParcelMaxPrimCount(thisObject); + } + else + { + // Normal Calculations + return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); + } + } + public int GetSimulatorMaxPrimCount(ILandObject thisObject) + { + if (overrideSimulatorMaxPrimCount != null) + { + return overrideSimulatorMaxPrimCount(thisObject); + } + else + { + //Normal Calculations + return m_scene.RegionInfo.ObjectCapacity; + } + } + #endregion + + #region Packet Request Handling + + public void SendLandProperties(int sequence_id, bool snap_selection, int request_result, IClientAPI remote_client) + { + IEstateModule estateModule = m_scene.RequestModuleInterface(); + uint regionFlags = 336723974 & ~((uint)(RegionFlags.AllowLandmark | RegionFlags.AllowSetHome)); + if (estateModule != null) + regionFlags = estateModule.GetRegionFlags(); + + // In a perfect world, this would have worked. + // +// if ((landData.Flags & (uint)ParcelFlags.AllowLandmark) != 0) +// regionFlags |= (uint)RegionFlags.AllowLandmark; +// if (landData.OwnerID == remote_client.AgentId) +// regionFlags |= (uint)RegionFlags.AllowSetHome; + + int seq_id; + if (snap_selection && (sequence_id == 0)) + { + seq_id = m_lastSeqId; + } + else + { + seq_id = sequence_id; + m_lastSeqId = seq_id; + } + + remote_client.SendLandProperties(seq_id, + snap_selection, request_result, LandData, + (float)m_scene.RegionInfo.RegionSettings.ObjectBonus, + GetParcelMaxPrimCount(this), + GetSimulatorMaxPrimCount(this), regionFlags); + } + + public void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client) + { + if (m_scene.Permissions.CanEditParcel(remote_client.AgentId,this)) + { + //Needs later group support + bool snap_selection = false; + LandData newData = LandData.Copy(); + + if (args.AuthBuyerID != newData.AuthBuyerID || args.SalePrice != newData.SalePrice) + { + if (m_scene.Permissions.CanSellParcel(remote_client.AgentId, this)) + { + newData.AuthBuyerID = args.AuthBuyerID; + newData.SalePrice = args.SalePrice; + snap_selection = true; + } + } + newData.Category = args.Category; + newData.Description = args.Desc; + newData.GroupID = args.GroupID; + newData.LandingType = args.LandingType; + newData.MediaAutoScale = args.MediaAutoScale; + newData.MediaID = args.MediaID; + newData.MediaURL = args.MediaURL; + newData.MusicURL = args.MusicURL; + newData.Name = args.Name; + newData.Flags = args.ParcelFlags; + newData.PassHours = args.PassHours; + newData.PassPrice = args.PassPrice; + newData.SnapshotID = args.SnapshotID; + newData.UserLocation = args.UserLocation; + newData.UserLookAt = args.UserLookAt; + + m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); + + SendLandUpdateToAvatarsOverMe(snap_selection); + } + } + + public void UpdateLandSold(UUID avatarID, UUID groupID, bool groupOwned, uint AuctionID, int claimprice, int area) + { + LandData newData = LandData.Copy(); + newData.OwnerID = avatarID; + newData.GroupID = groupID; + newData.IsGroupOwned = groupOwned; + //newData.auctionID = AuctionID; + newData.ClaimDate = Util.UnixTimeSinceEpoch(); + newData.ClaimPrice = claimprice; + newData.SalePrice = 0; + newData.AuthBuyerID = UUID.Zero; + newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); + m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); + + SendLandUpdateToAvatarsOverMe(true); + } + + public void DeedToGroup(UUID groupID) + { + LandData newData = LandData.Copy(); + newData.OwnerID = groupID; + newData.GroupID = groupID; + newData.IsGroupOwned = true; + + // Reset show in directory flag on deed + newData.Flags &= ~(uint) (ParcelFlags.ForSale | ParcelFlags.ForSaleObjects | ParcelFlags.SellParcelObjects | ParcelFlags.ShowDirectory); + + m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); + + SendLandUpdateToAvatarsOverMe(true); + } + + public bool IsEitherBannedOrRestricted(UUID avatar) + { + if (IsBannedFromLand(avatar)) + { + return true; + } + else if (IsRestrictedFromLand(avatar)) + { + return true; + } + return false; + } + + public bool HasGroupAccess(UUID avatar) + { + if ((LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) + { + IGroupsModule groupsModule = + m_scene.RequestModuleInterface(); + + List agentGroups = new List(); + if (groupsModule != null) + { + GroupMembershipData[] GroupMembership = + groupsModule.GetMembershipData(avatar); + + if (GroupMembership != null) + { + for (int i = 0; i < GroupMembership.Length; i++) + { + if (LandData.GroupID == GroupMembership[i].GroupID) + { + return true; + } + } + } + } + } + return false; + } + + public bool IsBannedFromLand(UUID avatar) + { + if (m_scene.Permissions.IsAdministrator(avatar)) + return false; + + if ((LandData.Flags & (uint) ParcelFlags.UseBanList) > 0) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = avatar; + entry.Flags = AccessList.Ban; + entry.Time = new DateTime(); + //See if they are on the list, but make sure the owner isn't banned + if (LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) + { + //They are banned, so lets send them a notice about this parcel + return true; + } + } + return false; + } + + public bool IsRestrictedFromLand(UUID avatar) + { + if (m_scene.Permissions.IsAdministrator(avatar)) + return false; + + if ((LandData.Flags & (uint) ParcelFlags.UseAccessList) > 0) + { + ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); + entry.AgentID = avatar; + entry.Flags = AccessList.Access; + entry.Time = new DateTime(); + + //If they are not on the access list and are not the owner + if (!LandData.ParcelAccessList.Contains(entry) && LandData.OwnerID != avatar) + { + if (!HasGroupAccess(avatar)) + { + //They are not allowed in this parcel, but not banned, so lets send them a notice about this parcel + return true; + } + } + } + + return false; + } + + public void SendLandUpdateToClient(IClientAPI remote_client) + { + SendLandProperties(0, false, 0, remote_client); + } + + public void SendLandUpdateToClient(bool snap_selection, IClientAPI remote_client) + { + SendLandProperties(0, snap_selection, 0, remote_client); + } + + public void SendLandUpdateToAvatarsOverMe() + { + SendLandUpdateToAvatarsOverMe(false); + } + + public void SendLandUpdateToAvatarsOverMe(bool snap_selection) + { + m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + { + if (avatar.IsChildAgent) + return; + + ILandObject over = null; + try + { + over = + m_scene.LandChannel.GetLandObject(Util.Clamp((int)Math.Round(avatar.AbsolutePosition.X), 0, ((int)Constants.RegionSize - 1)), + Util.Clamp((int)Math.Round(avatar.AbsolutePosition.Y), 0, ((int)Constants.RegionSize - 1))); + } + catch (Exception) + { + m_log.Warn("[LAND]: " + "unable to get land at x: " + Math.Round(avatar.AbsolutePosition.X) + " y: " + + Math.Round(avatar.AbsolutePosition.Y)); + } + + if (over != null) + { + if (over.LandData.LocalID == LandData.LocalID) + { + if (((over.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) && + m_scene.RegionInfo.RegionSettings.AllowDamage) + avatar.Invulnerable = false; + else + avatar.Invulnerable = true; + + SendLandUpdateToClient(snap_selection, avatar.ControllingClient); + } + } + }); + } + + #endregion + + #region AccessList Functions + + public List CreateAccessListArrayByFlag(AccessList flag) + { + List list = new List(); + foreach (ParcelManager.ParcelAccessEntry entry in LandData.ParcelAccessList) + { + if (entry.Flags == flag) + { + list.Add(entry.AgentID); + } + } + if (list.Count == 0) + { + list.Add(UUID.Zero); + } + + return list; + } + + public void SendAccessList(UUID agentID, UUID sessionID, uint flags, int sequenceID, + IClientAPI remote_client) + { + + if (flags == (uint) AccessList.Access || flags == (uint) AccessList.Both) + { + List avatars = CreateAccessListArrayByFlag(AccessList.Access); + remote_client.SendLandAccessListData(avatars,(uint) AccessList.Access,LandData.LocalID); + } + + if (flags == (uint) AccessList.Ban || flags == (uint) AccessList.Both) + { + List avatars = CreateAccessListArrayByFlag(AccessList.Ban); + remote_client.SendLandAccessListData(avatars, (uint)AccessList.Ban, LandData.LocalID); + } + } + + public void UpdateAccessList(uint flags, List entries, IClientAPI remote_client) + { + LandData newData = LandData.Copy(); + + if (entries.Count == 1 && entries[0].AgentID == UUID.Zero) + { + entries.Clear(); + } + + List toRemove = new List(); + foreach (ParcelManager.ParcelAccessEntry entry in newData.ParcelAccessList) + { + if (entry.Flags == (AccessList)flags) + { + toRemove.Add(entry); + } + } + + foreach (ParcelManager.ParcelAccessEntry entry in toRemove) + { + newData.ParcelAccessList.Remove(entry); + } + foreach (ParcelManager.ParcelAccessEntry entry in entries) + { + ParcelManager.ParcelAccessEntry temp = new ParcelManager.ParcelAccessEntry(); + temp.AgentID = entry.AgentID; + temp.Time = new DateTime(); //Pointless? Yes. + temp.Flags = (AccessList)flags; + + if (!newData.ParcelAccessList.Contains(temp)) + { + newData.ParcelAccessList.Add(temp); + } + } + + m_scene.LandChannel.UpdateLandObject(LandData.LocalID, newData); + } + + #endregion + + #region Update Functions + + public void UpdateLandBitmapByteArray() + { + LandData.Bitmap = ConvertLandBitmapToBytes(); + } + + /// + /// Update all settings in land such as area, bitmap byte array, etc + /// + public void ForceUpdateLandInfo() + { + UpdateAABBAndAreaValues(); + UpdateLandBitmapByteArray(); + } + + public void SetLandBitmapFromByteArray() + { + LandBitmap = ConvertBytesToLandBitmap(); + } + + /// + /// Updates the AABBMin and AABBMax values after area/shape modification of the land object + /// + private void UpdateAABBAndAreaValues() + { + int min_x = 64; + int min_y = 64; + int max_x = 0; + int max_y = 0; + int tempArea = 0; + int x, y; + for (x = 0; x < 64; x++) + { + for (y = 0; y < 64; y++) + { + if (LandBitmap[x, y] == true) + { + if (min_x > x) min_x = x; + if (min_y > y) min_y = y; + if (max_x < x) max_x = x; + if (max_y < y) max_y = y; + tempArea += 16; //16sqm peice of land + } + } + } + int tx = min_x * 4; + if (tx > ((int)Constants.RegionSize - 1)) + tx = ((int)Constants.RegionSize - 1); + int ty = min_y * 4; + if (ty > ((int)Constants.RegionSize - 1)) + ty = ((int)Constants.RegionSize - 1); + LandData.AABBMin = + new Vector3((float) (min_x * 4), (float) (min_y * 4), + (float) m_scene.Heightmap[tx, ty]); + + tx = max_x * 4; + if (tx > ((int)Constants.RegionSize - 1)) + tx = ((int)Constants.RegionSize - 1); + ty = max_y * 4; + if (ty > ((int)Constants.RegionSize - 1)) + ty = ((int)Constants.RegionSize - 1); + LandData.AABBMax = + new Vector3((float) (max_x * 4), (float) (max_y * 4), + (float) m_scene.Heightmap[tx, ty]); + LandData.Area = tempArea; + } + + #endregion + + #region Land Bitmap Functions + + /// + /// Sets the land's bitmap manually + /// + /// 64x64 block representing where this land is on a map + public void SetLandBitmap(bool[,] bitmap) + { + if (bitmap.GetLength(0) != 64 || bitmap.GetLength(1) != 64 || bitmap.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + //throw new Exception("Error: Invalid Parcel Bitmap"); + } + else + { + //Valid: Lets set it + LandBitmap = bitmap; + ForceUpdateLandInfo(); + } + } + + /// + /// Gets the land's bitmap manually + /// + /// + public bool[,] GetLandBitmap() + { + return LandBitmap; + } + + /// + /// Full sim land object creation + /// + /// + public bool[,] BasicFullRegionLandBitmap() + { + return GetSquareLandBitmap(0, 0, (int) Constants.RegionSize, (int) Constants.RegionSize); + } + + /// + /// Used to modify the bitmap between the x and y points. Points use 64 scale + /// + /// + /// + /// + /// + /// + public bool[,] GetSquareLandBitmap(int start_x, int start_y, int end_x, int end_y) + { + bool[,] tempBitmap = new bool[64,64]; + tempBitmap.Initialize(); + + tempBitmap = ModifyLandBitmapSquare(tempBitmap, start_x, start_y, end_x, end_y, true); + return tempBitmap; + } + + /// + /// Change a land bitmap at within a square and set those points to a specific value + /// + /// + /// + /// + /// + /// + /// + /// + public bool[,] ModifyLandBitmapSquare(bool[,] land_bitmap, int start_x, int start_y, int end_x, int end_y, + bool set_value) + { + if (land_bitmap.GetLength(0) != 64 || land_bitmap.GetLength(1) != 64 || land_bitmap.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + //throw new Exception("Error: Invalid Parcel Bitmap in modifyLandBitmapSquare()"); + } + + int x, y; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + if (x >= start_x / 4 && x < end_x / 4 + && y >= start_y / 4 && y < end_y / 4) + { + land_bitmap[x, y] = set_value; + } + } + } + return land_bitmap; + } + + /// + /// Join the true values of 2 bitmaps together + /// + /// + /// + /// + public bool[,] MergeLandBitmaps(bool[,] bitmap_base, bool[,] bitmap_add) + { + if (bitmap_base.GetLength(0) != 64 || bitmap_base.GetLength(1) != 64 || bitmap_base.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_base in mergeLandBitmaps"); + } + if (bitmap_add.GetLength(0) != 64 || bitmap_add.GetLength(1) != 64 || bitmap_add.Rank != 2) + { + //Throw an exception - The bitmap is not 64x64 + throw new Exception("Error: Invalid Parcel Bitmap - Bitmap_add in mergeLandBitmaps"); + } + + int x, y; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + if (bitmap_add[x, y]) + { + bitmap_base[x, y] = true; + } + } + } + return bitmap_base; + } + + /// + /// Converts the land bitmap to a packet friendly byte array + /// + /// + private byte[] ConvertLandBitmapToBytes() + { + byte[] tempConvertArr = new byte[512]; + byte tempByte = 0; + int x, y, i, byteNum = 0; + i = 0; + for (y = 0; y < 64; y++) + { + for (x = 0; x < 64; x++) + { + tempByte = Convert.ToByte(tempByte | Convert.ToByte(LandBitmap[x, y]) << (i++ % 8)); + if (i % 8 == 0) + { + tempConvertArr[byteNum] = tempByte; + tempByte = (byte) 0; + i = 0; + byteNum++; + } + } + } + return tempConvertArr; + } + + private bool[,] ConvertBytesToLandBitmap() + { + bool[,] tempConvertMap = new bool[landArrayMax, landArrayMax]; + tempConvertMap.Initialize(); + byte tempByte = 0; + int x = 0, y = 0, i = 0, bitNum = 0; + for (i = 0; i < 512; i++) + { + tempByte = LandData.Bitmap[i]; + for (bitNum = 0; bitNum < 8; bitNum++) + { + bool bit = Convert.ToBoolean(Convert.ToByte(tempByte >> bitNum) & (byte) 1); + tempConvertMap[x, y] = bit; + x++; + if (x > 63) + { + x = 0; + y++; + } + } + } + return tempConvertMap; + } + + #endregion + + #region Object Select and Object Owner Listing + + public void SendForceObjectSelect(int local_id, int request_type, List returnIDs, IClientAPI remote_client) + { + if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) + { + List resultLocalIDs = new List(); + try + { + lock (primsOverMe) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.LocalId > 0) + { + if (request_type == LandChannel.LAND_SELECT_OBJECTS_OWNER && obj.OwnerID == LandData.OwnerID) + { + resultLocalIDs.Add(obj.LocalId); + } + else if (request_type == LandChannel.LAND_SELECT_OBJECTS_GROUP && obj.GroupID == LandData.GroupID && LandData.GroupID != UUID.Zero) + { + resultLocalIDs.Add(obj.LocalId); + } + else if (request_type == LandChannel.LAND_SELECT_OBJECTS_OTHER && + obj.OwnerID != remote_client.AgentId) + { + resultLocalIDs.Add(obj.LocalId); + } + else if (request_type == (int)ObjectReturnType.List && returnIDs.Contains(obj.OwnerID)) + { + resultLocalIDs.Add(obj.LocalId); + } + } + } + } + } catch (InvalidOperationException) + { + m_log.Error("[LAND]: Unable to force select the parcel objects. Arr."); + } + + remote_client.SendForceClientSelectObjects(resultLocalIDs); + } + } + + /// + /// Notify the parcel owner each avatar that owns prims situated on their land. This notification includes + /// aggreagete details such as the number of prims. + /// + /// + /// + /// A + /// + public void SendLandObjectOwners(IClientAPI remote_client) + { + if (m_scene.Permissions.CanEditParcel(remote_client.AgentId, this)) + { + Dictionary primCount = new Dictionary(); + List groups = new List(); + + lock (primsOverMe) + { + try + { + + foreach (SceneObjectGroup obj in primsOverMe) + { + try + { + if (!primCount.ContainsKey(obj.OwnerID)) + { + primCount.Add(obj.OwnerID, 0); + } + } + catch (NullReferenceException) + { + m_log.Info("[LAND]: " + "Got Null Reference when searching land owners from the parcel panel"); + } + try + { + primCount[obj.OwnerID] += obj.PrimCount; + } + catch (KeyNotFoundException) + { + m_log.Error("[LAND]: Unable to match a prim with it's owner."); + } + if (obj.OwnerID == obj.GroupID && (!groups.Contains(obj.OwnerID))) + groups.Add(obj.OwnerID); + } + } + catch (InvalidOperationException) + { + m_log.Error("[LAND]: Unable to Enumerate Land object arr."); + } + } + + remote_client.SendLandObjectOwners(LandData, groups, primCount); + } + } + + public Dictionary GetLandObjectOwners() + { + Dictionary ownersAndCount = new Dictionary(); + lock (primsOverMe) + { + try + { + + foreach (SceneObjectGroup obj in primsOverMe) + { + if (!ownersAndCount.ContainsKey(obj.OwnerID)) + { + ownersAndCount.Add(obj.OwnerID, 0); + } + ownersAndCount[obj.OwnerID] += obj.PrimCount; + } + } + catch (InvalidOperationException) + { + m_log.Error("[LAND]: Unable to enumerate land owners. arr."); + } + + } + return ownersAndCount; + } + + #endregion + + #region Object Returning + + public void ReturnObject(SceneObjectGroup obj) + { + SceneObjectGroup[] objs = new SceneObjectGroup[1]; + objs[0] = obj; + m_scene.returnObjects(objs, obj.OwnerID); + } + + public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) + { + Dictionary> returns = + new Dictionary>(); + + lock (primsOverMe) + { + if (type == (uint)ObjectReturnType.Owner) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.OwnerID == m_landData.OwnerID) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + else if (type == (uint)ObjectReturnType.Group && m_landData.GroupID != UUID.Zero) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.GroupID == m_landData.GroupID) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + else if (type == (uint)ObjectReturnType.Other) + { + foreach (SceneObjectGroup obj in primsOverMe) + { + if (obj.OwnerID != m_landData.OwnerID && + (obj.GroupID != m_landData.GroupID || + m_landData.GroupID == UUID.Zero)) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + else if (type == (uint)ObjectReturnType.List) + { + List ownerlist = new List(owners); + + foreach (SceneObjectGroup obj in primsOverMe) + { + if (ownerlist.Contains(obj.OwnerID)) + { + if (!returns.ContainsKey(obj.OwnerID)) + returns[obj.OwnerID] = + new List(); + returns[obj.OwnerID].Add(obj); + } + } + } + } + + foreach (List ol in returns.Values) + { + if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) + m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); + } + } + + #endregion + + #region Object Adding/Removing from Parcel + + public void ResetLandPrimCounts() + { + LandData.GroupPrims = 0; + LandData.OwnerPrims = 0; + LandData.OtherPrims = 0; + LandData.SelectedPrims = 0; + + + lock (primsOverMe) + primsOverMe.Clear(); + } + + public void AddPrimToCount(SceneObjectGroup obj) + { + + UUID prim_owner = obj.OwnerID; + int prim_count = obj.PrimCount; + + if (obj.IsSelected) + { + LandData.SelectedPrims += prim_count; + } + else + { + if (prim_owner == LandData.OwnerID) + { + LandData.OwnerPrims += prim_count; + } + else if ((obj.GroupID == LandData.GroupID || + prim_owner == LandData.GroupID) && + LandData.GroupID != UUID.Zero) + { + LandData.GroupPrims += prim_count; + } + else + { + LandData.OtherPrims += prim_count; + } + } + + lock (primsOverMe) + primsOverMe.Add(obj); + } + + public void RemovePrimFromCount(SceneObjectGroup obj) + { + lock (primsOverMe) + { + if (primsOverMe.Contains(obj)) + { + UUID prim_owner = obj.OwnerID; + int prim_count = obj.PrimCount; + + if (prim_owner == LandData.OwnerID) + { + LandData.OwnerPrims -= prim_count; + } + else if (obj.GroupID == LandData.GroupID || + prim_owner == LandData.GroupID) + { + LandData.GroupPrims -= prim_count; + } + else + { + LandData.OtherPrims -= prim_count; + } + + primsOverMe.Remove(obj); + } + } + } + + #endregion + + #endregion + + #endregion + + /// + /// Set the media url for this land parcel + /// + /// + public void SetMediaUrl(string url) + { + LandData.MediaURL = url; + SendLandUpdateToAvatarsOverMe(); + } + + /// + /// Set the music url for this land parcel + /// + /// + public void SetMusicUrl(string url) + { + LandData.MusicURL = url; + SendLandUpdateToAvatarsOverMe(); + } + } +} -- cgit v1.1 From 4cf5ef3cd4c6712f74615385a03217f5d4cecb80 Mon Sep 17 00:00:00 2001 From: meta7 Date: Mon, 30 Aug 2010 11:41:20 -0700 Subject: Kick the user from the region in the circumstance that the TP home failed - ONLY if it was triggered by an estate ban. This makes baby jesus cry, and should be fixed to search for alternative regions if the home region is unavailable. --- .../Framework/EntityTransfer/EntityTransferModule.cs | 16 +++++++++++----- .../EntityTransfer/HGEntityTransferModule.cs | 19 ++++++++++++------- .../World/Estate/EstateManagementModule.cs | 18 +++++++++++++++--- .../Framework/Interfaces/IEntityTransferModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 5 +++-- 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 0ba67d3..d6f37ae 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -99,7 +99,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected virtual void OnNewClient(IClientAPI client) { - client.OnTeleportHomeRequest += TeleportHome; + client.OnTeleportHomeRequest += TeleportHomeFired; } public virtual void Close() @@ -552,7 +552,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #region Teleport Home - public virtual void TeleportHome(UUID id, IClientAPI client) + public void TeleportHomeFired(UUID id, IClientAPI client) + { + TeleportHome(id, client); + } + + public virtual bool TeleportHome(UUID id, IClientAPI client) { m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); @@ -565,14 +570,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // can't find the Home region: Tell viewer and abort client.SendTeleportFailed("You don't have a home position set."); - return; + return false; } GridRegion regionInfo = m_aScene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID); if (regionInfo == null) { // can't find the Home region: Tell viewer and abort client.SendTeleportFailed("Your home region could not be found."); - return; + return false; } m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})", regionInfo.RegionName, regionInfo.RegionID, regionInfo.RegionLocX / Constants.RegionSize, regionInfo.RegionLocY / Constants.RegionSize); @@ -586,8 +591,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // can't find the Home region: Tell viewer and abort client.SendTeleportFailed("Your home region could not be found."); - return; + return false; } + return true; } #endregion diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 1ac7508..47898cc 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -86,7 +86,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected override void OnNewClient(IClientAPI client) { - client.OnTeleportHomeRequest += TeleportHome; + client.OnTeleportHomeRequest += TeleportHomeFired; client.OnConnectionClosed += new Action(OnConnectionClosed); } @@ -174,7 +174,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return m_aScene.SimulationService.CreateAgent(reg, agentCircuit, teleportFlags, out reason); } - public override void TeleportHome(UUID id, IClientAPI client) + public void TeleportHomeFired(UUID id, IClientAPI client) + { + TeleportHome(id, client); + } + + public override bool TeleportHome(UUID id, IClientAPI client) { m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Request to teleport {0} {1} home", client.FirstName, client.LastName); @@ -184,8 +189,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // local grid user m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: User is local"); - base.TeleportHome(id, client); - return; + return base.TeleportHome(id, client); } // Foreign user wants to go home @@ -195,7 +199,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { client.SendTeleportFailed("Your information has been lost"); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Unable to locate agent's gateway information"); - return; + return false; } IUserAgentService userAgentService = new UserAgentServiceConnector(aCircuit.ServiceURLs["HomeURI"].ToString()); @@ -205,7 +209,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { client.SendTeleportFailed("Your home region could not be found"); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent's home region not found"); - return; + return false; } ScenePresence sp = ((Scene)(client.Scene)).GetScenePresence(client.AgentId); @@ -213,7 +217,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { client.SendTeleportFailed("Internal error"); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Agent not found in the scene where it is supposed to be"); - return; + return false; } IEventQueue eq = sp.Scene.RequestModuleInterface(); @@ -223,6 +227,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer aCircuit.firstname, aCircuit.lastname, finalDestination.RegionName, homeGatekeeper.ExternalHostName, homeGatekeeper.HttpPort, homeGatekeeper.RegionName); DoTeleport(sp, homeGatekeeper, finalDestination, position, lookAt, (uint)(Constants.TeleportFlags.SetLastToTarget | Constants.TeleportFlags.ViaHome), eq); + return true; } #endregion diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 171e0b9..8411d04 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -345,7 +345,11 @@ namespace OpenSim.Region.CoreModules.World.Estate { if (!s.IsChildAgent) { - m_scene.TeleportClientHome(user, s.ControllingClient); + if (!m_scene.TeleportClientHome(user, s.ControllingClient)) + { + s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); + s.ControllingClient.Close(); + } } } @@ -479,7 +483,11 @@ namespace OpenSim.Region.CoreModules.World.Estate ScenePresence s = m_scene.GetScenePresence(prey); if (s != null) { - m_scene.TeleportClientHome(prey, s.ControllingClient); + if (!m_scene.TeleportClientHome(prey, s.ControllingClient)) + { + s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); + s.ControllingClient.Close(); + } } } } @@ -498,7 +506,11 @@ namespace OpenSim.Region.CoreModules.World.Estate // Also make sure they are actually in the region if (p != null && !p.IsChildAgent) { - m_scene.TeleportClientHome(p.UUID, p.ControllingClient); + if (!m_scene.TeleportClientHome(p.UUID, p.ControllingClient)) + { + p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); + p.ControllingClient.Close(); + } } } }); diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index e8738c4..45ca5c5 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); - void TeleportHome(UUID id, IClientAPI client); + bool TeleportHome(UUID id, IClientAPI client); void Cross(ScenePresence agent, bool isFlying); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 957c4e8..736b696 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2985,15 +2985,16 @@ namespace OpenSim.Region.Framework.Scenes /// /// The avatar's Unique ID /// The IClientAPI for the client - public virtual void TeleportClientHome(UUID agentId, IClientAPI client) + public virtual bool TeleportClientHome(UUID agentId, IClientAPI client) { if (m_teleportModule != null) - m_teleportModule.TeleportHome(agentId, client); + return m_teleportModule.TeleportHome(agentId, client); else { m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); client.SendTeleportFailed("Unable to perform teleports on this simulator."); } + return false; } /// -- cgit v1.1 From b973fe52976c909197c360d6afdd62952e3d37ae Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 31 Aug 2010 22:24:11 +0200 Subject: Adjust the "Magic numbers" we use because we can't reference the actual script state enum to reflect recent changes. --- .../CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 2 +- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 2a36362..4159610 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -689,7 +689,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } // Fire on_rez - group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 0); + group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); rootPart.ParentGroup.ResumeScripts(); rootPart.ScheduleFullUpdate(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 8760c84..ffbf7bf 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1993,7 +1993,7 @@ namespace OpenSim.Region.Framework.Scenes // We can only call this after adding the scene object, since the scene object references the scene // to find out if scripts should be activated at all. - group.CreateScriptInstances(param, true, DefaultScriptEngine, 2); + group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); group.ScheduleGroupForFullUpdate(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 6a742c1..767d370 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2442,7 +2442,7 @@ namespace OpenSim.Region.Framework.Scenes return false; } - newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, 1); + newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, 2); newObject.ResumeScripts(); diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index b86a564..8823df1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1928,7 +1928,7 @@ namespace OpenSim.Region.Framework.Scenes copy.UpdateGroupRotationR(rot); } - copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 0); + copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); copy.HasGroupChanged = true; copy.ScheduleGroupForFullUpdate(); copy.ResumeScripts(); -- cgit v1.1 From 2232e6f27300032188a7a1eeb77c56e84cd51d66 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 1 Sep 2010 14:08:52 +0200 Subject: Improve sim health reporting. Output error message if heartbeat thread is restarted by scene. This may help to find out why this recovery mechanism isn't working. --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index b950dbd..a9e6647 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1160,6 +1160,7 @@ namespace OpenSim.Region.Framework.Scenes //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); if (HeartbeatThread != null) { + m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName); HeartbeatThread.Abort(); HeartbeatThread = null; } @@ -4555,7 +4556,7 @@ namespace OpenSim.Region.Framework.Scenes // int health=1; // Start at 1, means we're up - if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) + if (m_firstHeartbeat || ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000)) health+=1; else return health; -- cgit v1.1 From 09fba1609493b5ad60ab95fb6db4b368a1833fc3 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 1 Sep 2010 20:10:44 +0200 Subject: Prevent Meta7 plants from being treated like dropped attachments and removed from the sim. --- OpenSim/Region/Framework/Scenes/Scene.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a9e6647..400f4c0 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5068,7 +5068,7 @@ namespace OpenSim.Region.Framework.Scenes { ForEachSOG(delegate (SceneObjectGroup grp) { - if (grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp))) + if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp))) { UUID agentID = grp.OwnerID; if (agentID == UUID.Zero) -- cgit v1.1 From db015963a9905b1af5d4d1d42a6384b5644a3617 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 2 Sep 2010 14:17:33 +0200 Subject: Remove the annoying "Script saved" popups when saving scripts in task inventory. They cause spam when using recompile scripts in selection and are redundant because that message is also shown in the script window message pane. These popups were a legacy from when we couldn't drive the message pane and their finest hour has now come. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index ffbf7bf..0d9682e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -218,8 +218,7 @@ namespace OpenSim.Region.Framework.Scenes // Update item with new asset item.AssetID = asset.FullID; - if (group.UpdateInventoryItem(item)) - remoteClient.SendAgentAlertMessage("Script saved", false); + group.UpdateInventoryItem(item); part.GetProperties(remoteClient); @@ -232,10 +231,6 @@ namespace OpenSim.Region.Framework.Scenes // errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0); } - else - { - remoteClient.SendAgentAlertMessage("Script saved", false); - } part.ParentGroup.ResumeScripts(); return errors; } @@ -1401,13 +1396,6 @@ namespace OpenSim.Region.Framework.Scenes { agentTransactions.HandleTaskItemUpdateFromTransaction( remoteClient, part, transactionID, currentItem); - - if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) - remoteClient.SendAgentAlertMessage("Notecard saved", false); - else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) - remoteClient.SendAgentAlertMessage("Script saved", false); - else - remoteClient.SendAgentAlertMessage("Item saved", false); } // Base ALWAYS has move -- cgit v1.1 From 0f40ec5c65f1698d2bb32cc28960b3651c1f7dac Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 2 Sep 2010 16:10:44 +0200 Subject: Implement UploadBakedTexture cap --- OpenSim/Framework/Capabilities/Caps.cs | 105 +++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs index 0db7bb9..8a339fe 100644 --- a/OpenSim/Framework/Capabilities/Caps.cs +++ b/OpenSim/Framework/Capabilities/Caps.cs @@ -44,6 +44,8 @@ namespace OpenSim.Framework.Capabilities string assetName, string description, UUID assetID, UUID inventoryItem, UUID parentFolder, byte[] data, string inventoryType, string assetType); + public delegate void UploadedBakedTexture(UUID assetID, byte[] data); + public delegate UUID UpdateItem(UUID itemID, byte[] data); public delegate void UpdateTaskScript(UUID itemID, UUID primID, bool isScriptRunning, byte[] data, ref ArrayList errors); @@ -97,6 +99,7 @@ namespace OpenSim.Framework.Capabilities // private static readonly string m_provisionVoiceAccountRequestPath = "0008/";// This is in a module. // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. + private static readonly string m_uploadBakedTexturePath = "0010/";// This is in the LandManagementModule. //private string eventQueue = "0100/"; private IScene m_Scene; @@ -185,6 +188,8 @@ namespace OpenSim.Framework.Capabilities m_capsHandlers["UpdateScriptTaskInventory"] = new RestStreamHandler("POST", capsBase + m_notecardTaskUpdatePath, ScriptTaskInventory); m_capsHandlers["UpdateScriptTask"] = m_capsHandlers["UpdateScriptTaskInventory"]; + m_capsHandlers["UploadBakedTexture"] = + new RestStreamHandler("POST", capsBase + m_uploadBakedTexturePath, UploadBakedTexture); } catch (Exception e) @@ -742,6 +747,50 @@ namespace OpenSim.Framework.Capabilities return null; } + public string UploadBakedTexture(string request, string path, + string param, OSHttpRequest httpRequest, + OSHttpResponse httpResponse) + { + try + { + m_log.Debug("[CAPS]: UploadBakedTexture Request in region: " + + m_regionName); + + string capsBase = "/CAPS/" + m_capsObjectPath; + string uploaderPath = Util.RandomClass.Next(5000, 8000).ToString("0000"); + + BakedTextureUploader uploader = + new BakedTextureUploader( capsBase + uploaderPath, + m_httpListener); + uploader.OnUpLoad += BakedTextureUploaded; + + m_httpListener.AddStreamHandler( + new BinaryStreamHandler("POST", capsBase + uploaderPath, + uploader.uploaderCaps)); + + string protocol = "http://"; + + if (m_httpListener.UseSSL) + protocol = "https://"; + + string uploaderURL = protocol + m_httpListenerHostName + ":" + + m_httpListenPort.ToString() + capsBase + uploaderPath; + + LLSDAssetUploadResponse uploadResponse = + new LLSDAssetUploadResponse(); + uploadResponse.uploader = uploaderURL; + uploadResponse.state = "upload"; + + return LLSDHelpers.SerialiseLLSDReply(uploadResponse); + } + catch (Exception e) + { + m_log.Error("[CAPS]: " + e.ToString()); + } + + return null; + } + /// /// Called by the notecard update handler. Provides a URL to which the client can upload a new asset. /// @@ -925,6 +974,17 @@ namespace OpenSim.Framework.Capabilities } } + public void BakedTextureUploaded(UUID assetID, byte[] data) + { + m_log.DebugFormat("[CAPS]: Received baked texture {0}", assetID.ToString()); + AssetBase asset; + asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_agentID.ToString()); + asset.Data = data; + asset.Temporary = true; + asset.Local = true; + m_assetCache.Store(asset); + } + /// /// Called when new asset data for an agent inventory item update has been uploaded. /// @@ -1243,5 +1303,50 @@ namespace OpenSim.Framework.Capabilities fs.Close(); } } + + public class BakedTextureUploader + { + public event UploadedBakedTexture OnUpLoad; + private UploadedBakedTexture handlerUpLoad = null; + + private string uploaderPath = String.Empty; + private UUID newAssetID; + private IHttpServer httpListener; + + public BakedTextureUploader(string path, IHttpServer httpServer) + { + newAssetID = UUID.Random(); + uploaderPath = path; + httpListener = httpServer; + } + + /// + /// + /// + /// + /// + /// + /// + public string uploaderCaps(byte[] data, string path, string param) + { + string res = String.Empty; + LLSDAssetUploadComplete uploadComplete = new LLSDAssetUploadComplete(); + uploadComplete.new_asset = newAssetID.ToString(); + uploadComplete.new_inventory_item = UUID.Zero; + uploadComplete.state = "complete"; + + res = LLSDHelpers.SerialiseLLSDReply(uploadComplete); + + httpListener.RemoveStreamHandler("POST", uploaderPath); + + handlerUpLoad = OnUpLoad; + if (handlerUpLoad != null) + { + handlerUpLoad(newAssetID, data); + } + + return res; + } + } } } -- cgit v1.1 From 713c6668273ebd853db7f3f69185c9b4f119f702 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 2 Sep 2010 19:49:42 +0200 Subject: Show when appearance is sent to an avatar to help track down failure \to display avatars --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 105501f..aa7de05 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3427,6 +3427,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP avp.Sender.IsTrial = false; avp.Sender.ID = agentID; + m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); OutPacket(avp, ThrottleOutPacketType.Task); } -- cgit v1.1 From eea5d8368acb9a7934e55b6e4b6ccddb40bc5611 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 2 Sep 2010 20:08:39 +0200 Subject: Experimentally comment the sending of unbaked avatars --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index cd80eb0..2acf8ff 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2806,7 +2806,9 @@ namespace OpenSim.Region.Framework.Scenes m_controllingClient.SendAvatarDataImmediate(this); SendInitialFullUpdateToAllClients(); - SendAppearanceToAllOtherAgents(); + // Experimentally commenting this. We don't have bakes at this time + // and 1.23 will not display an avatar without bakes. + //SendAppearanceToAllOtherAgents(); } /// -- cgit v1.1 From 5ea979d51517b11895a4c5431e3c3c02767a23ac Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Thu, 2 Sep 2010 20:51:27 +0200 Subject: Remove commented code and the comment, as the change has proven out --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 2acf8ff..604ffad 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2806,9 +2806,6 @@ namespace OpenSim.Region.Framework.Scenes m_controllingClient.SendAvatarDataImmediate(this); SendInitialFullUpdateToAllClients(); - // Experimentally commenting this. We don't have bakes at this time - // and 1.23 will not display an avatar without bakes. - //SendAppearanceToAllOtherAgents(); } /// -- cgit v1.1 From 16814dd8f18b51f5dd8841ae341847e117bb83b3 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Thu, 2 Sep 2010 21:51:19 +0000 Subject: Fixes to JUMP system. --- .../Scenes/Animation/ScenePresenceAnimator.cs | 151 ++++++++++++++++----- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 66 ++++++--- OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs | 7 +- 3 files changed, 168 insertions(+), 56 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index b847d87..99d9564 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -58,7 +58,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation private int m_animTickFall; // private int m_animTickJump; public int m_animTickJump; // ScenePresence has to see this to control +Z force - + public bool m_jumping = false; // Add for jumping + public float m_jumpVelocity = 0f; // Add for jumping + private int m_landing = 0; // Add for jumping + /// /// The scene presence that this animator applies to /// @@ -141,9 +144,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation /// public string GetMovementAnimation() { +//Console.WriteLine("GMA-------"); //## const float FALL_DELAY = 0.33f; - const float PREJUMP_DELAY = 0.25f; - +//rm for jumping const float PREJUMP_DELAY = 0.25f; + const float PREJUMP_DELAY = 200f; // mS add for jumping + const float JUMP_PERIOD = 800f; // mS add for jumping #region Inputs AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; @@ -177,8 +182,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation // Is the avatar trying to move? // bool moving = (move != Vector3.Zero); - bool jumping = m_animTickJump != 0; - +// rm for jumping bool jumping = m_animTickJump != 0; #endregion Inputs #region Flying @@ -187,6 +191,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation { m_animTickFall = 0; m_animTickJump = 0; + m_jumping = false; //add for jumping flag + m_jumpVelocity = 0f; //add for jumping flag + actor.Selected = false; //add for jumping flag if (move.X != 0f || move.Y != 0f) { @@ -213,8 +220,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation #region Falling/Floating/Landing - if (actor == null || !actor.IsColliding) +// rm for jumping if (actor == null || !actor.IsColliding) + if ((actor == null || !actor.IsColliding) && !m_jumping) // add for jumping { +//Console.WriteLine("FFL"); //## float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; @@ -223,7 +232,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation // Just started falling m_animTickFall = Environment.TickCount; } - else if (!jumping && fallElapsed > FALL_DELAY) +// else if (!jumping && fallElapsed > FALL_DELAY) + else if (!m_jumping && fallElapsed > FALL_DELAY) // add for jumping { // Falling long enough to trigger the animation return "FALLDOWN"; @@ -234,6 +244,67 @@ namespace OpenSim.Region.Framework.Scenes.Animation #endregion Falling/Floating/Landing + + #region Jumping // section added for jumping... + + Vector3 vj = Vector3.Zero; + int jumptime; + jumptime = Environment.TickCount - m_animTickJump; + + + if ((move.Z > 0f) && (!m_jumping)) + { +//Console.WriteLine("PJ {0}", jumptime); //## + // Start jumping, prejump + m_animTickFall = 0; + m_jumping = true; + actor.Selected = true; // borrowed for jmping flag + m_animTickJump = Environment.TickCount; + vj.Z = 0.35f; +m_jumpVelocity = 0.35f; + vj += actor.Velocity; +// #@ actor.Velocity = vj; + return "PREJUMP"; + } + + if(m_jumping) + { + if ( (jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) + { +//Console.WriteLine("LA {0}", jumptime); //## + // end jumping + m_jumping = false; + actor.Selected = false; // borrowed for jumping flag +m_jumpVelocity = 0f; + m_animTickFall = Environment.TickCount; + return "LAND"; + } + else if (jumptime > JUMP_PERIOD) + { +//Console.WriteLine("JD {0}", jumptime); //## + // jump down + vj = actor.Velocity; + vj.Z = 0f; +m_jumpVelocity = 0f; +// #@ actor.Velocity = vj; + return "JUMP"; + } + else if (jumptime > PREJUMP_DELAY) + { +//Console.WriteLine("JU {0}", jumptime); //## + // jump up + m_jumping = true; + vj.Z = 10f; +m_jumpVelocity = 10f; + vj.X = actor.Velocity.X; + vj.Y = actor.Velocity.Y; +// #@ actor.Velocity = vj; + return "JUMP"; + } + } + + #endregion Jumping // end added section + #region Ground Movement if (m_movementAnimation == "FALLDOWN") @@ -245,11 +316,26 @@ namespace OpenSim.Region.Framework.Scenes.Animation } else if (m_movementAnimation == "LAND") { - float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; - if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) +// rm jumping float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; + int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping +// rm jumping if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) +/* Try change ## + if ((m_animTickFall != 0) && (landElapsed <= 500)) // add for jumping + return "LAND"; + */ + // NB if this is set too long a weird anim reset from some place prevents STAND from being sent to client + if ((m_animTickFall != 0) && (landElapsed <= 300)) // add for jumping + { +//Console.WriteLine("LAND"); //## return "LAND"; + } + else + { +//Console.WriteLine("STAND"); //## + return "STAND"; + } } - +/* This section removed, replaced by jumping section m_animTickFall = 0; if (move.Z > 0f) @@ -279,27 +365,28 @@ namespace OpenSim.Region.Framework.Scenes.Animation { // Not jumping m_animTickJump = 0; - - if (move.X != 0f || move.Y != 0f) - { - // Walking / crouchwalking / running - if (move.Z < 0f) - return "CROUCHWALK"; - else if (m_scenePresence.SetAlwaysRun) - return "RUN"; - else - return "WALK"; - } + */ + // next section moved outside paren. and realigned for jumping + if (move.X != 0f || move.Y != 0f) + { + // Walking / crouchwalking / running + if (move.Z < 0f) + return "CROUCHWALK"; + else if (m_scenePresence.SetAlwaysRun) + return "RUN"; else - { - // Not walking - if (move.Z < 0f) - return "CROUCH"; - else - return "STAND"; - } + return "WALK"; } - +// rm for jumping else + else if (!m_jumping) // add for jumping + { + // Not walking + if (move.Z < 0f) + return "CROUCH"; + else + return "STAND"; + } + // end section realign for jumping #endregion Ground Movement return m_movementAnimation; @@ -311,15 +398,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation public void UpdateMovementAnimations() { m_movementAnimation = GetMovementAnimation(); - if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) +/* if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump) { // This was the previous behavior before PREJUMP TrySetMovementAnimation("JUMP"); } else - { + { removed for jumping */ TrySetMovementAnimation(m_movementAnimation); - } +// rm for jumping } } public UUID[] GetAnimationArray() diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index cd80eb0..f682ee5 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1471,6 +1471,9 @@ namespace OpenSim.Region.Framework.Scenes if (actor.Flying != oldflying) update_movementflag = true; + if (m_animator.m_jumping) // add for jumping + update_movementflag = true; + if (q != m_bodyRot) { m_bodyRot = q; @@ -2580,6 +2583,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.Info("[AGENT]: Stop FLying"); //} } + /* This jumping section removed to SPA else if (!actor.Flying && actor.IsColliding) { if (direc.Z > 2.0f) @@ -2592,12 +2596,12 @@ namespace OpenSim.Region.Framework.Scenes { direc.Z *= 0.1f; // prejump } - /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs + / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs Animator.TrySetMovementAnimation("PREJUMP"); Animator.TrySetMovementAnimation("JUMP"); - */ + * / } - } + } */ } // TODO: Add the force instead of only setting it to support multiple forces per frame? @@ -3543,28 +3547,46 @@ namespace OpenSim.Region.Framework.Scenes /// public override void UpdateMovement() { - if (m_forceToApply.HasValue) - { + if (Animator!=null) // add for jumping + { // add for jumping + // if (!m_animator.m_jumping) // add for jumping + // { // add for jumping - Vector3 force = m_forceToApply.Value; - m_updateflag = true; - Velocity = force; + if (m_forceToApply.HasValue) // this section realigned + { - m_forceToApply = null; - } - else - { - if (m_isNudging) - { - Vector3 force = Vector3.Zero; + Vector3 force = m_forceToApply.Value; + m_updateflag = true; +if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping + Velocity = force; +//Console.WriteLine("UM1 {0}", Velocity); + m_forceToApply = null; + } + else + { + if (m_isNudging) + { + Vector3 force = Vector3.Zero; + + m_updateflag = true; +if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping + Velocity = force; +//Console.WriteLine("UM2 {0}", Velocity); + m_isNudging = false; + m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND" + } + else // add for jumping + { // add for jumping + Vector3 force = Vector3.Zero; // add for jumping +if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping +//Console.WriteLine("UM3 {0}", Velocity); + Velocity = force; // add for jumping + } - m_updateflag = true; - Velocity = force; - m_isNudging = false; - m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND" - } - } - } + } + // } // end realign + } // add for jumping + } // add for jumping /// /// Adds a physical representation of the avatar to the Physics plugin diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index 61c16b8..0c79aa6 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -90,6 +90,7 @@ namespace OpenSim.Region.Physics.OdePlugin public float walkDivisor = 1.3f; public float runDivisor = 0.8f; private bool flying = false; + private bool jumping = false; // add for jumping private bool m_iscolliding = false; private bool m_iscollidingGround = false; private bool m_wascolliding = false; @@ -229,7 +230,8 @@ namespace OpenSim.Region.Physics.OdePlugin public override bool Selected { - set { return; } +// set { return; } + set { jumping = value; } // add for jumping flag } public override float Buoyancy @@ -1018,7 +1020,8 @@ namespace OpenSim.Region.Physics.OdePlugin { // close, jump to lateral destination d.BodySetPosition(Body, _zeroPosition.X, _zeroPosition.Y, pos.Z); } - if (flying) +// if (flying) + if (flying || jumping) // add for jumping { vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; } -- cgit v1.1 From 457160afc3cc0878b068486a7cbb8a41a5f18520 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Fri, 3 Sep 2010 03:16:08 +0200 Subject: Fix an issue with rezzing scripted objects. --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index c5994b2..1959427 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -278,7 +278,7 @@ namespace OpenSim.Region.Framework.Scenes if (!m_part.ParentGroup.Scene.RegionInfo.RegionSettings.DisableScripts) { - if (stateSource == 1 && // Prim crossing + if (stateSource == 2 && // Prim crossing m_part.ParentGroup.Scene.m_trustBinaries) { m_items.LockItemsForWrite(true); @@ -1263,4 +1263,4 @@ namespace OpenSim.Region.Framework.Scenes Items.LockItemsForRead(false); } } -} \ No newline at end of file +} -- cgit v1.1 From e5936071711e35f9edf44d8393b8ad28ef4023db Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Sun, 5 Sep 2010 14:16:42 +0200 Subject: Remove "Dwell" support from core and replace it with calls to methods on IDwellModule --- OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs | 6 +- OpenSim/Data/MySQL/MySQLLegacyRegionData.cs | 6 +- OpenSim/Data/SQLite/SQLiteRegionData.cs | 3 - OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs | 3 - OpenSim/Framework/LandData.cs | 14 --- .../Serialization/External/LandDataSerializer.cs | 5 +- .../HttpServer/SynchronousRestFormsRequester.cs | 109 ++++++++++----------- .../Region/ClientStack/LindenUDP/LLClientView.cs | 6 +- .../CoreModules/World/Land/LandManagementModule.cs | 13 --- OpenSim/Region/DataSnapshot/LandSnapshot.cs | 7 +- 10 files changed, 69 insertions(+), 103 deletions(-) diff --git a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs index 7ff8737..77b8a10 100644 --- a/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLLegacyRegionData.cs @@ -638,9 +638,9 @@ ELSE //Insert new values string sql = @"INSERT INTO [land] -([UUID],[RegionUUID],[LocalLandID],[Bitmap],[Name],[Description],[OwnerUUID],[IsGroupOwned],[Area],[AuctionID],[Category],[ClaimDate],[ClaimPrice],[GroupUUID],[SalePrice],[LandStatus],[LandFlags],[LandingType],[MediaAutoScale],[MediaTextureUUID],[MediaURL],[MusicURL],[PassHours],[PassPrice],[SnapshotUUID],[UserLocationX],[UserLocationY],[UserLocationZ],[UserLookAtX],[UserLookAtY],[UserLookAtZ],[AuthbuyerID],[OtherCleanTime],[Dwell]) +([UUID],[RegionUUID],[LocalLandID],[Bitmap],[Name],[Description],[OwnerUUID],[IsGroupOwned],[Area],[AuctionID],[Category],[ClaimDate],[ClaimPrice],[GroupUUID],[SalePrice],[LandStatus],[LandFlags],[LandingType],[MediaAutoScale],[MediaTextureUUID],[MediaURL],[MusicURL],[PassHours],[PassPrice],[SnapshotUUID],[UserLocationX],[UserLocationY],[UserLocationZ],[UserLookAtX],[UserLookAtY],[UserLookAtZ],[AuthbuyerID],[OtherCleanTime]) VALUES -(@UUID,@RegionUUID,@LocalLandID,@Bitmap,@Name,@Description,@OwnerUUID,@IsGroupOwned,@Area,@AuctionID,@Category,@ClaimDate,@ClaimPrice,@GroupUUID,@SalePrice,@LandStatus,@LandFlags,@LandingType,@MediaAutoScale,@MediaTextureUUID,@MediaURL,@MusicURL,@PassHours,@PassPrice,@SnapshotUUID,@UserLocationX,@UserLocationY,@UserLocationZ,@UserLookAtX,@UserLookAtY,@UserLookAtZ,@AuthbuyerID,@OtherCleanTime,@Dwell)"; +(@UUID,@RegionUUID,@LocalLandID,@Bitmap,@Name,@Description,@OwnerUUID,@IsGroupOwned,@Area,@AuctionID,@Category,@ClaimDate,@ClaimPrice,@GroupUUID,@SalePrice,@LandStatus,@LandFlags,@LandingType,@MediaAutoScale,@MediaTextureUUID,@MediaURL,@MusicURL,@PassHours,@PassPrice,@SnapshotUUID,@UserLocationX,@UserLocationY,@UserLocationZ,@UserLookAtX,@UserLookAtY,@UserLookAtZ,@AuthbuyerID,@OtherCleanTime)"; using (SqlConnection conn = new SqlConnection(m_connectionString)) using (SqlCommand cmd = new SqlCommand(sql, conn)) @@ -954,7 +954,6 @@ VALUES newData.SnapshotID = new UUID((Guid)row["SnapshotUUID"]); newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); - newData.Dwell = Convert.ToInt32(row["Dwell"]); try { @@ -1357,7 +1356,6 @@ VALUES parameters.Add(_Database.CreateParameter("UserLookAtZ", land.UserLookAt.Z)); parameters.Add(_Database.CreateParameter("AuthBuyerID", land.AuthBuyerID)); parameters.Add(_Database.CreateParameter("OtherCleanTime", land.OtherCleanTime)); - parameters.Add(_Database.CreateParameter("Dwell", land.Dwell)); return parameters.ToArray(); } diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs index 04446ce..30253c3 100644 --- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs @@ -677,7 +677,7 @@ namespace OpenSim.Data.MySQL "MusicURL, PassHours, PassPrice, SnapshotUUID, " + "UserLocationX, UserLocationY, UserLocationZ, " + "UserLookAtX, UserLookAtY, UserLookAtZ, " + - "AuthbuyerID, OtherCleanTime, Dwell, MediaType, MediaDescription, " + + "AuthbuyerID, OtherCleanTime, MediaType, MediaDescription, " + "MediaSize, MediaLoop, ObscureMusic, ObscureMedia) values (" + "?UUID, ?RegionUUID, " + "?LocalLandID, ?Bitmap, ?Name, ?Description, " + @@ -688,7 +688,7 @@ namespace OpenSim.Data.MySQL "?MusicURL, ?PassHours, ?PassPrice, ?SnapshotUUID, " + "?UserLocationX, ?UserLocationY, ?UserLocationZ, " + "?UserLookAtX, ?UserLookAtY, ?UserLookAtZ, " + - "?AuthbuyerID, ?OtherCleanTime, ?Dwell, ?MediaType, ?MediaDescription, "+ + "?AuthbuyerID, ?OtherCleanTime, ?MediaType, ?MediaDescription, "+ "CONCAT(?MediaWidth, ',', ?MediaHeight), ?MediaLoop, ?ObscureMusic, ?ObscureMedia)"; FillLandCommand(cmd, parcel.LandData, parcel.RegionUUID); @@ -1329,7 +1329,6 @@ namespace OpenSim.Data.MySQL UUID.TryParse((string)row["AuthBuyerID"], out authedbuyer); UUID.TryParse((string)row["SnapshotUUID"], out snapshotID); newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); - newData.Dwell = Convert.ToInt32(row["Dwell"]); newData.AuthBuyerID = authedbuyer; newData.SnapshotID = snapshotID; @@ -1660,7 +1659,6 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("UserLookAtZ", land.UserLookAt.Z); cmd.Parameters.AddWithValue("AuthBuyerID", land.AuthBuyerID); cmd.Parameters.AddWithValue("OtherCleanTime", land.OtherCleanTime); - cmd.Parameters.AddWithValue("Dwell", land.Dwell); cmd.Parameters.AddWithValue("MediaDescription", land.MediaDescription); cmd.Parameters.AddWithValue("MediaType", land.MediaType); cmd.Parameters.AddWithValue("MediaWidth", land.MediaWidth); diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs index 8432e74..88699a7 100644 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLite/SQLiteRegionData.cs @@ -1111,7 +1111,6 @@ namespace OpenSim.Data.SQLite createCol(land, "UserLookAtZ", typeof (Double)); createCol(land, "AuthbuyerID", typeof(String)); createCol(land, "OtherCleanTime", typeof(Int32)); - createCol(land, "Dwell", typeof(Int32)); land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; @@ -1449,7 +1448,6 @@ namespace OpenSim.Data.SQLite UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID); newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); - newData.Dwell = Convert.ToInt32(row["Dwell"]); return newData; } @@ -1761,7 +1759,6 @@ namespace OpenSim.Data.SQLite row["UserLookAtZ"] = land.UserLookAt.Z; row["AuthbuyerID"] = land.AuthBuyerID.ToString(); row["OtherCleanTime"] = land.OtherCleanTime; - row["Dwell"] = land.Dwell; row["MediaType"] = land.MediaType; row["MediaDescription"] = land.MediaDescription; row["MediaSize"] = land.MediaWidth.ToString() + "," + land.MediaHeight.ToString(); diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs index 289fd94..b5ce4c0 100644 --- a/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLiteLegacy/SQLiteRegionData.cs @@ -1069,7 +1069,6 @@ namespace OpenSim.Data.SQLiteLegacy createCol(land, "UserLookAtZ", typeof (Double)); createCol(land, "AuthbuyerID", typeof(String)); createCol(land, "OtherCleanTime", typeof(Int32)); - createCol(land, "Dwell", typeof(Int32)); land.PrimaryKey = new DataColumn[] {land.Columns["UUID"]}; @@ -1400,7 +1399,6 @@ namespace OpenSim.Data.SQLiteLegacy UUID.TryParse((string)row["AuthbuyerID"], out authBuyerID); newData.OtherCleanTime = Convert.ToInt32(row["OtherCleanTime"]); - newData.Dwell = Convert.ToInt32(row["Dwell"]); return newData; } @@ -1711,7 +1709,6 @@ namespace OpenSim.Data.SQLiteLegacy row["UserLookAtZ"] = land.UserLookAt.Z; row["AuthbuyerID"] = land.AuthBuyerID.ToString(); row["OtherCleanTime"] = land.OtherCleanTime; - row["Dwell"] = land.Dwell; } /// diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs index 4440c94..5bb0413 100644 --- a/OpenSim/Framework/LandData.cs +++ b/OpenSim/Framework/LandData.cs @@ -88,7 +88,6 @@ namespace OpenSim.Framework private UUID _snapshotID = UUID.Zero; private Vector3 _userLocation = new Vector3(); private Vector3 _userLookAt = new Vector3(); - private int _dwell = 0; private int _otherCleanTime = 0; private string _mediaType = "none/none"; private string _mediaDescription = ""; @@ -620,18 +619,6 @@ namespace OpenSim.Framework } /// - /// Deprecated idea. Number of visitors ~= free money - /// - public int Dwell { - get { - return _dwell; - } - set { - _dwell = value; - } - } - - /// /// Number of minutes to return SceneObjectGroup that are owned by someone who doesn't own /// the parcel and isn't set to the same 'group' as the parcel. /// @@ -703,7 +690,6 @@ namespace OpenSim.Framework landData._userLocation = _userLocation; landData._userLookAt = _userLookAt; landData._otherCleanTime = _otherCleanTime; - landData._dwell = _dwell; landData._mediaType = _mediaType; landData._mediaDescription = _mediaDescription; landData._mediaWidth = _mediaWidth; diff --git a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs index ff0afc8..fc0387b 100644 --- a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs +++ b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs @@ -118,7 +118,8 @@ namespace OpenSim.Framework.Serialization.External landData.SnapshotID = UUID.Parse( xtr.ReadElementString("SnapshotID")); landData.UserLocation = Vector3.Parse( xtr.ReadElementString("UserLocation")); landData.UserLookAt = Vector3.Parse( xtr.ReadElementString("UserLookAt")); - landData.Dwell = Convert.ToInt32( xtr.ReadElementString("Dwell")); + // No longer used here + xtr.ReadElementString("Dwell"); landData.OtherCleanTime = Convert.ToInt32( xtr.ReadElementString("OtherCleanTime")); xtr.ReadEndElement(); @@ -177,7 +178,7 @@ namespace OpenSim.Framework.Serialization.External xtw.WriteElementString("SnapshotID", landData.SnapshotID.ToString()); xtw.WriteElementString("UserLocation", landData.UserLocation.ToString()); xtw.WriteElementString("UserLookAt", landData.UserLookAt.ToString()); - xtw.WriteElementString("Dwell", Convert.ToString(landData.Dwell)); + xtw.WriteElementString("Dwell", "0"); xtw.WriteElementString("OtherCleanTime", Convert.ToString(landData.OtherCleanTime)); xtw.WriteEndElement(); diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs index f955df7..41ece86 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs @@ -57,80 +57,73 @@ namespace OpenSim.Framework.Servers.HttpServer { WebRequest request = WebRequest.Create(requestUrl); request.Method = verb; + string respstring = String.Empty; - if ((verb == "POST") || (verb == "PUT")) + using (MemoryStream buffer = new MemoryStream()) { - request.ContentType = "text/www-form-urlencoded"; - - MemoryStream buffer = new MemoryStream(); - int length = 0; - using (StreamWriter writer = new StreamWriter(buffer)) + if ((verb == "POST") || (verb == "PUT")) { - writer.Write(obj); - writer.Flush(); - } + request.ContentType = "text/www-form-urlencoded"; - length = (int)obj.Length; - request.ContentLength = length; + int length = 0; + using (StreamWriter writer = new StreamWriter(buffer)) + { + writer.Write(obj); + writer.Flush(); + } - Stream requestStream = null; - try - { - requestStream = request.GetRequestStream(); - requestStream.Write(buffer.ToArray(), 0, length); - } - catch (Exception e) - { - m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: " + e.ToString(), requestUrl); - } - finally - { - // If this is closed, it will be disposed internally, - // but the above write is asynchronous and may hit after - // we're through here. So the thread handling that will - // throw and put us back into the catch above. Isn't - // .NET great? - //if (requestStream != null) - // requestStream.Close(); - // Let's not close this - //buffer.Close(); + length = (int)obj.Length; + request.ContentLength = length; + Stream requestStream = null; + try + { + requestStream = request.GetRequestStream(); + requestStream.Write(buffer.ToArray(), 0, length); + } + catch (Exception e) + { + m_log.DebugFormat("[FORMS]: exception occured on sending request to {0}: " + e.ToString(), requestUrl); + } + finally + { + if (requestStream != null) + requestStream.Close(); + } } - } - - string respstring = String.Empty; - try - { - using (WebResponse resp = request.GetResponse()) + try { - if (resp.ContentLength != 0) + using (WebResponse resp = request.GetResponse()) { - Stream respStream = null; - try + if (resp.ContentLength != 0) { - respStream = resp.GetResponseStream(); - using (StreamReader reader = new StreamReader(respStream)) + Stream respStream = null; + try { - respstring = reader.ReadToEnd(); + respStream = resp.GetResponseStream(); + using (StreamReader reader = new StreamReader(respStream)) + { + respstring = reader.ReadToEnd(); + } + } + catch (Exception e) + { + m_log.DebugFormat("[FORMS]: exception occured on receiving reply " + e.ToString()); + } + finally + { + if (respStream != null) + respStream.Close(); } - } - catch (Exception e) - { - m_log.DebugFormat("[FORMS]: exception occured on receiving reply " + e.ToString()); - } - finally - { - if (respStream != null) - respStream.Close(); } } } - } - catch (System.InvalidOperationException) - { - // This is what happens when there is invalid XML - m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving request"); + catch (System.InvalidOperationException) + { + // This is what happens when there is invalid XML + m_log.DebugFormat("[FORMS]: InvalidOperationException on receiving request"); + } } return respstring; } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index a1cd30a..3dea40c 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -2687,6 +2687,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y) { + float dwell = 0.0f; + IDwellModule dwellModule = m_scene.RequestModuleInterface(); + if (dwellModule != null) + dwell = dwellModule.GetDwell(land.GlobalID); ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply); reply.AgentData.AgentID = m_agentId; reply.Data.ParcelID = parcelID; @@ -2711,7 +2715,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP reply.Data.GlobalZ = pos.Z; reply.Data.SimName = Utils.StringToBytes(info.RegionName); reply.Data.SnapshotID = land.SnapshotID; - reply.Data.Dwell = land.Dwell; + reply.Data.Dwell = dwell; reply.Data.SalePrice = land.SalePrice; reply.Data.AuctionID = (int)land.AuctionID; diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 776fe30..040dc8c 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -171,7 +171,6 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelGodForceOwner += ClientOnParcelGodForceOwner; client.OnParcelReclaim += ClientOnParcelReclaim; client.OnParcelInfoRequest += ClientOnParcelInfoRequest; -// client.OnParcelDwellRequest += ClientOnParcelDwellRequest; client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; client.OnPreAgentUpdate += ClientOnPreAgentUpdate; @@ -1512,18 +1511,6 @@ namespace OpenSim.Region.CoreModules.World.Land #endregion - private void ClientOnParcelDwellRequest(int localID, IClientAPI remoteClient) - { - ILandObject selectedParcel = null; - lock (m_landList) - { - if (!m_landList.TryGetValue(localID, out selectedParcel)) - return; - } - - remoteClient.SendParcelDwellReply(localID, selectedParcel.LandData.GlobalID, selectedParcel.LandData.Dwell); - } - private void ClientOnParcelInfoRequest(IClientAPI remoteClient, UUID parcelID) { if (parcelID == UUID.Zero) diff --git a/OpenSim/Region/DataSnapshot/LandSnapshot.cs b/OpenSim/Region/DataSnapshot/LandSnapshot.cs index 64d29f2..b8c90cd 100644 --- a/OpenSim/Region/DataSnapshot/LandSnapshot.cs +++ b/OpenSim/Region/DataSnapshot/LandSnapshot.cs @@ -123,6 +123,8 @@ namespace OpenSim.Region.DataSnapshot.Providers ILandChannel landChannel = m_scene.LandChannel; List parcels = landChannel.AllParcels(); + IDwellModule dwellModule = m_scene.RequestModuleInterface(); + XmlNode parent = nodeFactory.CreateNode(XmlNodeType.Element, "parceldata", ""); if (parcels != null) { @@ -208,7 +210,10 @@ namespace OpenSim.Region.DataSnapshot.Providers xmlparcel.AppendChild(infouuid); XmlNode dwell = nodeFactory.CreateNode(XmlNodeType.Element, "dwell", ""); - dwell.InnerText = parcel.Dwell.ToString(); + if (dwellModule != null) + dwell.InnerText = dwellModule.GetDwell(parcel.GlobalID).ToString(); + else + dwell.InnerText = "0"; xmlparcel.AppendChild(dwell); //TODO: figure how to figure out teleport system landData.landingType -- cgit v1.1 From 00a23eea0ec5d3607cf9cd021a3a182da258686e Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 6 Sep 2010 03:59:48 +0200 Subject: Reflect the ParcelPropertiesUpdateRequest into Scene.EventManager, because modules need to see it (Search!) even if it comes in via CAPS --- .../CoreModules/World/Land/LandManagementModule.cs | 14 +++++++++--- OpenSim/Region/Framework/Scenes/EventManager.cs | 26 +++++++++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 040dc8c..f62ec1b 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -1115,7 +1115,11 @@ namespace OpenSim.Region.CoreModules.World.Land m_landList.TryGetValue(localID, out land); } - if (land != null) land.UpdateLandProperties(args, remote_client); + if (land != null) + { + land.UpdateLandProperties(args, remote_client); + m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(args, localID, remote_client); + } } public void ClientOnParcelDivideRequest(int west, int south, int east, int north, IClientAPI remote_client) @@ -1433,9 +1437,13 @@ namespace OpenSim.Region.CoreModules.World.Land m_landList.TryGetValue(parcelID, out land); } - if (land != null) { + if (land != null) + { land.UpdateLandProperties(land_update, client); - } else { + m_scene.EventManager.TriggerOnParcelPropertiesUpdateRequest(land_update, parcelID, client); + } + else + { m_log.WarnFormat("[LAND] unable to find parcelID {0}", parcelID); } return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 52e6e92..d4e2736 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -113,6 +113,8 @@ namespace OpenSim.Region.Framework.Scenes public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; + public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; + /// /// Fired when an object is touched/grabbed. /// @@ -2128,5 +2130,27 @@ namespace OpenSim.Region.Framework.Scenes } } } + + public void TriggerOnParcelPropertiesUpdateRequest(LandUpdateArgs args, + int local_id, IClientAPI remote_client) + { + ParcelPropertiesUpdateRequest handler = OnParcelPropertiesUpdateRequest; + if (handler != null) + { + foreach (ParcelPropertiesUpdateRequest d in handler.GetInvocationList()) + { + try + { + d(args, local_id, remote_client); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[EVENT MANAGER]: Delegate for TriggerOnSceneObjectPartCopy failed - continuing. {0} {1}", + e.Message, e.StackTrace); + } + } + } + } } -} \ No newline at end of file +} -- cgit v1.1 From f2e343d53081dbd6956d39b1e172e171101a4900 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 6 Sep 2010 14:09:46 +0200 Subject: Workaround for mono bug #312968 --- OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs index 41ece86..e481b2b 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs @@ -64,6 +64,7 @@ namespace OpenSim.Framework.Servers.HttpServer if ((verb == "POST") || (verb == "PUT")) { request.ContentType = "text/www-form-urlencoded"; + request.KeepAlive = true; int length = 0; using (StreamWriter writer = new StreamWriter(buffer)) -- cgit v1.1 From 06adbc13242c16d40f9e9a02652067131f2eb9b7 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 6 Sep 2010 17:24:10 +0200 Subject: Revert "Workaround for mono bug #312968" This reverts commit f2e343d53081dbd6956d39b1e172e171101a4900. Doesn't compile with our version of Mono. Patched Mono instead. --- OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs index e481b2b..41ece86 100644 --- a/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs +++ b/OpenSim/Framework/Servers/HttpServer/SynchronousRestFormsRequester.cs @@ -64,7 +64,6 @@ namespace OpenSim.Framework.Servers.HttpServer if ((verb == "POST") || (verb == "PUT")) { request.ContentType = "text/www-form-urlencoded"; - request.KeepAlive = true; int length = 0; using (StreamWriter writer = new StreamWriter(buffer)) -- cgit v1.1 From f4f9a2cb4590fe56e672242b4c5697078785e793 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 6 Sep 2010 18:14:24 +0200 Subject: Don't turn off the sale settings on child prims when linking, and on copy of prims anymore. The behavior now matches SL and can be used to link vendor prims for transport --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 8823df1..86842b3 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1619,11 +1619,6 @@ namespace OpenSim.Region.Framework.Scenes if (child != null) { - // Make sure no child prim is set for sale - // So that, on delink, no prims are unwittingly - // left for sale and sold off - child.RootPart.ObjectSaleType = 0; - child.RootPart.SalePrice = 10; childGroups.Add(child); } } @@ -1907,9 +1902,6 @@ namespace OpenSim.Region.Framework.Scenes child.ApplyNextOwnerPermissions(); } } - - copy.RootPart.ObjectSaleType = 0; - copy.RootPart.SalePrice = 10; } Entities.Add(copy); -- cgit v1.1 From 8886afd31961e1a838cb15df863ff9155885e0c6 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Mon, 6 Sep 2010 21:59:52 +0200 Subject: Fix yet another cause of "Ghost attachments" --- .../CoreModules/Avatar/Attachments/AttachmentsModule.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index bd9e621..100b55c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -271,8 +271,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) tainted = true; - AttachObject(remoteClient, objatt, AttachmentPt, false); - //objatt.ScheduleGroupForFullUpdate(); + // This will throw if the attachment fails + try + { + AttachObject(remoteClient, objatt, AttachmentPt, false); + } + catch + { + // Make sure the object doesn't stick around and bail + m_scene.DeleteSceneObject(objatt, false); + return null; + } if (tainted) objatt.HasGroupChanged = true; @@ -616,4 +625,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments so.HasGroupChanged = false; } } -} \ No newline at end of file +} -- cgit v1.1 From c719e016ed9bfbb56fd8c571b9b7b9622bcef566 Mon Sep 17 00:00:00 2001 From: Kitto Flora Date: Mon, 6 Sep 2010 21:45:07 +0000 Subject: Falling animation fix, comment out instrumentation. --- .../Scenes/Animation/ScenePresenceAnimator.cs | 95 +++++++++++++--------- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 6 +- OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs | 21 +++-- OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs | 18 +++- 4 files changed, 90 insertions(+), 50 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 99d9564..9658e11 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -61,6 +61,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation public bool m_jumping = false; // Add for jumping public float m_jumpVelocity = 0f; // Add for jumping private int m_landing = 0; // Add for jumping + public bool m_falling = false; // Add for falling + private float m_fallHeight; // Add for falling /// /// The scene presence that this animator applies to @@ -118,7 +120,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation public void ResetAnimations() { +Console.WriteLine("ResetA............."); m_animations.Clear(); +TrySetMovementAnimation("STAND"); } /// @@ -145,7 +149,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation public string GetMovementAnimation() { //Console.WriteLine("GMA-------"); //## - const float FALL_DELAY = 0.33f; +//#@ const float FALL_DELAY = 0.33f; + const float FALL_DELAY = 800f; //## mS //rm for jumping const float PREJUMP_DELAY = 0.25f; const float PREJUMP_DELAY = 200f; // mS add for jumping const float JUMP_PERIOD = 800f; // mS add for jumping @@ -191,9 +196,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation { m_animTickFall = 0; m_animTickJump = 0; - m_jumping = false; //add for jumping flag - m_jumpVelocity = 0f; //add for jumping flag + m_jumping = false; //add for jumping + m_falling = true; //add for falling + m_jumpVelocity = 0f; //add for jumping actor.Selected = false; //add for jumping flag + m_fallHeight = actor.Position.Z; // save latest flying height if (move.X != 0f || move.Y != 0f) { @@ -205,8 +212,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation } else if (move.Z < 0f) { - if (actor != null && actor.IsColliding) + if (actor != null && actor.IsColliding) + { //## +//Console.WriteLine("LAND FLYING"); // ## return "LAND"; + } //# else return "HOVER_DOWN"; } @@ -223,19 +233,25 @@ namespace OpenSim.Region.Framework.Scenes.Animation // rm for jumping if (actor == null || !actor.IsColliding) if ((actor == null || !actor.IsColliding) && !m_jumping) // add for jumping { -//Console.WriteLine("FFL"); //## - float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; +// rm float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; + float fallElapsed = (float)(Environment.TickCount - m_animTickFall); // add, in mS float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; +//Console.WriteLine("falling t={0} v={1}", fallElapsed, fallVelocity); //## - if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f)) +// rm for fall if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f)) + if (!m_jumping && (fallVelocity < -3.0f) ) m_falling = true; // add for falling and jumping + + if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) // add for jumping + // not falling yet or going up { - // Just started falling + // reset start of fall time m_animTickFall = Environment.TickCount; } // else if (!jumping && fallElapsed > FALL_DELAY) - else if (!m_jumping && fallElapsed > FALL_DELAY) // add for jumping + else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) ) // add for falling and jumping { // Falling long enough to trigger the animation +//Console.WriteLine("FALLDOWN"); //## return "FALLDOWN"; } @@ -247,7 +263,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation #region Jumping // section added for jumping... - Vector3 vj = Vector3.Zero; int jumptime; jumptime = Environment.TickCount - m_animTickJump; @@ -258,12 +273,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation // Start jumping, prejump m_animTickFall = 0; m_jumping = true; + m_falling = false; actor.Selected = true; // borrowed for jmping flag m_animTickJump = Environment.TickCount; - vj.Z = 0.35f; -m_jumpVelocity = 0.35f; - vj += actor.Velocity; -// #@ actor.Velocity = vj; + m_jumpVelocity = 0.35f; return "PREJUMP"; } @@ -274,8 +287,9 @@ m_jumpVelocity = 0.35f; //Console.WriteLine("LA {0}", jumptime); //## // end jumping m_jumping = false; + m_falling = false; actor.Selected = false; // borrowed for jumping flag -m_jumpVelocity = 0f; + m_jumpVelocity = 0f; m_animTickFall = Environment.TickCount; return "LAND"; } @@ -283,10 +297,7 @@ m_jumpVelocity = 0f; { //Console.WriteLine("JD {0}", jumptime); //## // jump down - vj = actor.Velocity; - vj.Z = 0f; -m_jumpVelocity = 0f; -// #@ actor.Velocity = vj; + m_jumpVelocity = 0f; return "JUMP"; } else if (jumptime > PREJUMP_DELAY) @@ -294,11 +305,7 @@ m_jumpVelocity = 0f; //Console.WriteLine("JU {0}", jumptime); //## // jump up m_jumping = true; - vj.Z = 10f; -m_jumpVelocity = 10f; - vj.X = actor.Velocity.X; - vj.Y = actor.Velocity.Y; -// #@ actor.Velocity = vj; + m_jumpVelocity = 10f; return "JUMP"; } } @@ -309,29 +316,37 @@ m_jumpVelocity = 10f; if (m_movementAnimation == "FALLDOWN") { + m_falling = false; m_animTickFall = Environment.TickCount; - // TODO: SOFT_LAND support - return "LAND"; + float fallHeight = m_fallHeight - actor.Position.Z; +//Console.WriteLine("Hit from {0}", fallHeight); //## + if (fallHeight > 15.0f) // add for falling + return "STANDUP"; + else if (fallHeight > 8.0f) // add for falling + return "SOFT_LAND"; // add for falling + else // add for falling + return "LAND"; // add for falling } - else if (m_movementAnimation == "LAND") - { // rm jumping float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; - int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping // rm jumping if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) -/* Try change ## - if ((m_animTickFall != 0) && (landElapsed <= 500)) // add for jumping - return "LAND"; - */ - // NB if this is set too long a weird anim reset from some place prevents STAND from being sent to client - if ((m_animTickFall != 0) && (landElapsed <= 300)) // add for jumping +// rm for landing return "LAND"; + else if ((m_movementAnimation == "LAND") || (m_movementAnimation == "SOFT_LAND") || (m_movementAnimation == "STANDUP")) + { + int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping + int limit = 1000; // add for jumping + if(m_movementAnimation == "LAND") limit = 350; // add for jumping + // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client + + if ((m_animTickFall != 0) && (landElapsed <= limit)) // add for jumping { -//Console.WriteLine("LAND"); //## - return "LAND"; +//Console.WriteLine("Lelapse {0}", m_movementAnimation); //## + return m_movementAnimation; } else { -//Console.WriteLine("STAND"); //## +//Console.WriteLine("end/STAND"); //## + m_fallHeight = actor.Position.Z; // save latest flying height return "STAND"; } } @@ -369,6 +384,8 @@ m_jumpVelocity = 10f; // next section moved outside paren. and realigned for jumping if (move.X != 0f || move.Y != 0f) { + m_fallHeight = actor.Position.Z; // save latest flying height + m_falling = false; // Add for falling // Walking / crouchwalking / running if (move.Z < 0f) return "CROUCHWALK"; @@ -380,6 +397,7 @@ m_jumpVelocity = 10f; // rm for jumping else else if (!m_jumping) // add for jumping { + m_falling = false; // Add for falling // Not walking if (move.Z < 0f) return "CROUCH"; @@ -389,6 +407,7 @@ m_jumpVelocity = 10f; // end section realign for jumping #endregion Ground Movement + m_falling = false; // Add for falling return m_movementAnimation; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 2ed00a0..faf6354 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2568,9 +2568,11 @@ namespace OpenSim.Region.Framework.Scenes if (actor != null) { - if (actor.Flying) +// rm falling if (actor.Flying) + if ((actor.Flying) || Animator.m_falling) // add for falling lateral speed { - direc *= 4.0f; +// rm speed mod direc *= 4.0f; + direc *= 5.2f; // for speed mod //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); //bool colliding = (m_physicsActor.IsColliding==true); //if (controlland) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index 0c79aa6..ae63cfa 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -269,7 +269,10 @@ namespace OpenSim.Region.Physics.OdePlugin /// public override bool IsColliding { - get { return m_iscolliding; } +//#@ get { return m_iscolliding; } + get { //## +//Console.WriteLine(">>>>>>>>>>>> IC get = {0}", m_iscolliding); //## + return m_iscolliding; } //## set { int i; @@ -307,6 +310,7 @@ namespace OpenSim.Region.Physics.OdePlugin { m_iscolliding = true; } +// ## Console.WriteLine("IC SET = {0} t{1} f{2} i {3}", value, truecount, falsecount, m_iscolliding); if (m_wascolliding != m_iscolliding) { //base.SendCollisionUpdate(new CollisionEventUpdate()); @@ -589,7 +593,7 @@ namespace OpenSim.Region.Physics.OdePlugin Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); _parent_scene.geom_name_map[Shell] = m_name; _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; -//Console.WriteLine("**** Create {2} Dicts: actor={0} name={1}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, m_name); +Console.WriteLine("**** Create {2} Dicts: actor={0} name={1} height={3} rad={4}", _parent_scene.actor_name_map.Count, _parent_scene.geom_name_map.Count, m_name, CAPSULE_LENGTH, CAPSULE_RADIUS); d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); d.GeomSetCollideBits(Shell, (int)m_collisionFlags); @@ -857,7 +861,9 @@ namespace OpenSim.Region.Physics.OdePlugin { m_pidControllerActive = false; force *= 100f; - doForce(force); +//Console.WriteLine("DF 1"); // ## + if (!force.ApproxEquals(Vector3.Zero, 0.01f)) + doForce(force); // If uncommented, things get pushed off world // // m_log.Debug("Push!"); @@ -896,7 +902,8 @@ namespace OpenSim.Region.Physics.OdePlugin d.BodyAddForce(Body, force.X, force.Y, force.Z); //d.BodySetRotation(Body, ref m_StandUpRotation); //standupStraight(); - + d.Vector3 vel = d.BodyGetLinearVel(Body); //## +//Console.WriteLine("AvVel <{0},{1},{2}>", vel.X, vel.Y, vel.Z); //## } } @@ -1103,12 +1110,14 @@ namespace OpenSim.Region.Physics.OdePlugin } if (vec.IsFinite()) { - if (!vec.ApproxEquals(Vector3.Zero, 0.01f)) + if (!vec.ApproxEquals(Vector3.Zero, 0.02f)) // 0.01 allows 0.002 !! { +//Console.WriteLine("DF 2"); // ## + doForce(vec); if (!_zeroFlag) { - AlignAvatarTiltWithCurrentDirectionOfMovement(vec); +// AlignAvatarTiltWithCurrentDirectionOfMovement(vec); } } } diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs index ab084fd..86f9893 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs @@ -713,7 +713,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Test if we're colliding a geom with a space. // If so we have to drill down into the space recursively - +//Console.WriteLine("near -----------"); //## if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) { if (g1 == IntPtr.Zero || g2 == IntPtr.Zero) @@ -844,11 +844,21 @@ namespace OpenSim.Region.Physics.OdePlugin // Testing if the collision is at the feet of the avatar //m_log.DebugFormat("[PHYSICS]: {0} - {1} - {2} - {3}", curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f)); - if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f)) - p2.IsColliding = true; - } +//#@ if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f)) +//#@ p2.IsColliding = true; + if ((p2.Position.Z - curContact.pos.Z) > (p2.Size.Z * 0.6f)){ //## +//Console.WriteLine("AvColl 1 {0} - {1} - {2} - {3}", //## +// curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f)); //## + p2.IsColliding = true; //## + }else{ +//Console.WriteLine("AvColl 2 {0} - {1} - {2} - {3}", //## +// curContact.pos.Z, p2.Position.Z, (p2.Position.Z - curContact.pos.Z), (p2.Size.Z * 0.6f)); //## + + } //## + } else { +//Console.WriteLine("AvColl 3 {0}", p2.PhysicsActorType); //## p2.IsColliding = true; } -- cgit v1.1 From 8ab4b277c1e1d5470a0322ec49dde665f3cceadc Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 7 Sep 2010 17:12:28 +0200 Subject: Fix some issues with unlinking --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 109 +++++++++++++------------- 1 file changed, 53 insertions(+), 56 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 905c683..a39f27a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1678,28 +1678,23 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = part.ParentGroup; if (!affectedGroups.Contains(group)) + { + group.areUpdatesSuspended = true; affectedGroups.Add(group); + } } } } if (childParts.Count > 0) { - try + foreach (SceneObjectPart child in childParts) { - childParts[0].ParentGroup.areUpdatesSuspended = true; - foreach (SceneObjectPart child in childParts) - { - // Unlink all child parts from their groups - // - child.ParentGroup.DelinkFromGroup(child, true); - child.ParentGroup.HasGroupChanged = true; - child.ParentGroup.ScheduleGroupForFullUpdate(); - } - } - finally - { - childParts[0].ParentGroup.areUpdatesSuspended = false; + // Unlink all child parts from their groups + // + child.ParentGroup.DelinkFromGroup(child, true); + child.ParentGroup.HasGroupChanged = true; + child.ParentGroup.ScheduleGroupForFullUpdate(); } } @@ -1710,9 +1705,10 @@ namespace OpenSim.Region.Framework.Scenes // However, editing linked parts and unlinking may be different // SceneObjectGroup group = root.ParentGroup; + group.areUpdatesSuspended = true; List newSet = null; - int numChildren = -1; + int numChildren; lock (group.Children) { @@ -1720,63 +1716,63 @@ namespace OpenSim.Region.Framework.Scenes numChildren = group.PrimCount; } + if (numChildren == 1) + break; + // If there are prims left in a link set, but the root is // slated for unlink, we need to do this + // Unlink the remaining set // - if (numChildren != 1) - { - // Unlink the remaining set - // - bool sendEventsToRemainder = true; - if (numChildren > 1) - sendEventsToRemainder = false; + bool sendEventsToRemainder = true; + if (numChildren > 1) + sendEventsToRemainder = false; - if (newSet.Count > 0) + foreach (SceneObjectPart p in newSet) + { + if (p != group.RootPart) { - try + group.DelinkFromGroup(p, sendEventsToRemainder); + if (numChildren > 2) { - newSet[0].ParentGroup.areUpdatesSuspended = true; - foreach (SceneObjectPart p in newSet) - { - if (p != group.RootPart) - group.DelinkFromGroup(p, sendEventsToRemainder); - } + p.ParentGroup.areUpdatesSuspended = true; } - finally + else { - newSet[0].ParentGroup.areUpdatesSuspended = false; + p.ParentGroup.HasGroupChanged = true; + p.ParentGroup.ScheduleGroupForFullUpdate(); } } + } + + // If there is more than one prim remaining, we + // need to re-link + // + if (numChildren > 2) + { + // Remove old root + // + if (newSet.Contains(root)) + newSet.Remove(root); - // If there is more than one prim remaining, we - // need to re-link + // Preserve link ordering // - if (numChildren > 2) + newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) { - // Remove old root - // - if (newSet.Contains(root)) - newSet.Remove(root); - - // Preserve link ordering - // - newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b) - { - return a.LinkNum.CompareTo(b.LinkNum); - }); + return a.LinkNum.CompareTo(b.LinkNum); + }); - // Determine new root - // - SceneObjectPart newRoot = newSet[0]; - newSet.RemoveAt(0); + // Determine new root + // + SceneObjectPart newRoot = newSet[0]; + newSet.RemoveAt(0); - foreach (SceneObjectPart newChild in newSet) - newChild.UpdateFlag = 0; + foreach (SceneObjectPart newChild in newSet) + newChild.UpdateFlag = 0; - LinkObjects(newRoot, newSet); - if (!affectedGroups.Contains(newRoot.ParentGroup)) - affectedGroups.Add(newRoot.ParentGroup); - } + newRoot.ParentGroup.areUpdatesSuspended = true; + LinkObjects(newRoot, newSet); + if (!affectedGroups.Contains(newRoot.ParentGroup)) + affectedGroups.Add(newRoot.ParentGroup); } } @@ -1786,6 +1782,7 @@ namespace OpenSim.Region.Framework.Scenes { g.TriggerScriptChangedEvent(Changed.LINK); g.HasGroupChanged = true; // Persist + g.areUpdatesSuspended = false; g.ScheduleGroupForFullUpdate(); } } -- cgit v1.1 From 50cc22c9e68aa62a529bf62553dc2f0739f3d0a2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 7 Sep 2010 20:19:52 +0100 Subject: Fix Simian regression --- .../SimianGrid/SimianAssetServiceConnector.cs | 37 +++++++++-------- .../SimianAuthenticationServiceConnector.cs | 35 ++++++++-------- .../SimianGrid/SimianAvatarServiceConnector.cs | 35 ++++++++-------- .../SimianGrid/SimianGridServiceConnector.cs | 35 ++++++++-------- .../SimianGrid/SimianInventoryServiceConnector.cs | 47 ++++++++++++---------- .../SimianGrid/SimianPresenceServiceConnector.cs | 35 ++++++++-------- .../SimianUserAccountServiceConnector.cs | 35 ++++++++-------- 7 files changed, 140 insertions(+), 119 deletions(-) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 99e6983..6d5b30e 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -81,7 +81,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianAssetServiceConnector(IConfigSource source) { - Initialise(source); + CommonInit(source); } public void Initialise(IConfigSource source) @@ -91,25 +91,28 @@ namespace OpenSim.Services.Connectors.SimianGrid { string name = moduleConfig.GetString("AssetServices", ""); if (name == Name) - { - IConfig gridConfig = source.Configs["AssetService"]; - if (gridConfig != null) - { - string serviceUrl = gridConfig.GetString("AssetServerURI"); - if (!String.IsNullOrEmpty(serviceUrl)) - { - if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) - serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; - } - } + CommonInit(source); + } + } - if (String.IsNullOrEmpty(m_serverUrl)) - m_log.Info("[SIMIAN ASSET CONNECTOR]: No AssetServerURI specified, disabling connector"); - else - m_Enabled = true; + private void CommonInit(IConfigSource source) + { + IConfig gridConfig = source.Configs["AssetService"]; + if (gridConfig != null) + { + string serviceUrl = gridConfig.GetString("AssetServerURI"); + if (!String.IsNullOrEmpty(serviceUrl)) + { + if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) + serviceUrl = serviceUrl + '/'; + m_serverUrl = serviceUrl; } } + + if (String.IsNullOrEmpty(m_serverUrl)) + m_log.Info("[SIMIAN ASSET CONNECTOR]: No AssetServerURI specified, disabling connector"); + else + m_Enabled = true; } #region IAssetService diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs index 68f73ee..51a09f8 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAuthenticationServiceConnector.cs @@ -69,7 +69,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianAuthenticationServiceConnector(IConfigSource source) { - Initialise(source); + CommonInit(source); } public void Initialise(IConfigSource source) @@ -79,24 +79,27 @@ namespace OpenSim.Services.Connectors.SimianGrid { string name = moduleConfig.GetString("AuthenticationServices", ""); if (name == Name) - { - IConfig gridConfig = source.Configs["AuthenticationService"]; - if (gridConfig != null) - { - string serviceUrl = gridConfig.GetString("AuthenticationServerURI"); - if (!String.IsNullOrEmpty(serviceUrl)) - { - if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) - serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; - m_Enabled = true; - } - } + CommonInit(source); + } + } - if (String.IsNullOrEmpty(m_serverUrl)) - m_log.Info("[SIMIAN AUTH CONNECTOR]: No AuthenticationServerURI specified, disabling connector"); + private void CommonInit(IConfigSource source) + { + IConfig gridConfig = source.Configs["AuthenticationService"]; + if (gridConfig != null) + { + string serviceUrl = gridConfig.GetString("AuthenticationServerURI"); + if (!String.IsNullOrEmpty(serviceUrl)) + { + if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) + serviceUrl = serviceUrl + '/'; + m_serverUrl = serviceUrl; + m_Enabled = true; } } + + if (String.IsNullOrEmpty(m_serverUrl)) + m_log.Info("[SIMIAN AUTH CONNECTOR]: No AuthenticationServerURI specified, disabling connector"); } public string Authenticate(UUID principalID, string password, int lifetime) diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs index 7e56bd1..3505c64 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAvatarServiceConnector.cs @@ -74,7 +74,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianAvatarServiceConnector(IConfigSource source) { - Initialise(source); + CommonInit(source); } public void Initialise(IConfigSource source) @@ -84,24 +84,27 @@ namespace OpenSim.Services.Connectors.SimianGrid { string name = moduleConfig.GetString("AvatarServices", ""); if (name == Name) - { - IConfig gridConfig = source.Configs["AvatarService"]; - if (gridConfig != null) - { - string serviceUrl = gridConfig.GetString("AvatarServerURI"); - if (!String.IsNullOrEmpty(serviceUrl)) - { - if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) - serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; - m_Enabled = true; - } - } + CommonInit(source); + } + } - if (String.IsNullOrEmpty(m_serverUrl)) - m_log.Info("[SIMIAN AVATAR CONNECTOR]: No AvatarServerURI specified, disabling connector"); + private void CommonInit(IConfigSource source) + { + IConfig gridConfig = source.Configs["AvatarService"]; + if (gridConfig != null) + { + string serviceUrl = gridConfig.GetString("AvatarServerURI"); + if (!String.IsNullOrEmpty(serviceUrl)) + { + if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) + serviceUrl = serviceUrl + '/'; + m_serverUrl = serviceUrl; + m_Enabled = true; } } + + if (String.IsNullOrEmpty(m_serverUrl)) + m_log.Info("[SIMIAN AVATAR CONNECTOR]: No AvatarServerURI specified, disabling connector"); } #region IAvatarService diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs index 4fceef6..c2c7168 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianGridServiceConnector.cs @@ -98,7 +98,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianGridServiceConnector(IConfigSource source) { - Initialise(source); + CommonInit(source); } public void Initialise(IConfigSource source) @@ -108,24 +108,27 @@ namespace OpenSim.Services.Connectors.SimianGrid { string name = moduleConfig.GetString("GridServices", ""); if (name == Name) - { - IConfig gridConfig = source.Configs["GridService"]; - if (gridConfig != null) - { - string serviceUrl = gridConfig.GetString("GridServerURI"); - if (!String.IsNullOrEmpty(serviceUrl)) - { - if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) - serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; - m_Enabled = true; - } - } + CommonInit(source); + } + } - if (String.IsNullOrEmpty(m_serverUrl)) - m_log.Info("[SIMIAN GRID CONNECTOR]: No GridServerURI specified, disabling connector"); + private void CommonInit(IConfigSource source) + { + IConfig gridConfig = source.Configs["GridService"]; + if (gridConfig != null) + { + string serviceUrl = gridConfig.GetString("GridServerURI"); + if (!String.IsNullOrEmpty(serviceUrl)) + { + if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) + serviceUrl = serviceUrl + '/'; + m_serverUrl = serviceUrl; + m_Enabled = true; } } + + if (String.IsNullOrEmpty(m_serverUrl)) + m_log.Info("[SIMIAN GRID CONNECTOR]: No GridServerURI specified, disabling connector"); } #region IGridService diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs index eb118ae..470eccd 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianInventoryServiceConnector.cs @@ -88,7 +88,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianInventoryServiceConnector(IConfigSource source) { - Initialise(source); + CommonInit(source); } public void Initialise(IConfigSource source) @@ -98,36 +98,39 @@ namespace OpenSim.Services.Connectors.SimianGrid { string name = moduleConfig.GetString("InventoryServices", ""); if (name == Name) + CommonInit(source); + } + } + + private void CommonInit(IConfigSource source) + { + IConfig gridConfig = source.Configs["InventoryService"]; + if (gridConfig != null) + { + string serviceUrl = gridConfig.GetString("InventoryServerURI"); + if (!String.IsNullOrEmpty(serviceUrl)) { - IConfig gridConfig = source.Configs["InventoryService"]; + if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) + serviceUrl = serviceUrl + '/'; + m_serverUrl = serviceUrl; + + gridConfig = source.Configs["UserAccountService"]; if (gridConfig != null) { - string serviceUrl = gridConfig.GetString("InventoryServerURI"); + serviceUrl = gridConfig.GetString("UserAccountServerURI"); if (!String.IsNullOrEmpty(serviceUrl)) { - if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) - serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; - - gridConfig = source.Configs["UserAccountService"]; - if (gridConfig != null) - { - serviceUrl = gridConfig.GetString("UserAccountServerURI"); - if (!String.IsNullOrEmpty(serviceUrl)) - { - m_userServerUrl = serviceUrl; - m_Enabled = true; - } - } + m_userServerUrl = serviceUrl; + m_Enabled = true; } } - - if (String.IsNullOrEmpty(m_serverUrl)) - m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No InventoryServerURI specified, disabling connector"); - else if (String.IsNullOrEmpty(m_userServerUrl)) - m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No UserAccountServerURI specified, disabling connector"); } } + + if (String.IsNullOrEmpty(m_serverUrl)) + m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No InventoryServerURI specified, disabling connector"); + else if (String.IsNullOrEmpty(m_userServerUrl)) + m_log.Info("[SIMIAN INVENTORY CONNECTOR]: No UserAccountServerURI specified, disabling connector"); } /// diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index 074c80f..077be3c 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs @@ -99,7 +99,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianPresenceServiceConnector(IConfigSource source) { - Initialise(source); + CommonInit(source); } public void Initialise(IConfigSource source) @@ -109,24 +109,27 @@ namespace OpenSim.Services.Connectors.SimianGrid { string name = moduleConfig.GetString("PresenceServices", ""); if (name == Name) + CommonInit(source); + } + } + + private void CommonInit(IConfigSource source) + { + IConfig gridConfig = source.Configs["PresenceService"]; + if (gridConfig != null) + { + string serviceUrl = gridConfig.GetString("PresenceServerURI"); + if (!String.IsNullOrEmpty(serviceUrl)) { - IConfig gridConfig = source.Configs["PresenceService"]; - if (gridConfig != null) - { - string serviceUrl = gridConfig.GetString("PresenceServerURI"); - if (!String.IsNullOrEmpty(serviceUrl)) - { - if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) - serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; - m_Enabled = true; - } - } - - if (String.IsNullOrEmpty(m_serverUrl)) - m_log.Info("[SIMIAN PRESENCE CONNECTOR]: No PresenceServerURI specified, disabling connector"); + if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) + serviceUrl = serviceUrl + '/'; + m_serverUrl = serviceUrl; + m_Enabled = true; } } + + if (String.IsNullOrEmpty(m_serverUrl)) + m_log.Info("[SIMIAN PRESENCE CONNECTOR]: No PresenceServerURI specified, disabling connector"); } #region IPresenceService diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index deb8695..694aa72 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -73,7 +73,7 @@ namespace OpenSim.Services.Connectors.SimianGrid public SimianUserAccountServiceConnector(IConfigSource source) { - Initialise(source); + CommonInit(source); } public void Initialise(IConfigSource source) @@ -83,24 +83,27 @@ namespace OpenSim.Services.Connectors.SimianGrid { string name = moduleConfig.GetString("UserAccountServices", ""); if (name == Name) - { - IConfig gridConfig = source.Configs["UserAccountService"]; - if (gridConfig != null) - { - string serviceUrl = gridConfig.GetString("UserAccountServerURI"); - if (!String.IsNullOrEmpty(serviceUrl)) - { - if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) - serviceUrl = serviceUrl + '/'; - m_serverUrl = serviceUrl; - m_Enabled = true; - } - } + CommonInit(source); + } + } - if (String.IsNullOrEmpty(m_serverUrl)) - m_log.Info("[SIMIAN ACCOUNT CONNECTOR]: No UserAccountServerURI specified, disabling connector"); + private void CommonInit(IConfigSource source) + { + IConfig gridConfig = source.Configs["UserAccountService"]; + if (gridConfig != null) + { + string serviceUrl = gridConfig.GetString("UserAccountServerURI"); + if (!String.IsNullOrEmpty(serviceUrl)) + { + if (!serviceUrl.EndsWith("/") && !serviceUrl.EndsWith("=")) + serviceUrl = serviceUrl + '/'; + m_serverUrl = serviceUrl; + m_Enabled = true; } } + + if (String.IsNullOrEmpty(m_serverUrl)) + m_log.Info("[SIMIAN ACCOUNT CONNECTOR]: No UserAccountServerURI specified, disabling connector"); } public UserAccount GetUserAccount(UUID scopeID, string firstName, string lastName) -- cgit v1.1 From 7a1b1dd419d458cbf46ecdf48872497186e67355 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Wed, 8 Sep 2010 00:49:32 +0200 Subject: Make AddRestoredSceneObject reset the IsDeleted flag so we can take an object out of the scene and then put it back in. --- OpenSim/Region/Framework/Scenes/Scene.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 6b71426..be342ab 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2003,7 +2003,10 @@ namespace OpenSim.Region.Framework.Scenes public bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { - return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); + bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); + if (result) + sceneObject.IsDeleted = false; + return result; } /// -- cgit v1.1 From 5e5260ad1b677f5ee85e065e0011ceb71d1c299a Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 11 Sep 2010 20:22:10 +0100 Subject: Prevent child agents from being blacklisted in the kill record. --- OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 3dea40c..8a96389 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -1529,10 +1529,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP kill.Header.Reliable = true; kill.Header.Zerocoded = true; - lock (m_entityUpdates.SyncRoot) + if (m_scene.GetScenePresence(localID) == null) { - m_killRecord.Add(localID); - OutPacket(kill, ThrottleOutPacketType.State); + lock (m_entityUpdates.SyncRoot) + { + m_killRecord.Add(localID); + OutPacket(kill, ThrottleOutPacketType.State); + } } } -- cgit v1.1 From 5e1aab92f588e776bb6ff6c532c0099e87908c4f Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 13 Sep 2010 23:12:48 +0100 Subject: Make the inimaster option default to OpenSimDefaults.ini. --- OpenSim/Region/Application/ConfigurationLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index e2e0640..31ce500 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -83,7 +83,7 @@ namespace OpenSim List sources = new List(); string masterFileName = - startupConfig.GetString("inimaster", String.Empty); + startupConfig.GetString("inimaster", "OpenSimDefaults.ini"); if (IsUri(masterFileName)) { -- cgit v1.1 From 8e51ca3a7ba51ae1b38ba66ae24a958ccb405a21 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 13 Sep 2010 23:17:42 +0100 Subject: Output an error and quit if the master file is missing. Also rename OpenSim.ini.example to bin/OpenSimDefaults.ini.example --- OpenSim/Region/Application/ConfigurationLoader.cs | 20 +- bin/OpenSim.ini.example | 1325 --------------------- bin/OpenSimDefaults.ini.example | 1325 +++++++++++++++++++++ 3 files changed, 1341 insertions(+), 1329 deletions(-) delete mode 100644 bin/OpenSim.ini.example create mode 100644 bin/OpenSimDefaults.ini.example diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index 31ce500..9d6fef7 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -85,6 +85,9 @@ namespace OpenSim string masterFileName = startupConfig.GetString("inimaster", "OpenSimDefaults.ini"); + if (masterFileName == "none") + masterFileName = String.Empty; + if (IsUri(masterFileName)) { if (!sources.Contains(masterFileName)) @@ -95,10 +98,19 @@ namespace OpenSim string masterFilePath = Path.GetFullPath( Path.Combine(Util.configDir(), masterFileName)); - if (masterFileName != String.Empty && - File.Exists(masterFilePath) && - (!sources.Contains(masterFilePath))) - sources.Add(masterFilePath); + if (masterFileName != String.Empty) + { + if (File.Exists(masterFilePath) + { + if (!sources.Contains(masterFilePath)) + sources.Add(masterFilePath); + } + else + { + m_log.ErrorFormat("Master ini file {0} not found", masterFilePath); + Environment.Exit(1); + } + } } diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example deleted file mode 100644 index ef8f73a..0000000 --- a/bin/OpenSim.ini.example +++ /dev/null @@ -1,1325 +0,0 @@ -[Startup] - ; Set this to true if you want to log crashes to disk - ; this can be useful when submitting bug reports. - save_crashes = false - - ; Directory to save crashes to if above is enabled - ; (default is /opensimdir/crashes/*.txt or C:\opensim\crashes\*.txt) - crash_dir = "crashes" - - ; Place to create a PID file - ; PIDFile = "/tmp/my.pid" - - ; Http proxy support for llHTTPRequest and dynamic texture loading - ; Set HttpProxy to the URL for your proxy server if you would like - ; to proxy llHTTPRequests through a firewall - ; HttpProxy = "http://proxy.com" - ; Set HttpProxyExceptions to a list of regular expressions for - ; URLs that you don't want going through the proxy such as servers - ; inside your firewall, separate patterns with a ';' - ; HttpProxyExceptions = ".mydomain.com;localhost" - - startup_console_commands_file = "startup_commands.txt" - shutdown_console_commands_file = "shutdown_commands.txt" - - ; To run a script every few minutes, set the script filename here - ; timer_Script = "filename" - - ; ## - ; ## SYSTEM - ; ## - - ; Sets the method that OpenSim will use to fire asynchronous - ; events. Valid values are UnsafeQueueUserWorkItem, - ; QueueUserWorkItem, BeginInvoke, SmartThreadPool, and Thread. - ; SmartThreadPool is reported to work well on Mono/Linux, but - ; UnsafeQueueUserWorkItem has been benchmarked with better - ; performance on .NET/Windows - async_call_method = SmartThreadPool - - ; Max threads to allocate on the FireAndForget thread pool - ; when running with the SmartThreadPool option above - MaxPoolThreads = 15 - - ; ## - ; ## CLIENTS - ; ## - - ; Enables EventQueueGet Service. - EventQueue = true - - ; Set this to the DLL containing the client stack to use. - clientstack_plugin="OpenSim.Region.ClientStack.LindenUDP.dll" - - ; ## - ; ## REGIONS - ; ## - - ; Determine where OpenSimulator looks for the files which tell it which regions to server - ; Defaults to "filesystem" if this setting isn't present - region_info_source = "filesystem" - ; region_info_source = "web" - - ; Determines where the region XML files are stored if you are loading these from the filesystem. - ; Defaults to bin/Regions in your OpenSimulator installation directory - ; regionload_regionsdir="C:\somewhere\xmlfiles\" - - ; Determines the page from which regions xml is retrieved if you are loading these from the web - ; The XML here has the same format as it does on the filesystem (including the tag), - ; except that everything is also enclosed in a tag. - ; regionload_webserver_url = "http://example.com/regions.xml"; - - ; Draw objects on maptile. This step might take a long time if you've got a large number of - ; objects, so you can turn it off here if you'd like. - DrawPrimOnMapTile = true - ; Use terrain texture for maptiles if true, use shaded green if false - TextureOnMapTile = false - - ; Maximum total size, and maximum size where a prim can be physical - NonPhysicalPrimMax = 256 - PhysicalPrimMax = 10 ; (I think this was moved to the Regions.ini!) - ClampPrimSize = false - - ; Allow scripts to cross region boundaries. These are recompiled on the new region. - AllowScriptCrossing = false - - ; Allow compiled script binary code to cross region boundaries. - ; If you set this to "true", any region that can teleport to you can - ; inject ARBITRARY BINARY CODE into your system. Use at your own risk. - ; YOU HAVE BEEN WARNED!!! - TrustBinaries = false - - ; Combine all contiguous regions into one large megaregion - ; Order your regions from South to North, West to East in your regions.ini and then set this to true - ; Warning! Don't use this with regions that have existing content!, This will likely break them - CombineContiguousRegions = false - - ; If you have only one region in an instance, or to avoid the many bugs - ; that you can trigger in modules by restarting a region, set this to - ; true to make the entire instance exit instead of restarting the region. - ; This is meant to be used on systems where some external system like - ; Monit will restart any instance that exits, thereby making the shutdown - ; into a restart. - ;InworldRestartShutsDown = false - - ; ## - ; ## PRIM STORAGE - ; ## - - ; Persistence of changed objects happens during regular sweeps. The following control that behaviour to - ; prevent frequently changing objects from heavily loading the region data store. - ; If both of these values are set to zero then persistence of all changed objects will happen on every sweep. - ; - ; Objects will be considered for persistance in the next sweep when they have not changed for this number of seconds - MinimumTimeBeforePersistenceConsidered = 60 - ; Objects will always be considered for persistance in the next sweep if the first change occurred this number of seconds ago - MaximumTimeBeforePersistenceConsidered = 600 - - ; Should avatars in neighbor sims see objects in this sim? - see_into_this_sim_from_neighbor = true - - ; ## - ; ## PHYSICS - ; ## - - ; if you would like to allow prims to be physical and move by physics with the physical checkbox in the client set this to true. - physical_prim = true - - ; Select a mesher here. - ; - ; Meshmerizer properly handles complex prims by using triangle meshes. - ; Note that only the ODE physics engine currently deals with meshed prims in a satisfactory way - ; - ; ZeroMesher is faster but leaves the physics engine to model the mesh using the basic shapes that it supports - ; Usually this is only a box - - meshing = Meshmerizer - ;meshing = ZeroMesher - - ; Choose one of the physics engines below - ; OpenDynamicsEngine is by some distance the most developed physics engine - ; basicphysics effectively does not model physics at all, making all objects phantom - - physics = OpenDynamicsEngine - ;physics = basicphysics - ;physics = POS - ;physics = modified_BulletX - - ; ## - ; ## PERMISSIONS - ; ## - - ;permissionmodules = "DefaultPermissionsModule" - - ;If any of the specified permissions modules fail to load, quit? - SecurePermissionsLoading = true - - ; If set to false, then, in theory, the server never carries out permission checks (allowing anybody to copy - ; any item, etc. This may not yet be implemented uniformally. - ; If set to true, then all permissions checks are carried out - ; Default is false - serverside_object_permissions = false - - allow_grid_gods = false - - ; This allows somne control over permissions - ; please note that this still doesn't duplicate SL, and is not intended to - ;region_owner_is_god = true - ;region_manager_is_god = false - ;parcel_owner_is_god = true - - ; Control user types that are allowed to create new scripts - ; Only enforced if serviceside_object_permissions is true - ; - ; Current possible values are - ; all - anyone can create scripts (subject to normal permissions) - ; gods - only administrators can create scripts (as long as allow_grid_gods is true) - ; Default value is all - ; allowed_script_creators = all - - ; Control user types that are allowed to edit (save) scripts - ; Only enforced if serviceside_object_permissions is true - ; - ; Current possible values are - ; all - anyone can edit scripts (subject to normal permissions) - ; gods - only administrators can edit scripts (as long as allow_grid_gods is true) - ; Default value is all - ; allowed_script_editors = all - - ; ## - ; ## SCRIPT ENGINE - ; ## - - DefaultScriptEngine = "XEngine" - - ; ## - ; ## WORLD MAP - ; ## - - ;WorldMapModule = "WorldMap" - ;MapImageModule = "MapImageModule" - ; Set to false to not generate any maptiles - ;GenerateMaptiles = "true" - ; Refresh (in seconds) the map tile periodically - ;MaptileRefresh = 0 - ; If not generating maptiles, use this static texture asset ID - ;MaptileStaticUUID = "00000000-0000-0000-0000-000000000000" - - ; ## - ; ## EMAIL MODULE - ; ## - - ;emailmodule = DefaultEmailModule - - ; ## - ; ## ANIMATIONS - ; ## - - ; If enabled, enableFlySlow will change the primary fly state to - ; FLYSLOW, and the "always run" state will be the regular fly. - - enableflyslow = false - - ; PreJump is an additional animation state, but it probably - ; won't look right until the physics engine supports it - ; (i.e delays takeoff for a moment) - - ; This is commented so it will come on automatically once it's - ; supported. - - ; enableprejump = true - - ; Simulator Stats URI - ; Enable JSON simulator data by setting a URI name (case sensitive) - ; Stats_URI = "jsonSimStats" - - ; Make OpenSim start all regions woth logins disabled. They will need - ; to be enabled from the console if this is set - ; StartDisabled = false - - ; Image decoding. Use CSJ2K for layer boundary decoding if true, - ; OpenJPEG if false - ; UseCSJ2K = true - -[SMTP] - enabled=false - - ;enabled=true - ;internal_object_host=lsl.opensim.local - ;host_domain_header_from=127.0.0.1 - ;SMTP_SERVER_HOSTNAME=127.0.0.1 - ;SMTP_SERVER_PORT=25 - ;SMTP_SERVER_LOGIN=foo - ;SMTP_SERVER_PASSWORD=bar - -[Network] - ConsoleUser = "Test" - ConsolePass = "secret" - http_listener_port = 9000 - console_port = 0 - - ; ssl config: Experimental! The auto https config only really works definately on windows XP now - ; you need a Cert Request/Signed pair installed in the MY store with the CN specified below - ; you can use https on other platforms, but you'll need to configure the httpapi yourself for now - http_listener_ssl = false ; Also create a SSL server - http_listener_cn = "localhost" ; Use the cert with the common name - http_listener_sslport = 9001 ; Use this port for SSL connections - http_listener_ssl_cert = "" ; Currently unused, but will be used for OSHttpServer - - ; Hostname to use in llRequestURL/llRequestSecureURL - ; if not defined - default machine name is being used - ; (on Windows this mean NETBIOS name - useably only inside local network) - ; ExternalHostNameForLSL=127.0.0.1 - - ; What is reported as the "X-Secondlife-Shard" - ; Defaults to the user server url if not set - ; The old default is "OpenSim", set here for compatibility - shard = "OpenSim" - - ; What is reported as the "User-Agent" when using llHTTPRequest - ; Defaults to not sent if not set here. See the notes section in the wiki at - ; http://wiki.secondlife.com/wiki/LlHTTPRequest for comments on adding - ; " (Mozilla Compatible)" to the text where there are problems with a web server - ;user_agent = "OpenSim LSL (Mozilla Compatible)" - -[XMLRPC] - ; ## - ; ## Scripting XMLRPC mapper - ; ## - - ; If enabled, this will post an event, "xmlrpc_uri(string)" to the - ; script concurrently with the first remote_data event. - ; This will contain the fully qualified URI an external site needs - ; to use to send XMLRPC requests to that script - - ;XmlRpcRouterModule = "XmlRpcRouterModule" - ;XmlRpcPort = 20800 - -[ClientStack.LindenUDP] - ; Set this to true to process incoming packets asynchronously. Networking is - ; already separated from packet handling with a queue, so this will only - ; affect whether networking internals such as packet decoding and - ; acknowledgement accounting are done synchronously or asynchronously - ; - ;async_packet_handling = false - - ; The client socket receive buffer size determines how many - ; incoming requests we can process; the default on .NET is 8192 - ; which is about 2 4k-sized UDP datagrams. On mono this is - ; whatever the underlying operating system has as default; for - ; example, ubuntu 8.04 or SLES11 have about 111k, which is about - ; 27 4k-sized UDP datagrams (on linux platforms you can [as root] - ; do "sysctl net.core.rmem_default" to find out what your system - ; uses a default socket receive buffer size. - ; - ; client_socket_rcvbuf_size allows you to specify the receive - ; buffer size LLUDPServer should use. NOTE: this will be limited - ; by the system's settings for the maximum client receive buffer - ; size (on linux systems you can set that with "sysctl -w - ; net.core.rmem_max=X") - ; - ;client_socket_rcvbuf_size = 8388608 - - ; Maximum outbound bytes per second for a single scene. This can be used to - ; throttle total outbound UDP traffic for a simulator. The default value is - ; 0, meaning no throttling at the scene level. The example given here is - ; 20 megabits - ; - ;scene_throttle_max_bps = 2621440 - - ; Maximum bits per second to send to any single client. This will override - ; the user's viewer preference settings. The default value is 0, meaning no - ; aggregate throttling on clients (only per-category throttling). The - ; example given here is 1.5 megabits - ; - ;client_throttle_max_bps = 196608 - - ; Per-client bytes per second rates for the various throttle categories. - ; These are default values that will be overriden by clients - ; - ;resend_default = 12500 - ;land_default = 1000 - ;wind_default = 1000 - ;cloud_default = 1000 - ;task_default = 1000 - ;texture_default = 1000 - ;asset_default = 1000 - ;state_default = 1000 - - ; Per-client maximum burst rates in bytes per second for the various - ; throttle categories. These are default values that will be overriden by - ; clients - ; - ;resend_limit = 18750 - ;land_limit = 29750 - ;wind_limit = 18750 - ;cloud_limit = 18750 - ;task_limit = 18750 - ;texture_limit = 55750 - ;asset_limit = 27500 - ;state_limit = 37000 - - ; Configures how ObjectUpdates are aggregated. These numbers - ; do not literally mean how many updates will be put in each - ; packet that goes over the wire, as packets are - ; automatically split on a 1400 byte boundary. These control - ; the balance between responsiveness of interest list updates - ; and total throughput. Higher numbers will ensure more full- - ; sized packets and faster sending of data, but more delay in - ; updating interest lists - ; - ;PrimTerseUpdatesPerPacket = 25 - ;AvatarTerseUpdatesPerPacket = 10 - ;PrimFullUpdatesPerPacket = 100 - - ; TextureSendLimit determines how many packets will be put on - ; the outgoing queue each cycle. Like the settings above, this - ; is a balance between responsiveness to priority updates and - ; total throughput. Higher numbers will give a better - ; throughput at the cost of reduced responsiveness to client - ; priority changes or transfer aborts - ; - ;TextureSendLimit = 20 - - ; Quash and remove any light properties from attachments not on the - ; hands. This allows flashlights and lanterns to function, but kills - ; silly vanity "Facelights" dead. Sorry, head mounted miner's lamps - ; will also be affected. - ; - ;DisableFacelights = "false" - -[Chat] - ; Controls whether the chat module is enabled. Default is true. - enabled = true; - - ; Distance in meters that whispers should travel. Default is 10m - whisper_distance = 10 - - ; Distance in meters that ordinary chat should travel. Default is 30m - say_distance = 30 - - ; Distance in meters that shouts should travel. Default is 100m - shout_distance = 100 - - ; Append a prefix to the god avatar names appearing in chat whilst in god mode - ; admin_prefix = "@" - - -[Messaging] - ; Control which region module is used for instant messaging. - ; Default is InstantMessageModule (this is the name of the core IM module as well as the setting) - InstantMessageModule = InstantMessageModule - ; MessageTransferModule = MessageTransferModule - ; OfflineMessageModule = OfflineMessageModule - ; OfflineMessageURL = http://yourserver/Offline.php - ; MuteListModule = MuteListModule - ; MuteListURL = http://yourserver/Mute.php - - ; Control whether group messages are forwarded to offline users. Default is true. - ; ForwardOfflineGroupMessages = true - - -[ODEPhysicsSettings] - ;## - ;## World Settings - ;## - - ;Gravity. Feel like falling up? change world_gravityz to 9.8 instead of -9.8. m/s - world_gravityx = 0 - world_gravityy = 0 - world_gravityz = -9.8 - - ; World Step size. (warning these are dangerous. Changing these will probably cause your scene to explode dramatically) - ; reference: fps = (0.09375/ODE_STEPSIZE) * 1000; - world_stepsize = 0.020 - world_internal_steps_without_collisions = 10 - - ;World Space settings. Affects memory consumption vs Collider CPU time for avatar and physical prim - world_hashspace_size_low = -4 - world_hashSpace_size_high = 128 - - ;Dynamic space settings Affects memory consumption vs Collider CPU time for static prim - meters_in_small_space = 29.9 - small_hashspace_size_low = -4 - small_hashspace_size_high = 66 - - ; ## - ; ## Contact properties. (the stuff that happens when things come in contact with each other) - ; ## - - ; surface layer around geometries other geometries can sink into before generating a contact - world_contact_surface_layer = 0.001 - - ; Filtering collisions helps keep things stable physics wise, but sometimes - ; it can be overzealous. If you notice bouncing, chances are it's that. - filter_collisions = false - - ; Non Moving Terrain Contact (avatar isn't moving) - nm_terraincontact_friction = 255.0 - nm_terraincontact_bounce = 0.1 - nm_terraincontact_erp = 0.1025 - - ; Moving Terrain Contact (avatar is moving) - m_terraincontact_friction = 75.0 - m_terraincontact_bounce = 0.05 - m_terrainContact_erp = 0.05025 - - ; Moving Avatar to object Contact - m_avatarobjectcontact_friction = 75.0 - m_avatarobjectcontact_bounce = 0.1 - - ; Object to Object Contact and Non-Moving Avatar to object - objectcontact_friction = 250.0 - objectcontact_bounce = 0.2 - - ; ## - ; ## Avatar Control - ; ## - - ; PID Controller Settings. These affect the math that causes the avatar to reach the - ; desired velocity - ; See http://en.wikipedia.org/wiki/PID_controller - - av_pid_derivative_linux = 2200.0 - av_pid_proportional_linux = 900.0; - - av_pid_derivative_win = 2200.0 - av_pid_proportional_win = 900.0; - - ;girth of the avatar. Adds radius to the height also - av_capsule_radius = 0.37 - - ; Max force permissible to use to keep the avatar standing up straight - av_capsule_standup_tensor_win = 550000 - av_capsule_standup_tensor_linux = 550000 - - ; specifies if the capsule should be tilted (=true; old compatibility mode) - ; or straight up-and-down (=false; better and more consistent physics behavior) - av_capsule_tilted = false - - ; used to calculate mass of avatar. - ; float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH); - ; av_density * AVvolume; - av_density = 80 - - ; use this value to cut 52% of the height the sim gives us - av_height_fudge_factor = 0.52 - - ; Movement. Smaller is faster. - - ; speed of movement with Always Run off - av_movement_divisor_walk = 1.3 - - ; speed of movement with Always Run on - av_movement_divisor_run = 0.8 - - ; When the avatar flies, it will be moved up by this amount off the ground (in meters) - minimum_ground_flight_offset = 3.0 - - ; ## - ; ## Object options - ; ## - - ; used in the mass calculation. - geometry_default_density = 10.000006836 - - ; amount of ODE steps where object is non moving for ODE to automatically put it to sleep - body_frames_auto_disable = 20 - - ; used to control llMove2Target - body_pid_derivative = 35 - body_pid_gain = 25 - - ; maximum number of contact points to generate per collision - contacts_per_collision = 80 - - ; amount of time a geom/body will try to cross a region border before it gets disabled - geom_crossing_failures_before_outofbounds = 5 - - ; start throttling the object updates if object comes in contact with 3 or more other objects - geom_contactpoints_start_throttling = 3 - - ; send 1 update for every x updates below when throttled - geom_updates_before_throttled_update = 15 - - ; Used for llSetStatus. How rigid the object rotation is held on the axis specified - body_motor_joint_maxforce_tensor_linux = 5 - body_motor_joint_maxforce_tensor_win = 5 - - ; Maximum mass an object can be before it is clamped - maximum_mass_object = 10000.01 - - ; ## - ; ## Sculpted Prim settings - ; ## - - ; Do we want to mesh sculpted prim to collide like they look? - mesh_sculpted_prim = true - - ; number^2 non-physical level of detail of the sculpt texture. 32x32 - 1024 verticies - mesh_lod = 32 - - ; number^2 physical level of detail of the sculpt texture. 16x16 - 256 verticies - mesh_physical_lod = 16 - - ; ## - ; ## Physics logging settings - logfiles are saved to *.DIF files - ; ## - - ; default is false - ;physics_logging = true - ;; every n simulation iterations, the physics snapshot file is updated - ;physics_logging_interval = 50 - ;; append to existing physics logfile, or overwrite existing logfiles? - ;physics_logging_append_existing_logfile = true - - ; ## - ; ## Joint support - ; ## - - ; if you would like physics joints to be enabled through a special naming convention in the client, set this to true. - ; (see NINJA Physics documentation, http://opensimulator.org/wiki/NINJA_Physics) - ; default is false - ;use_NINJA_physics_joints = true - - ; ## - ; ## additional meshing options - ; ## - - ; physical collision mesh proxies are normally created for complex prim shapes, and collisions for simple boxes and - ; spheres are computed algorithmically. If you would rather have mesh proxies for simple prims, you can set this to - ; true. Note that this will increase memory usage and region startup time. Default is false. - ;force_simple_prim_meshing = true - - -[RemoteAdmin] - enabled = false - - ; Set this to a nonzero value to have remote admin use a different port - port = 0 - - ; This password is required to make any XMLRPC call (should be set as the "password" parameter) - access_password = unknown - - ; set this variable to true if you want the create_region XmlRpc - ; call to unconditionally enable voice on all parcels for a newly - ; created region [default: false] - create_region_enable_voice = false - - ; set this variable to false if you want the create_region XmlRpc - ; call to create all regions as private per default (can be - ; overridden in the XmlRpc call) [default: true] - create_region_public = false - - ; the create_region XmlRpc call uses region_file_template to generate - ; the file name of newly create regions (if they are created - ; persistent). the parameter available are: - ; {0} - X location - ; {1} - Y location - ; {2} - region UUID - ; {3} - region port - ; {4} - region name with " ", ":", "/" mapped to "_" - region_file_template = "{0}x{1}-{2}.ini" - - ; we can limit the number of regions that XmlRpcCreateRegion will - ; allow by setting this to a positive, non-0 number: as long as the - ; number of regions is below region_limits, XmlRpcCreateRegion will - ; succeed. setting region_limit to 0 disables the check. - ; default is 0 - ;region_limit = 0 - - ; enable only those methods you deem to be appropriate using a | delimited whitelist - ; for example, enabled_methods = admin_broadcast|admin_region_query|admin_save_oar|admin_save_xml - ; if this parameter is not specified but enabled = true, all methods will be available - enabled_methods = all - - ; specify the default appearance for an avatar created through the remote admin interface - ; This will only take effect is the file specified by the default_appearance setting below exists - ;default_male = Default Male - ;default_female = Default Female - - ; update appearance copies inventory items and wearables of default avatars. if this value is false - ; (default), just worn assets are copied to the Clothes folder; if true, all Clothes and Bodyparts - ; subfolders are copied. the receiver will wear the same items the default avatar did wear. - ;copy_folders = false - - ; path to default appearance XML file that specifies the look of the default avatars - ;default_appearance = default_appearance.xml - -[RestPlugins] - ; Change this to true to enable REST Plugins. This must be true if you wish to use - ; REST Region or REST Asset and Inventory Plugins - enabled = false - god_key = SECRET - prefix = /admin - - -[RestRegionPlugin] - ; Change this to true to enable the REST Region Plugin - enabled = false - - -[RestHandler] - ; Change this to true to enable the REST Asset and Inventory Plugin - enabled = false - authenticate = true - secured = true - extended-escape = true - realm = OpenSim REST - dump-asset = false - path-fill = true - dump-line-size = 32 - flush-on-error = true - - -; Uncomment the following for IRC bridge -; experimental, so if it breaks... keep both parts... yada yada -; also, not good error detection when it fails -;[IRC] - ;enabled = true ; you need to set this otherwise it won't connect - ;server = name.of.irc.server.on.the.net - ;; user password - only use this if the server requires one - ;password = mypass - ;nick = OpenSimBotNameProbablyMakeThisShorter - ;channel = #the_irc_channel_you_want_to_connect_to - ;user = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot" - ;port = 6667 - ;; channel to listen for configuration commands - ;commands_enabled = false - ;command_channel = 2777 - ;report_clients = true - ;; relay private chat connections - ;; relay_private_channels = true: will relay IRC chat from/to private in-world channels - ;; relay_private_channel_out -- channel to send messages out to the IRC bridge - ;; relay_private_channel_in -- channel to receive message from the IRC bridge - ;; relay_chat = false: IRC bridge will not relay normal chat - ;; access_password -- simple security device - ;; - ;; so, to just relay chat from an IRC channel to in-world region and vice versa: - ;; - ;; relay_private_channels = false - ;; relay_chat = true - ;; - ;; to relay chat only to/from private in-world channels: - ;; - ;; relay_chat = false - ;; relay_private_channels = true - ;; relay_private_channel_in = 2226 - ;; relay_private_channel_out = 2225 - ;; - ;; in this example, all chat coming in from IRC will be send out via - ;; in-world channel 2226, and all chat from in-world channel 2225 will - ;; be relayed to the IRC channel. - ;; - ;relay_private_channels = false - ;relay_private_channel_in = 2226 - ;relay_private_channel_out = 2225 - ;relay_chat = true - ;access_password = foobar - - ;;fallback_region = name of "default" region - ;;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message - ;; must start with "PRIVMSG {0} : " or irc server will get upset - ;;for : : - ;;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}" - ;;for : - : - ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}" - ;;for : - from : - ;;msgformat = "PRIVMSG {0} : {3} - from {1}" - - ;; exclude_list allows you to stop the IRC connector from announcing the - ;;arrival and departure of certain users. For example: admins, bots. - - ;exclude_list=User 1,User 2,User 3 - - -;[CMS] - ;enabled = true - ;channel = 345 - - -; Uncomment the following to control the progression of daytime -; in the Sim. The defaults are what is shown below -;[Sun] - ; number of wall clock hours for an opensim day. 24.0 would mean realtime - ;day_length = 4 - ; Year length in days - ;year_length = 60 - ; Day to Night Ratio - ;day_night_offset = 0.45 - ; send a Sun update every update_interval # of frames. A lower number will - ; make for smoother sun transition at the cost of network - ;update_interval = 100 - - -[Wind] - ; Enables the wind module. Default is true - enabled = true - - ; How often should wind be updated, as a function of world frames. Approximately 50 frames a second - wind_update_rate = 150 - - ; The Default Wind Plugin to load - wind_plugin = SimpleRandomWind - - ; These settings are specific to the ConfigurableWind plugin - ; To use ConfigurableWind as the default, simply change wind_plugin to ConfigurableWind and uncomment the following. - ; avg_strength = 5.0 - ; avg_direction = 0.0 - ; var_strength = 0.0 - ; var_direction = 0.0 - ; rate_change = 1.0 - - ; This setting is specific to the SimpleRandomWind plugin - ; Adjusts wind strength. 0.0 = no wind, 1.0 = normal wind. Default is 1.0 - strength = 1.0 - - -[Cloud] - ; Enable this to generate classic particle clouds above the sim. - ; default is disabled - turn it on here - enabled = false - - ; Density of cloud cover 0.0 to 1.0 Defult 0.5 - density = 0.5 - - ; update interval for the cloud cover data returned by llCloud(). - ; default is 1000 - cloud_update_rate = 1000 - -[LightShare] - - ; This enables the transmission of Windlight scenes to supporting clients, such as the Meta7 viewer. - ; It has no ill effect on viewers which do not support server-side windlight settings. - ; Currently we only have support for MySQL databases. - enable_windlight = false; - -[Trees] - ; Enable this to allow the tree module to manage your sim trees, including growing, reproducing and dying - ; default is false - active_trees = false - - ; Density of tree population - tree_density = 1000.0 - - -[VectorRender] - - ; the font to use for rendering text (default: Arial) - ; font_name = "Arial" - - -[LL-Functions] - ; Set the following to true to allow administrator owned scripts to execute console commands - ; currently unused - ; AllowosConsoleCommand=false - - AllowGodFunctions = false - - ; Maximum number of llListen events we allow per script - ; Set this to 0 to have no limit imposed. - max_listens_per_script = 64 - - -[DataSnapshot] - ; The following set of configs pertains to search. - ; Set index_sims to true to enable search engines to index your searchable data - ; If false, no data will be exposed, DataSnapshot module will be off, and you can ignore the rest of these search-related configs - ; default is false - index_sims = false - - ; The variable data_exposure controls what the regions expose: - ; minimum: exposes only things explicitly marked for search - ; all: exposes everything - data_exposure = minimum - - ; If search is on, change this to your grid name; will be ignored for standalones - gridname = "OSGrid" - - ; Period between data snapshots, in seconds. 20 minutes, for starters, so that you see the initial changes fast. - ; Later, you may want to increase this to 3600 (1 hour) or more - default_snapshot_period = 1200 - - ; This will be created in bin, if it doesn't exist already. It will hold the data snapshots. - snapshot_cache_directory = "DataSnapshot" - - ; This semicolon-separated string serves to notify specific data services about the existence - ; of this sim. Uncomment if you want to index your data with this and/or other search providers. - ;data_services="http://metaverseink.com/cgi-bin/register.py" - - -[Economy] - ; These economy values get used in the BetaGridLikeMoneyModule. - This module is for demonstration only - - - ; Enables selling things for $0 - SellEnabled = "false" - - ; 45000 is the highest value that the sim could possibly report because of protocol constraints - ObjectCapacity = 45000 - - ; Money Unit fee to upload textures, animations etc - PriceUpload = 0 - - ; Money Unit fee to create groups - PriceGroupCreate = 0 - - ; We don't really know what the rest of these values do. These get sent to the client - ; These taken from Agni at a Public Telehub. Change at your own risk. - ObjectCount = 0 - PriceEnergyUnit = 100 - PriceObjectClaim = 10 - PricePublicObjectDecay = 4 - PricePublicObjectDelete = 4 - PriceParcelClaim = 1 - PriceParcelClaimFactor = 1 - - PriceRentLight = 5 - TeleportMinPrice = 2 - TeleportPriceExponent = 2 - EnergyEfficiency = 1 - PriceObjectRent = 1 - PriceObjectScaleFactor = 10 - PriceParcelRent = 1 - -[Git] -Enabled = true -RepoPath = "git" - -;How many seconds between the scheduled commits? -CommitInterval = 21600 - -;Disable all except the initial commit? -DisableNonEssentialCommits = false - -;Should we automatically commit when necessary to avoid objects never making it into the repo? -UseSafetyCommit = true - - -[SVN] - Enabled = false - Directory = SVNmodule\repo - URL = "svn://your.repo.here/" - Username = "user" - Password = "password" - ImportOnStartup = false - Autosave = false - AutoSavePeriod = 15 ; Number of minutes between autosave backups - - -[XEngine] - ; Enable this engine in this OpenSim instance - Enabled = true - - ; How many threads to keep alive even if nothing is happening - MinThreads = 2 - - ; How many threads to start at maximum load - MaxThreads = 100 - - ; Time a thread must be idle (in seconds) before it dies - IdleTimeout = 60 - - ; Thread priority ("Lowest", "BelowNormal", "Normal", "AboveNormal", "Highest") - Priority = "BelowNormal" - - ; Maximum number of events to queue for a script (excluding timers) - MaxScriptEventQueue = 300 - - ; Stack size per thread created - ThreadStackSize = 262144 - - ; Set this to true (the default) to load each script into a separate - ; AppDomain. Setting this to false will load all script assemblies into the - ; current AppDomain, which will reduce the per-script overhead at the - ; expense of reduced security and the inability to garbage collect the - ; script assemblies - AppDomainLoading = true - - ; Rate to poll for asynchronous command replies (ms) - ; currently unused - ;AsyncLLCommandLoopms = 50 - - ; Save the source of all compiled scripts - WriteScriptSourceToDebugFile = false - - ; Default language for scripts - DefaultCompileLanguage = lsl - - ; List of allowed languages (lsl,vb,js,cs) - ; AllowedCompilers=lsl,cs,js,vb. - ; *warning*, non lsl languages have access to static methods such as System.IO.File. Enable at your own risk. - AllowedCompilers=lsl - - ; Compile debug info (line numbers) into the script assemblies - CompileWithDebugInformation = true - - ; Allow the user of mod* functions. This allows a script to pass messages - ; to a region module via the modSendCommand() function - ; Default is false - AllowMODFunctions = false - - ; Allow the use of os* functions (some are dangerous) - AllowOSFunctions = false - - ; Allow the user of LightShare functions - AllowLightShareFunctions = false - - ; Threat level to allow, one of None, VeryLow, Low, Moderate, High, VeryHigh, Severe - OSFunctionThreatLevel = VeryLow - - ; Interval (s) between background save of script states - SaveInterval = 120 - - ; Interval (s) between maintenance runs (0 = disable) - MaintenanceInterval = 10 - - ; Time a script can spend in an event handler before it is interrupted - EventLimit = 30 - - ; If a script overruns it's event limit, kill the script? - KillTimedOutScripts = false - - ; Sets the multiplier for the scripting delays - ScriptDelayFactor = 1.0 - - ; The factor the 10 m distances llimits are multiplied by - ScriptDistanceLimitFactor = 1.0 - - ; Maximum length of notecard line read - ; Increasing this to large values potentially opens - ; up the system to malicious scripters - ; NotecardLineReadCharsMax = 255 - - ; Sensor settings - SensorMaxRange = 96.0 - SensorMaxResults = 16 - - ; OS Functions enable/disable - ; For each function, you can add one line, as shown - ; The default for all functions allows them if below threat level - - ; true allows the use of the function unconditionally - ; Allow_osSetRegionWaterHeight = true - - ; false disables the function completely - ; Allow_osSetRegionWaterHeight = false - - ; Comma separated list of UUIDS allows the function for that list of UUIDS - ; Allow_osSetRegionWaterHeight = 888760cb-a3cf-43ac-8ea4-8732fd3ee2bb - - ; You can also use script creators as the uuid - ; Creators_osSetRegionWaterHeight = , ... - - ; If both Allow_ and Creators_ are given, effective permissions - ; are the union of the two. - - ; Allow for llCreateLink and llBreakLink to work without asking for permission - ; only enable this in a trusted environment otherwise you may be subject to hijacking - ; AutomaticLinkPermission = false - - ; Disable underground movement of prims (default true); set to - ; false to allow script controlled underground positioning of - ; prims - ; DisableUndergroundMovement = true - - -[OpenGridProtocol] - ;These are the settings for the Open Grid Protocol.. the Agent Domain, Region Domain, you know.. - ;On/true or Off/false - ogp_enabled=false - - ;Name Prefix/suffix when using OGP - ogp_firstname_prefix="" - ogp_lastname_suffix="_EXTERNAL" - - -[Concierge] - ; Enable concierge module - ; Default is false - enabled = false - - ; name of the concierge - whoami = "jeeves" - - ; password for updating the welcome message templates via XmlRpc - password = SECRET - - ; regex specifying for which regions concierge service is desired; if - ; empty, then for all - regions = "^MeetingSpace-" - - ; for each region that matches the regions regexp you can provide - ; (optionally) a welcome template using format substitution: - ; {0} is replaced with the name of the avatar entering the region - ; {1} is replaced with the name of the region - ; {2} is replaced with the name of the concierge (whoami variable above) - - welcomes = /path/to/welcome/template/directory - - ; Concierge can send attendee lists to an event broker whenever an - ; avatar enters or leaves a concierged region. the URL is subject - ; to format substitution: - ; {0} is replaced with the region's name - ; {1} is replaced with the region's UUID - broker = "http://broker.place.com/{1}" - - -[RegionReady] - ; Enable this module to get notified once all items and scripts in the region have been completely loaded and compiled - ; default is false - enabled = false - - ; Channel on which to signal region readiness through a message - ; formatted as follows: "{server_startup|oar_file_load},{0|1},n,[oar error]" - ; - the first field indicating whether this is an initial server startup - ; - the second field is a number indicating whether the OAR file loaded ok (1 == ok, 0 == error) - ; - the third field is a number indicating how many scripts failed to compile - ; - "oar error" if supplied, provides the error message from the OAR load - channel_notify = -800 - - -[MRM] - ; Enables the Mini Region Modules Script Engine. - ; default is false - Enabled = false - - ; Runs MRM in a Security Sandbox - ; WARNING: DISABLING IS A SECURITY RISK. - Sandboxed = true - - ; The level sandbox to use, adjust at your OWN RISK. - ; Valid values are: - ; * FullTrust - ; * SkipVerification - ; * Execution - ; * Nothing - ; * LocalIntranet - ; * Internet - ; * Everything - SandboxLevel = "Internet" - - ; Only allow Region Owners to run MRMs - ; May represent a security risk if you disable this. - OwnerOnly = true - -[Hypergrid] - ; Keep it false for now. Making it true requires the use of a special client in order to access inventory - safemode = false - -[VivoxVoice] - ; The VivoxVoice module will allow you to provide voice on your - ; region(s). It uses the same voice technology as the LL grid and - ; works with recent LL clients (we have tested 1.22.9.110075, so - ; anything later ought to be fine as well). - ; - ; For this to work you need to obtain an admin account from Vivox - ; that allows you to create voice accounts and region channels. - - enabled = false - - ; vivox voice server - vivox_server = www.foobar.vivox.com - - ; vivox SIP URI - vivox_sip_uri = foobar.vivox.com - - ; vivox admin user name - vivox_admin_user = DeepThroat - - ; vivox admin password - vivox_admin_password = VoiceG4te - - ; channel type: "channel" or "positional" - ; - positional: spatial sound (default) - ; - channel: normal "conference call", no spatial sound - ;vivox_channel_type = positional - - ; channel characteristics (unless you know what you are doing, i'd - ; leave them as they are --- now you WILL muck around with them, - ; huh? sigh) - - ; channel distance model: - ; 0 - no attenuation - ; 1 - inverse distance attenuation - ; 2 - linear attenuation (default) - ; 3 - exponential attenuation - ;vivox_channel_distance_model = 2 - - ; channel mode: - ; - "open" (default) - ; - "lecture" - ; - "presentation" - ; - "auditorium" - ;vivox_channel_mode = "open" - - ; channel roll off: rate of attenuation - ; - a value between 1.0 and 4.0, default is 2.0 - ;vivox_channel_roll_off = 2.0 - - ; channel max range: distance at which channel is silent - ; - a value between 0 and 160, default is 80 - ;vivox_channel_max_range = 80 - - ; channel clamping distance: distance before attenuation applies - ; - a value between 0 and 160, default is 10 - ;vivox_channel_clamping_distance = 10 - -[FreeSwitchVoice] - ; In order for this to work you need a functioning FreeSWITCH PBX set up. - ; Configuration details at http://opensimulator.org/wiki/Freeswitch_Module - enabled = false - ; FreeSWITCH server is going to contact us and ask us all sorts of things - freeswitch_server_user = freeswitch - freeswitch_server_pass = password - freeswitch_api_prefix = /api - ; external IP address of your OpenSim voice enabled region - ; note: all regions running on same OpenSim.exe will be enabled - freeswitch_service_server = ip.address.of.your.sim - ; this should be the same port the region listens on - freeswitch_service_port = 9000 - freeswitch_realm = ip.address.of.freeswitch.server - freeswitch_sip_proxy = ip.address.of.freeswitch.server:5060 - ; STUN = Simple Traversal of UDP through NATs - ; See http://wiki.freeswitch.org/wiki/NAT_Traversal - ; stun.freeswitch.org is not guaranteed to be running so use it in production at your own risk - freeswitch_attempt_stun = false - freeswitch_stun_server = ip.address.of.stun.server - freeswitch_echo_server = ip.address.of.freeswitch.server - freeswitch_echo_port = 50505 - freeswitch_well_known_ip = ip.address.of.freeswitch.server - ; - ; Type the address of your http server here, hostname is allowed. This is provided so you can specify a hostname - ; This is used by client for account verification. By default, it's the same as the freeswitch service server. - ; - ; opensim_well_known_http_address = Address_Of_Your_SIM_HTTP_Server_Hostname_Allowed - ; - freeswitch_default_timeout = 5000 - freeswitch_subscribe_retry = 120 - ; freeswitch_password_reset_url = - -[Groups] - Enabled = false - - ; This is the current groups stub in Region.CoreModules.Avatar.Groups. All the other settings below only really - ; apply to the Flotsam/SimianGrid GroupsModule - Module = Default - - ; This module can use a PHP XmlRpc server from the Flotsam project at http://code.google.com/p/flotsam/ - ; or from the SimianGrid project at http://code.google.com/p/openmetaverse - ;Module = GroupsModule - - ; Enable Group Notices - ;NoticesEnabled = true - - ; This makes the Groups modules very chatty on the console. - DebugEnabled = false - - ; Specify which messaging module to use for groups messaging and if it's enabled - ;MessagingModule = GroupsMessagingModule - ;MessagingEnabled = true - - ; Service connectors to the Groups Service. Select one depending on whether you're using a Flotsam XmlRpc backend or a SimianGrid backend - - ; SimianGrid Service for Groups - ;ServicesConnectorModule = SimianGroupsServicesConnector - ;GroupsServerURI = http://mygridserver.com:82/Grid/ - - ; Flotsam XmlRpc Service for Groups - ;ServicesConnectorModule = XmlRpcGroupsServicesConnector - ;GroupsServerURI = http://yourxmlrpcserver.com/xmlrpc.php - - ; XmlRpc Security settings. These must match those set on your backend groups service. - ;XmlRpcServiceReadKey = 1234 - ;XmlRpcServiceWriteKey = 1234 - - ; Disables HTTP Keep-Alive for XmlRpcGroupsServicesConnector HTTP Requests, - ; this is a work around fora problem discovered on some Windows based region servers. - ; Only disable keep alive if you see a large number (dozens) of the following Exceptions: - ; System.Net.WebException: The request was aborted: The request was canceled. - ; XmlRpcDisableKeepAlive = false - - -[PacketPool] - ; Enables the experimental packet pool. Yes, we've been here before. - ;RecyclePackets = true; - ;RecycleDataBlocks = true; - - -[InterestManagement] - ; This section controls how state updates are prioritized for each client - ; Valid values are Time, Distance, SimpleAngularDistance, and FrontBack - UpdatePrioritizationScheme = FrontBack - ReprioritizationEnabled = true - ReprioritizationInterval = 2000.0 - RootReprioritizationDistance = 10.0 - ChildReprioritizationDistance = 20.0 - - -[WebStats] -; View region statistics via a web page -; See http://opensimulator.org/wiki/FAQ#Region_Statistics_on_a_Web_Page -; Use a web browser and type in the "Login URI" + "/SStats/" -; For example- http://127.0.0.1:9000/SStats/ -; enabled=false - -[LandManagement] -; DefaultAdministratorGroupUUID = ""; -; DefaultAdministratorParcelName = ""; - -[MediaOnAPrim] - ; Enable media on a prim facilities - Enabled = true; - -[MOTD] -Enabled = false -Message = "The MOTD module is working!" - - -;; -;; These are defaults that are overwritten below in [Architecture]. -;; These defaults allow OpenSim to work out of the box with -;; zero configuration -;; -[AssetService] - DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" - AssetLoaderArgs = "assets/AssetSets.xml" - - ; Disable this to prevent the default asset set from being inserted into the - ; asset store each time the region starts - AssetLoaderEnabled = true - -[GridService] - ;; default standalone, overridable in StandaloneCommon.ini - StorageProvider = "OpenSim.Data.Null.dll:NullRegionData" - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; The following is the configuration section for the new style services - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -[Architecture] - ; Choose exactly one and only one of the architectures below. - - Include-Standalone = "config-include/Standalone.ini" - ;Include-HGStandalone = "config-include/StandaloneHypergrid.ini" - ;Include-Grid = "config-include/Grid.ini" - ;Include-HGGrid = "config-include/GridHypergrid.ini" - ;Include-SimianGrid = "config-include/SimianGrid.ini" - ;Include-HyperSimianGrid = "config-include/HyperSimianGrid.ini" - - ; Then choose - ; config-include/StandaloneCommon.ini.example (if you're in standlone) OR - ; config-include/GridCommon.ini.example (if you're connected to a grid) - ; Copy to your own .ini there (without .example extension) and edit it - ; to customize your data - - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;; The below pulls in optional module config files - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -[Modules] - Include-modules = "addon-modules/*/config/*.ini" - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ENSURE [Architecture] and [Modules] Sections with their "includes" -;; are last to allow for overrides -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/bin/OpenSimDefaults.ini.example b/bin/OpenSimDefaults.ini.example new file mode 100644 index 0000000..ef8f73a --- /dev/null +++ b/bin/OpenSimDefaults.ini.example @@ -0,0 +1,1325 @@ +[Startup] + ; Set this to true if you want to log crashes to disk + ; this can be useful when submitting bug reports. + save_crashes = false + + ; Directory to save crashes to if above is enabled + ; (default is /opensimdir/crashes/*.txt or C:\opensim\crashes\*.txt) + crash_dir = "crashes" + + ; Place to create a PID file + ; PIDFile = "/tmp/my.pid" + + ; Http proxy support for llHTTPRequest and dynamic texture loading + ; Set HttpProxy to the URL for your proxy server if you would like + ; to proxy llHTTPRequests through a firewall + ; HttpProxy = "http://proxy.com" + ; Set HttpProxyExceptions to a list of regular expressions for + ; URLs that you don't want going through the proxy such as servers + ; inside your firewall, separate patterns with a ';' + ; HttpProxyExceptions = ".mydomain.com;localhost" + + startup_console_commands_file = "startup_commands.txt" + shutdown_console_commands_file = "shutdown_commands.txt" + + ; To run a script every few minutes, set the script filename here + ; timer_Script = "filename" + + ; ## + ; ## SYSTEM + ; ## + + ; Sets the method that OpenSim will use to fire asynchronous + ; events. Valid values are UnsafeQueueUserWorkItem, + ; QueueUserWorkItem, BeginInvoke, SmartThreadPool, and Thread. + ; SmartThreadPool is reported to work well on Mono/Linux, but + ; UnsafeQueueUserWorkItem has been benchmarked with better + ; performance on .NET/Windows + async_call_method = SmartThreadPool + + ; Max threads to allocate on the FireAndForget thread pool + ; when running with the SmartThreadPool option above + MaxPoolThreads = 15 + + ; ## + ; ## CLIENTS + ; ## + + ; Enables EventQueueGet Service. + EventQueue = true + + ; Set this to the DLL containing the client stack to use. + clientstack_plugin="OpenSim.Region.ClientStack.LindenUDP.dll" + + ; ## + ; ## REGIONS + ; ## + + ; Determine where OpenSimulator looks for the files which tell it which regions to server + ; Defaults to "filesystem" if this setting isn't present + region_info_source = "filesystem" + ; region_info_source = "web" + + ; Determines where the region XML files are stored if you are loading these from the filesystem. + ; Defaults to bin/Regions in your OpenSimulator installation directory + ; regionload_regionsdir="C:\somewhere\xmlfiles\" + + ; Determines the page from which regions xml is retrieved if you are loading these from the web + ; The XML here has the same format as it does on the filesystem (including the tag), + ; except that everything is also enclosed in a tag. + ; regionload_webserver_url = "http://example.com/regions.xml"; + + ; Draw objects on maptile. This step might take a long time if you've got a large number of + ; objects, so you can turn it off here if you'd like. + DrawPrimOnMapTile = true + ; Use terrain texture for maptiles if true, use shaded green if false + TextureOnMapTile = false + + ; Maximum total size, and maximum size where a prim can be physical + NonPhysicalPrimMax = 256 + PhysicalPrimMax = 10 ; (I think this was moved to the Regions.ini!) + ClampPrimSize = false + + ; Allow scripts to cross region boundaries. These are recompiled on the new region. + AllowScriptCrossing = false + + ; Allow compiled script binary code to cross region boundaries. + ; If you set this to "true", any region that can teleport to you can + ; inject ARBITRARY BINARY CODE into your system. Use at your own risk. + ; YOU HAVE BEEN WARNED!!! + TrustBinaries = false + + ; Combine all contiguous regions into one large megaregion + ; Order your regions from South to North, West to East in your regions.ini and then set this to true + ; Warning! Don't use this with regions that have existing content!, This will likely break them + CombineContiguousRegions = false + + ; If you have only one region in an instance, or to avoid the many bugs + ; that you can trigger in modules by restarting a region, set this to + ; true to make the entire instance exit instead of restarting the region. + ; This is meant to be used on systems where some external system like + ; Monit will restart any instance that exits, thereby making the shutdown + ; into a restart. + ;InworldRestartShutsDown = false + + ; ## + ; ## PRIM STORAGE + ; ## + + ; Persistence of changed objects happens during regular sweeps. The following control that behaviour to + ; prevent frequently changing objects from heavily loading the region data store. + ; If both of these values are set to zero then persistence of all changed objects will happen on every sweep. + ; + ; Objects will be considered for persistance in the next sweep when they have not changed for this number of seconds + MinimumTimeBeforePersistenceConsidered = 60 + ; Objects will always be considered for persistance in the next sweep if the first change occurred this number of seconds ago + MaximumTimeBeforePersistenceConsidered = 600 + + ; Should avatars in neighbor sims see objects in this sim? + see_into_this_sim_from_neighbor = true + + ; ## + ; ## PHYSICS + ; ## + + ; if you would like to allow prims to be physical and move by physics with the physical checkbox in the client set this to true. + physical_prim = true + + ; Select a mesher here. + ; + ; Meshmerizer properly handles complex prims by using triangle meshes. + ; Note that only the ODE physics engine currently deals with meshed prims in a satisfactory way + ; + ; ZeroMesher is faster but leaves the physics engine to model the mesh using the basic shapes that it supports + ; Usually this is only a box + + meshing = Meshmerizer + ;meshing = ZeroMesher + + ; Choose one of the physics engines below + ; OpenDynamicsEngine is by some distance the most developed physics engine + ; basicphysics effectively does not model physics at all, making all objects phantom + + physics = OpenDynamicsEngine + ;physics = basicphysics + ;physics = POS + ;physics = modified_BulletX + + ; ## + ; ## PERMISSIONS + ; ## + + ;permissionmodules = "DefaultPermissionsModule" + + ;If any of the specified permissions modules fail to load, quit? + SecurePermissionsLoading = true + + ; If set to false, then, in theory, the server never carries out permission checks (allowing anybody to copy + ; any item, etc. This may not yet be implemented uniformally. + ; If set to true, then all permissions checks are carried out + ; Default is false + serverside_object_permissions = false + + allow_grid_gods = false + + ; This allows somne control over permissions + ; please note that this still doesn't duplicate SL, and is not intended to + ;region_owner_is_god = true + ;region_manager_is_god = false + ;parcel_owner_is_god = true + + ; Control user types that are allowed to create new scripts + ; Only enforced if serviceside_object_permissions is true + ; + ; Current possible values are + ; all - anyone can create scripts (subject to normal permissions) + ; gods - only administrators can create scripts (as long as allow_grid_gods is true) + ; Default value is all + ; allowed_script_creators = all + + ; Control user types that are allowed to edit (save) scripts + ; Only enforced if serviceside_object_permissions is true + ; + ; Current possible values are + ; all - anyone can edit scripts (subject to normal permissions) + ; gods - only administrators can edit scripts (as long as allow_grid_gods is true) + ; Default value is all + ; allowed_script_editors = all + + ; ## + ; ## SCRIPT ENGINE + ; ## + + DefaultScriptEngine = "XEngine" + + ; ## + ; ## WORLD MAP + ; ## + + ;WorldMapModule = "WorldMap" + ;MapImageModule = "MapImageModule" + ; Set to false to not generate any maptiles + ;GenerateMaptiles = "true" + ; Refresh (in seconds) the map tile periodically + ;MaptileRefresh = 0 + ; If not generating maptiles, use this static texture asset ID + ;MaptileStaticUUID = "00000000-0000-0000-0000-000000000000" + + ; ## + ; ## EMAIL MODULE + ; ## + + ;emailmodule = DefaultEmailModule + + ; ## + ; ## ANIMATIONS + ; ## + + ; If enabled, enableFlySlow will change the primary fly state to + ; FLYSLOW, and the "always run" state will be the regular fly. + + enableflyslow = false + + ; PreJump is an additional animation state, but it probably + ; won't look right until the physics engine supports it + ; (i.e delays takeoff for a moment) + + ; This is commented so it will come on automatically once it's + ; supported. + + ; enableprejump = true + + ; Simulator Stats URI + ; Enable JSON simulator data by setting a URI name (case sensitive) + ; Stats_URI = "jsonSimStats" + + ; Make OpenSim start all regions woth logins disabled. They will need + ; to be enabled from the console if this is set + ; StartDisabled = false + + ; Image decoding. Use CSJ2K for layer boundary decoding if true, + ; OpenJPEG if false + ; UseCSJ2K = true + +[SMTP] + enabled=false + + ;enabled=true + ;internal_object_host=lsl.opensim.local + ;host_domain_header_from=127.0.0.1 + ;SMTP_SERVER_HOSTNAME=127.0.0.1 + ;SMTP_SERVER_PORT=25 + ;SMTP_SERVER_LOGIN=foo + ;SMTP_SERVER_PASSWORD=bar + +[Network] + ConsoleUser = "Test" + ConsolePass = "secret" + http_listener_port = 9000 + console_port = 0 + + ; ssl config: Experimental! The auto https config only really works definately on windows XP now + ; you need a Cert Request/Signed pair installed in the MY store with the CN specified below + ; you can use https on other platforms, but you'll need to configure the httpapi yourself for now + http_listener_ssl = false ; Also create a SSL server + http_listener_cn = "localhost" ; Use the cert with the common name + http_listener_sslport = 9001 ; Use this port for SSL connections + http_listener_ssl_cert = "" ; Currently unused, but will be used for OSHttpServer + + ; Hostname to use in llRequestURL/llRequestSecureURL + ; if not defined - default machine name is being used + ; (on Windows this mean NETBIOS name - useably only inside local network) + ; ExternalHostNameForLSL=127.0.0.1 + + ; What is reported as the "X-Secondlife-Shard" + ; Defaults to the user server url if not set + ; The old default is "OpenSim", set here for compatibility + shard = "OpenSim" + + ; What is reported as the "User-Agent" when using llHTTPRequest + ; Defaults to not sent if not set here. See the notes section in the wiki at + ; http://wiki.secondlife.com/wiki/LlHTTPRequest for comments on adding + ; " (Mozilla Compatible)" to the text where there are problems with a web server + ;user_agent = "OpenSim LSL (Mozilla Compatible)" + +[XMLRPC] + ; ## + ; ## Scripting XMLRPC mapper + ; ## + + ; If enabled, this will post an event, "xmlrpc_uri(string)" to the + ; script concurrently with the first remote_data event. + ; This will contain the fully qualified URI an external site needs + ; to use to send XMLRPC requests to that script + + ;XmlRpcRouterModule = "XmlRpcRouterModule" + ;XmlRpcPort = 20800 + +[ClientStack.LindenUDP] + ; Set this to true to process incoming packets asynchronously. Networking is + ; already separated from packet handling with a queue, so this will only + ; affect whether networking internals such as packet decoding and + ; acknowledgement accounting are done synchronously or asynchronously + ; + ;async_packet_handling = false + + ; The client socket receive buffer size determines how many + ; incoming requests we can process; the default on .NET is 8192 + ; which is about 2 4k-sized UDP datagrams. On mono this is + ; whatever the underlying operating system has as default; for + ; example, ubuntu 8.04 or SLES11 have about 111k, which is about + ; 27 4k-sized UDP datagrams (on linux platforms you can [as root] + ; do "sysctl net.core.rmem_default" to find out what your system + ; uses a default socket receive buffer size. + ; + ; client_socket_rcvbuf_size allows you to specify the receive + ; buffer size LLUDPServer should use. NOTE: this will be limited + ; by the system's settings for the maximum client receive buffer + ; size (on linux systems you can set that with "sysctl -w + ; net.core.rmem_max=X") + ; + ;client_socket_rcvbuf_size = 8388608 + + ; Maximum outbound bytes per second for a single scene. This can be used to + ; throttle total outbound UDP traffic for a simulator. The default value is + ; 0, meaning no throttling at the scene level. The example given here is + ; 20 megabits + ; + ;scene_throttle_max_bps = 2621440 + + ; Maximum bits per second to send to any single client. This will override + ; the user's viewer preference settings. The default value is 0, meaning no + ; aggregate throttling on clients (only per-category throttling). The + ; example given here is 1.5 megabits + ; + ;client_throttle_max_bps = 196608 + + ; Per-client bytes per second rates for the various throttle categories. + ; These are default values that will be overriden by clients + ; + ;resend_default = 12500 + ;land_default = 1000 + ;wind_default = 1000 + ;cloud_default = 1000 + ;task_default = 1000 + ;texture_default = 1000 + ;asset_default = 1000 + ;state_default = 1000 + + ; Per-client maximum burst rates in bytes per second for the various + ; throttle categories. These are default values that will be overriden by + ; clients + ; + ;resend_limit = 18750 + ;land_limit = 29750 + ;wind_limit = 18750 + ;cloud_limit = 18750 + ;task_limit = 18750 + ;texture_limit = 55750 + ;asset_limit = 27500 + ;state_limit = 37000 + + ; Configures how ObjectUpdates are aggregated. These numbers + ; do not literally mean how many updates will be put in each + ; packet that goes over the wire, as packets are + ; automatically split on a 1400 byte boundary. These control + ; the balance between responsiveness of interest list updates + ; and total throughput. Higher numbers will ensure more full- + ; sized packets and faster sending of data, but more delay in + ; updating interest lists + ; + ;PrimTerseUpdatesPerPacket = 25 + ;AvatarTerseUpdatesPerPacket = 10 + ;PrimFullUpdatesPerPacket = 100 + + ; TextureSendLimit determines how many packets will be put on + ; the outgoing queue each cycle. Like the settings above, this + ; is a balance between responsiveness to priority updates and + ; total throughput. Higher numbers will give a better + ; throughput at the cost of reduced responsiveness to client + ; priority changes or transfer aborts + ; + ;TextureSendLimit = 20 + + ; Quash and remove any light properties from attachments not on the + ; hands. This allows flashlights and lanterns to function, but kills + ; silly vanity "Facelights" dead. Sorry, head mounted miner's lamps + ; will also be affected. + ; + ;DisableFacelights = "false" + +[Chat] + ; Controls whether the chat module is enabled. Default is true. + enabled = true; + + ; Distance in meters that whispers should travel. Default is 10m + whisper_distance = 10 + + ; Distance in meters that ordinary chat should travel. Default is 30m + say_distance = 30 + + ; Distance in meters that shouts should travel. Default is 100m + shout_distance = 100 + + ; Append a prefix to the god avatar names appearing in chat whilst in god mode + ; admin_prefix = "@" + + +[Messaging] + ; Control which region module is used for instant messaging. + ; Default is InstantMessageModule (this is the name of the core IM module as well as the setting) + InstantMessageModule = InstantMessageModule + ; MessageTransferModule = MessageTransferModule + ; OfflineMessageModule = OfflineMessageModule + ; OfflineMessageURL = http://yourserver/Offline.php + ; MuteListModule = MuteListModule + ; MuteListURL = http://yourserver/Mute.php + + ; Control whether group messages are forwarded to offline users. Default is true. + ; ForwardOfflineGroupMessages = true + + +[ODEPhysicsSettings] + ;## + ;## World Settings + ;## + + ;Gravity. Feel like falling up? change world_gravityz to 9.8 instead of -9.8. m/s + world_gravityx = 0 + world_gravityy = 0 + world_gravityz = -9.8 + + ; World Step size. (warning these are dangerous. Changing these will probably cause your scene to explode dramatically) + ; reference: fps = (0.09375/ODE_STEPSIZE) * 1000; + world_stepsize = 0.020 + world_internal_steps_without_collisions = 10 + + ;World Space settings. Affects memory consumption vs Collider CPU time for avatar and physical prim + world_hashspace_size_low = -4 + world_hashSpace_size_high = 128 + + ;Dynamic space settings Affects memory consumption vs Collider CPU time for static prim + meters_in_small_space = 29.9 + small_hashspace_size_low = -4 + small_hashspace_size_high = 66 + + ; ## + ; ## Contact properties. (the stuff that happens when things come in contact with each other) + ; ## + + ; surface layer around geometries other geometries can sink into before generating a contact + world_contact_surface_layer = 0.001 + + ; Filtering collisions helps keep things stable physics wise, but sometimes + ; it can be overzealous. If you notice bouncing, chances are it's that. + filter_collisions = false + + ; Non Moving Terrain Contact (avatar isn't moving) + nm_terraincontact_friction = 255.0 + nm_terraincontact_bounce = 0.1 + nm_terraincontact_erp = 0.1025 + + ; Moving Terrain Contact (avatar is moving) + m_terraincontact_friction = 75.0 + m_terraincontact_bounce = 0.05 + m_terrainContact_erp = 0.05025 + + ; Moving Avatar to object Contact + m_avatarobjectcontact_friction = 75.0 + m_avatarobjectcontact_bounce = 0.1 + + ; Object to Object Contact and Non-Moving Avatar to object + objectcontact_friction = 250.0 + objectcontact_bounce = 0.2 + + ; ## + ; ## Avatar Control + ; ## + + ; PID Controller Settings. These affect the math that causes the avatar to reach the + ; desired velocity + ; See http://en.wikipedia.org/wiki/PID_controller + + av_pid_derivative_linux = 2200.0 + av_pid_proportional_linux = 900.0; + + av_pid_derivative_win = 2200.0 + av_pid_proportional_win = 900.0; + + ;girth of the avatar. Adds radius to the height also + av_capsule_radius = 0.37 + + ; Max force permissible to use to keep the avatar standing up straight + av_capsule_standup_tensor_win = 550000 + av_capsule_standup_tensor_linux = 550000 + + ; specifies if the capsule should be tilted (=true; old compatibility mode) + ; or straight up-and-down (=false; better and more consistent physics behavior) + av_capsule_tilted = false + + ; used to calculate mass of avatar. + ; float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH); + ; av_density * AVvolume; + av_density = 80 + + ; use this value to cut 52% of the height the sim gives us + av_height_fudge_factor = 0.52 + + ; Movement. Smaller is faster. + + ; speed of movement with Always Run off + av_movement_divisor_walk = 1.3 + + ; speed of movement with Always Run on + av_movement_divisor_run = 0.8 + + ; When the avatar flies, it will be moved up by this amount off the ground (in meters) + minimum_ground_flight_offset = 3.0 + + ; ## + ; ## Object options + ; ## + + ; used in the mass calculation. + geometry_default_density = 10.000006836 + + ; amount of ODE steps where object is non moving for ODE to automatically put it to sleep + body_frames_auto_disable = 20 + + ; used to control llMove2Target + body_pid_derivative = 35 + body_pid_gain = 25 + + ; maximum number of contact points to generate per collision + contacts_per_collision = 80 + + ; amount of time a geom/body will try to cross a region border before it gets disabled + geom_crossing_failures_before_outofbounds = 5 + + ; start throttling the object updates if object comes in contact with 3 or more other objects + geom_contactpoints_start_throttling = 3 + + ; send 1 update for every x updates below when throttled + geom_updates_before_throttled_update = 15 + + ; Used for llSetStatus. How rigid the object rotation is held on the axis specified + body_motor_joint_maxforce_tensor_linux = 5 + body_motor_joint_maxforce_tensor_win = 5 + + ; Maximum mass an object can be before it is clamped + maximum_mass_object = 10000.01 + + ; ## + ; ## Sculpted Prim settings + ; ## + + ; Do we want to mesh sculpted prim to collide like they look? + mesh_sculpted_prim = true + + ; number^2 non-physical level of detail of the sculpt texture. 32x32 - 1024 verticies + mesh_lod = 32 + + ; number^2 physical level of detail of the sculpt texture. 16x16 - 256 verticies + mesh_physical_lod = 16 + + ; ## + ; ## Physics logging settings - logfiles are saved to *.DIF files + ; ## + + ; default is false + ;physics_logging = true + ;; every n simulation iterations, the physics snapshot file is updated + ;physics_logging_interval = 50 + ;; append to existing physics logfile, or overwrite existing logfiles? + ;physics_logging_append_existing_logfile = true + + ; ## + ; ## Joint support + ; ## + + ; if you would like physics joints to be enabled through a special naming convention in the client, set this to true. + ; (see NINJA Physics documentation, http://opensimulator.org/wiki/NINJA_Physics) + ; default is false + ;use_NINJA_physics_joints = true + + ; ## + ; ## additional meshing options + ; ## + + ; physical collision mesh proxies are normally created for complex prim shapes, and collisions for simple boxes and + ; spheres are computed algorithmically. If you would rather have mesh proxies for simple prims, you can set this to + ; true. Note that this will increase memory usage and region startup time. Default is false. + ;force_simple_prim_meshing = true + + +[RemoteAdmin] + enabled = false + + ; Set this to a nonzero value to have remote admin use a different port + port = 0 + + ; This password is required to make any XMLRPC call (should be set as the "password" parameter) + access_password = unknown + + ; set this variable to true if you want the create_region XmlRpc + ; call to unconditionally enable voice on all parcels for a newly + ; created region [default: false] + create_region_enable_voice = false + + ; set this variable to false if you want the create_region XmlRpc + ; call to create all regions as private per default (can be + ; overridden in the XmlRpc call) [default: true] + create_region_public = false + + ; the create_region XmlRpc call uses region_file_template to generate + ; the file name of newly create regions (if they are created + ; persistent). the parameter available are: + ; {0} - X location + ; {1} - Y location + ; {2} - region UUID + ; {3} - region port + ; {4} - region name with " ", ":", "/" mapped to "_" + region_file_template = "{0}x{1}-{2}.ini" + + ; we can limit the number of regions that XmlRpcCreateRegion will + ; allow by setting this to a positive, non-0 number: as long as the + ; number of regions is below region_limits, XmlRpcCreateRegion will + ; succeed. setting region_limit to 0 disables the check. + ; default is 0 + ;region_limit = 0 + + ; enable only those methods you deem to be appropriate using a | delimited whitelist + ; for example, enabled_methods = admin_broadcast|admin_region_query|admin_save_oar|admin_save_xml + ; if this parameter is not specified but enabled = true, all methods will be available + enabled_methods = all + + ; specify the default appearance for an avatar created through the remote admin interface + ; This will only take effect is the file specified by the default_appearance setting below exists + ;default_male = Default Male + ;default_female = Default Female + + ; update appearance copies inventory items and wearables of default avatars. if this value is false + ; (default), just worn assets are copied to the Clothes folder; if true, all Clothes and Bodyparts + ; subfolders are copied. the receiver will wear the same items the default avatar did wear. + ;copy_folders = false + + ; path to default appearance XML file that specifies the look of the default avatars + ;default_appearance = default_appearance.xml + +[RestPlugins] + ; Change this to true to enable REST Plugins. This must be true if you wish to use + ; REST Region or REST Asset and Inventory Plugins + enabled = false + god_key = SECRET + prefix = /admin + + +[RestRegionPlugin] + ; Change this to true to enable the REST Region Plugin + enabled = false + + +[RestHandler] + ; Change this to true to enable the REST Asset and Inventory Plugin + enabled = false + authenticate = true + secured = true + extended-escape = true + realm = OpenSim REST + dump-asset = false + path-fill = true + dump-line-size = 32 + flush-on-error = true + + +; Uncomment the following for IRC bridge +; experimental, so if it breaks... keep both parts... yada yada +; also, not good error detection when it fails +;[IRC] + ;enabled = true ; you need to set this otherwise it won't connect + ;server = name.of.irc.server.on.the.net + ;; user password - only use this if the server requires one + ;password = mypass + ;nick = OpenSimBotNameProbablyMakeThisShorter + ;channel = #the_irc_channel_you_want_to_connect_to + ;user = "USER OpenSimBot 8 * :I'm an OpenSim to IRC bot" + ;port = 6667 + ;; channel to listen for configuration commands + ;commands_enabled = false + ;command_channel = 2777 + ;report_clients = true + ;; relay private chat connections + ;; relay_private_channels = true: will relay IRC chat from/to private in-world channels + ;; relay_private_channel_out -- channel to send messages out to the IRC bridge + ;; relay_private_channel_in -- channel to receive message from the IRC bridge + ;; relay_chat = false: IRC bridge will not relay normal chat + ;; access_password -- simple security device + ;; + ;; so, to just relay chat from an IRC channel to in-world region and vice versa: + ;; + ;; relay_private_channels = false + ;; relay_chat = true + ;; + ;; to relay chat only to/from private in-world channels: + ;; + ;; relay_chat = false + ;; relay_private_channels = true + ;; relay_private_channel_in = 2226 + ;; relay_private_channel_out = 2225 + ;; + ;; in this example, all chat coming in from IRC will be send out via + ;; in-world channel 2226, and all chat from in-world channel 2225 will + ;; be relayed to the IRC channel. + ;; + ;relay_private_channels = false + ;relay_private_channel_in = 2226 + ;relay_private_channel_out = 2225 + ;relay_chat = true + ;access_password = foobar + + ;;fallback_region = name of "default" region + ;;MSGformat fields : 0=botnick, 1=user, 2=region, 3=message + ;; must start with "PRIVMSG {0} : " or irc server will get upset + ;;for : : + ;;msgformat = "PRIVMSG {0} :<{1} in {2}>: {3}" + ;;for : - : + ;msgformat = "PRIVMSG {0} : {3} - {1} of {2}" + ;;for : - from : + ;;msgformat = "PRIVMSG {0} : {3} - from {1}" + + ;; exclude_list allows you to stop the IRC connector from announcing the + ;;arrival and departure of certain users. For example: admins, bots. + + ;exclude_list=User 1,User 2,User 3 + + +;[CMS] + ;enabled = true + ;channel = 345 + + +; Uncomment the following to control the progression of daytime +; in the Sim. The defaults are what is shown below +;[Sun] + ; number of wall clock hours for an opensim day. 24.0 would mean realtime + ;day_length = 4 + ; Year length in days + ;year_length = 60 + ; Day to Night Ratio + ;day_night_offset = 0.45 + ; send a Sun update every update_interval # of frames. A lower number will + ; make for smoother sun transition at the cost of network + ;update_interval = 100 + + +[Wind] + ; Enables the wind module. Default is true + enabled = true + + ; How often should wind be updated, as a function of world frames. Approximately 50 frames a second + wind_update_rate = 150 + + ; The Default Wind Plugin to load + wind_plugin = SimpleRandomWind + + ; These settings are specific to the ConfigurableWind plugin + ; To use ConfigurableWind as the default, simply change wind_plugin to ConfigurableWind and uncomment the following. + ; avg_strength = 5.0 + ; avg_direction = 0.0 + ; var_strength = 0.0 + ; var_direction = 0.0 + ; rate_change = 1.0 + + ; This setting is specific to the SimpleRandomWind plugin + ; Adjusts wind strength. 0.0 = no wind, 1.0 = normal wind. Default is 1.0 + strength = 1.0 + + +[Cloud] + ; Enable this to generate classic particle clouds above the sim. + ; default is disabled - turn it on here + enabled = false + + ; Density of cloud cover 0.0 to 1.0 Defult 0.5 + density = 0.5 + + ; update interval for the cloud cover data returned by llCloud(). + ; default is 1000 + cloud_update_rate = 1000 + +[LightShare] + + ; This enables the transmission of Windlight scenes to supporting clients, such as the Meta7 viewer. + ; It has no ill effect on viewers which do not support server-side windlight settings. + ; Currently we only have support for MySQL databases. + enable_windlight = false; + +[Trees] + ; Enable this to allow the tree module to manage your sim trees, including growing, reproducing and dying + ; default is false + active_trees = false + + ; Density of tree population + tree_density = 1000.0 + + +[VectorRender] + + ; the font to use for rendering text (default: Arial) + ; font_name = "Arial" + + +[LL-Functions] + ; Set the following to true to allow administrator owned scripts to execute console commands + ; currently unused + ; AllowosConsoleCommand=false + + AllowGodFunctions = false + + ; Maximum number of llListen events we allow per script + ; Set this to 0 to have no limit imposed. + max_listens_per_script = 64 + + +[DataSnapshot] + ; The following set of configs pertains to search. + ; Set index_sims to true to enable search engines to index your searchable data + ; If false, no data will be exposed, DataSnapshot module will be off, and you can ignore the rest of these search-related configs + ; default is false + index_sims = false + + ; The variable data_exposure controls what the regions expose: + ; minimum: exposes only things explicitly marked for search + ; all: exposes everything + data_exposure = minimum + + ; If search is on, change this to your grid name; will be ignored for standalones + gridname = "OSGrid" + + ; Period between data snapshots, in seconds. 20 minutes, for starters, so that you see the initial changes fast. + ; Later, you may want to increase this to 3600 (1 hour) or more + default_snapshot_period = 1200 + + ; This will be created in bin, if it doesn't exist already. It will hold the data snapshots. + snapshot_cache_directory = "DataSnapshot" + + ; This semicolon-separated string serves to notify specific data services about the existence + ; of this sim. Uncomment if you want to index your data with this and/or other search providers. + ;data_services="http://metaverseink.com/cgi-bin/register.py" + + +[Economy] + ; These economy values get used in the BetaGridLikeMoneyModule. - This module is for demonstration only - + + ; Enables selling things for $0 + SellEnabled = "false" + + ; 45000 is the highest value that the sim could possibly report because of protocol constraints + ObjectCapacity = 45000 + + ; Money Unit fee to upload textures, animations etc + PriceUpload = 0 + + ; Money Unit fee to create groups + PriceGroupCreate = 0 + + ; We don't really know what the rest of these values do. These get sent to the client + ; These taken from Agni at a Public Telehub. Change at your own risk. + ObjectCount = 0 + PriceEnergyUnit = 100 + PriceObjectClaim = 10 + PricePublicObjectDecay = 4 + PricePublicObjectDelete = 4 + PriceParcelClaim = 1 + PriceParcelClaimFactor = 1 + + PriceRentLight = 5 + TeleportMinPrice = 2 + TeleportPriceExponent = 2 + EnergyEfficiency = 1 + PriceObjectRent = 1 + PriceObjectScaleFactor = 10 + PriceParcelRent = 1 + +[Git] +Enabled = true +RepoPath = "git" + +;How many seconds between the scheduled commits? +CommitInterval = 21600 + +;Disable all except the initial commit? +DisableNonEssentialCommits = false + +;Should we automatically commit when necessary to avoid objects never making it into the repo? +UseSafetyCommit = true + + +[SVN] + Enabled = false + Directory = SVNmodule\repo + URL = "svn://your.repo.here/" + Username = "user" + Password = "password" + ImportOnStartup = false + Autosave = false + AutoSavePeriod = 15 ; Number of minutes between autosave backups + + +[XEngine] + ; Enable this engine in this OpenSim instance + Enabled = true + + ; How many threads to keep alive even if nothing is happening + MinThreads = 2 + + ; How many threads to start at maximum load + MaxThreads = 100 + + ; Time a thread must be idle (in seconds) before it dies + IdleTimeout = 60 + + ; Thread priority ("Lowest", "BelowNormal", "Normal", "AboveNormal", "Highest") + Priority = "BelowNormal" + + ; Maximum number of events to queue for a script (excluding timers) + MaxScriptEventQueue = 300 + + ; Stack size per thread created + ThreadStackSize = 262144 + + ; Set this to true (the default) to load each script into a separate + ; AppDomain. Setting this to false will load all script assemblies into the + ; current AppDomain, which will reduce the per-script overhead at the + ; expense of reduced security and the inability to garbage collect the + ; script assemblies + AppDomainLoading = true + + ; Rate to poll for asynchronous command replies (ms) + ; currently unused + ;AsyncLLCommandLoopms = 50 + + ; Save the source of all compiled scripts + WriteScriptSourceToDebugFile = false + + ; Default language for scripts + DefaultCompileLanguage = lsl + + ; List of allowed languages (lsl,vb,js,cs) + ; AllowedCompilers=lsl,cs,js,vb. + ; *warning*, non lsl languages have access to static methods such as System.IO.File. Enable at your own risk. + AllowedCompilers=lsl + + ; Compile debug info (line numbers) into the script assemblies + CompileWithDebugInformation = true + + ; Allow the user of mod* functions. This allows a script to pass messages + ; to a region module via the modSendCommand() function + ; Default is false + AllowMODFunctions = false + + ; Allow the use of os* functions (some are dangerous) + AllowOSFunctions = false + + ; Allow the user of LightShare functions + AllowLightShareFunctions = false + + ; Threat level to allow, one of None, VeryLow, Low, Moderate, High, VeryHigh, Severe + OSFunctionThreatLevel = VeryLow + + ; Interval (s) between background save of script states + SaveInterval = 120 + + ; Interval (s) between maintenance runs (0 = disable) + MaintenanceInterval = 10 + + ; Time a script can spend in an event handler before it is interrupted + EventLimit = 30 + + ; If a script overruns it's event limit, kill the script? + KillTimedOutScripts = false + + ; Sets the multiplier for the scripting delays + ScriptDelayFactor = 1.0 + + ; The factor the 10 m distances llimits are multiplied by + ScriptDistanceLimitFactor = 1.0 + + ; Maximum length of notecard line read + ; Increasing this to large values potentially opens + ; up the system to malicious scripters + ; NotecardLineReadCharsMax = 255 + + ; Sensor settings + SensorMaxRange = 96.0 + SensorMaxResults = 16 + + ; OS Functions enable/disable + ; For each function, you can add one line, as shown + ; The default for all functions allows them if below threat level + + ; true allows the use of the function unconditionally + ; Allow_osSetRegionWaterHeight = true + + ; false disables the function completely + ; Allow_osSetRegionWaterHeight = false + + ; Comma separated list of UUIDS allows the function for that list of UUIDS + ; Allow_osSetRegionWaterHeight = 888760cb-a3cf-43ac-8ea4-8732fd3ee2bb + + ; You can also use script creators as the uuid + ; Creators_osSetRegionWaterHeight = , ... + + ; If both Allow_ and Creators_ are given, effective permissions + ; are the union of the two. + + ; Allow for llCreateLink and llBreakLink to work without asking for permission + ; only enable this in a trusted environment otherwise you may be subject to hijacking + ; AutomaticLinkPermission = false + + ; Disable underground movement of prims (default true); set to + ; false to allow script controlled underground positioning of + ; prims + ; DisableUndergroundMovement = true + + +[OpenGridProtocol] + ;These are the settings for the Open Grid Protocol.. the Agent Domain, Region Domain, you know.. + ;On/true or Off/false + ogp_enabled=false + + ;Name Prefix/suffix when using OGP + ogp_firstname_prefix="" + ogp_lastname_suffix="_EXTERNAL" + + +[Concierge] + ; Enable concierge module + ; Default is false + enabled = false + + ; name of the concierge + whoami = "jeeves" + + ; password for updating the welcome message templates via XmlRpc + password = SECRET + + ; regex specifying for which regions concierge service is desired; if + ; empty, then for all + regions = "^MeetingSpace-" + + ; for each region that matches the regions regexp you can provide + ; (optionally) a welcome template using format substitution: + ; {0} is replaced with the name of the avatar entering the region + ; {1} is replaced with the name of the region + ; {2} is replaced with the name of the concierge (whoami variable above) + + welcomes = /path/to/welcome/template/directory + + ; Concierge can send attendee lists to an event broker whenever an + ; avatar enters or leaves a concierged region. the URL is subject + ; to format substitution: + ; {0} is replaced with the region's name + ; {1} is replaced with the region's UUID + broker = "http://broker.place.com/{1}" + + +[RegionReady] + ; Enable this module to get notified once all items and scripts in the region have been completely loaded and compiled + ; default is false + enabled = false + + ; Channel on which to signal region readiness through a message + ; formatted as follows: "{server_startup|oar_file_load},{0|1},n,[oar error]" + ; - the first field indicating whether this is an initial server startup + ; - the second field is a number indicating whether the OAR file loaded ok (1 == ok, 0 == error) + ; - the third field is a number indicating how many scripts failed to compile + ; - "oar error" if supplied, provides the error message from the OAR load + channel_notify = -800 + + +[MRM] + ; Enables the Mini Region Modules Script Engine. + ; default is false + Enabled = false + + ; Runs MRM in a Security Sandbox + ; WARNING: DISABLING IS A SECURITY RISK. + Sandboxed = true + + ; The level sandbox to use, adjust at your OWN RISK. + ; Valid values are: + ; * FullTrust + ; * SkipVerification + ; * Execution + ; * Nothing + ; * LocalIntranet + ; * Internet + ; * Everything + SandboxLevel = "Internet" + + ; Only allow Region Owners to run MRMs + ; May represent a security risk if you disable this. + OwnerOnly = true + +[Hypergrid] + ; Keep it false for now. Making it true requires the use of a special client in order to access inventory + safemode = false + +[VivoxVoice] + ; The VivoxVoice module will allow you to provide voice on your + ; region(s). It uses the same voice technology as the LL grid and + ; works with recent LL clients (we have tested 1.22.9.110075, so + ; anything later ought to be fine as well). + ; + ; For this to work you need to obtain an admin account from Vivox + ; that allows you to create voice accounts and region channels. + + enabled = false + + ; vivox voice server + vivox_server = www.foobar.vivox.com + + ; vivox SIP URI + vivox_sip_uri = foobar.vivox.com + + ; vivox admin user name + vivox_admin_user = DeepThroat + + ; vivox admin password + vivox_admin_password = VoiceG4te + + ; channel type: "channel" or "positional" + ; - positional: spatial sound (default) + ; - channel: normal "conference call", no spatial sound + ;vivox_channel_type = positional + + ; channel characteristics (unless you know what you are doing, i'd + ; leave them as they are --- now you WILL muck around with them, + ; huh? sigh) + + ; channel distance model: + ; 0 - no attenuation + ; 1 - inverse distance attenuation + ; 2 - linear attenuation (default) + ; 3 - exponential attenuation + ;vivox_channel_distance_model = 2 + + ; channel mode: + ; - "open" (default) + ; - "lecture" + ; - "presentation" + ; - "auditorium" + ;vivox_channel_mode = "open" + + ; channel roll off: rate of attenuation + ; - a value between 1.0 and 4.0, default is 2.0 + ;vivox_channel_roll_off = 2.0 + + ; channel max range: distance at which channel is silent + ; - a value between 0 and 160, default is 80 + ;vivox_channel_max_range = 80 + + ; channel clamping distance: distance before attenuation applies + ; - a value between 0 and 160, default is 10 + ;vivox_channel_clamping_distance = 10 + +[FreeSwitchVoice] + ; In order for this to work you need a functioning FreeSWITCH PBX set up. + ; Configuration details at http://opensimulator.org/wiki/Freeswitch_Module + enabled = false + ; FreeSWITCH server is going to contact us and ask us all sorts of things + freeswitch_server_user = freeswitch + freeswitch_server_pass = password + freeswitch_api_prefix = /api + ; external IP address of your OpenSim voice enabled region + ; note: all regions running on same OpenSim.exe will be enabled + freeswitch_service_server = ip.address.of.your.sim + ; this should be the same port the region listens on + freeswitch_service_port = 9000 + freeswitch_realm = ip.address.of.freeswitch.server + freeswitch_sip_proxy = ip.address.of.freeswitch.server:5060 + ; STUN = Simple Traversal of UDP through NATs + ; See http://wiki.freeswitch.org/wiki/NAT_Traversal + ; stun.freeswitch.org is not guaranteed to be running so use it in production at your own risk + freeswitch_attempt_stun = false + freeswitch_stun_server = ip.address.of.stun.server + freeswitch_echo_server = ip.address.of.freeswitch.server + freeswitch_echo_port = 50505 + freeswitch_well_known_ip = ip.address.of.freeswitch.server + ; + ; Type the address of your http server here, hostname is allowed. This is provided so you can specify a hostname + ; This is used by client for account verification. By default, it's the same as the freeswitch service server. + ; + ; opensim_well_known_http_address = Address_Of_Your_SIM_HTTP_Server_Hostname_Allowed + ; + freeswitch_default_timeout = 5000 + freeswitch_subscribe_retry = 120 + ; freeswitch_password_reset_url = + +[Groups] + Enabled = false + + ; This is the current groups stub in Region.CoreModules.Avatar.Groups. All the other settings below only really + ; apply to the Flotsam/SimianGrid GroupsModule + Module = Default + + ; This module can use a PHP XmlRpc server from the Flotsam project at http://code.google.com/p/flotsam/ + ; or from the SimianGrid project at http://code.google.com/p/openmetaverse + ;Module = GroupsModule + + ; Enable Group Notices + ;NoticesEnabled = true + + ; This makes the Groups modules very chatty on the console. + DebugEnabled = false + + ; Specify which messaging module to use for groups messaging and if it's enabled + ;MessagingModule = GroupsMessagingModule + ;MessagingEnabled = true + + ; Service connectors to the Groups Service. Select one depending on whether you're using a Flotsam XmlRpc backend or a SimianGrid backend + + ; SimianGrid Service for Groups + ;ServicesConnectorModule = SimianGroupsServicesConnector + ;GroupsServerURI = http://mygridserver.com:82/Grid/ + + ; Flotsam XmlRpc Service for Groups + ;ServicesConnectorModule = XmlRpcGroupsServicesConnector + ;GroupsServerURI = http://yourxmlrpcserver.com/xmlrpc.php + + ; XmlRpc Security settings. These must match those set on your backend groups service. + ;XmlRpcServiceReadKey = 1234 + ;XmlRpcServiceWriteKey = 1234 + + ; Disables HTTP Keep-Alive for XmlRpcGroupsServicesConnector HTTP Requests, + ; this is a work around fora problem discovered on some Windows based region servers. + ; Only disable keep alive if you see a large number (dozens) of the following Exceptions: + ; System.Net.WebException: The request was aborted: The request was canceled. + ; XmlRpcDisableKeepAlive = false + + +[PacketPool] + ; Enables the experimental packet pool. Yes, we've been here before. + ;RecyclePackets = true; + ;RecycleDataBlocks = true; + + +[InterestManagement] + ; This section controls how state updates are prioritized for each client + ; Valid values are Time, Distance, SimpleAngularDistance, and FrontBack + UpdatePrioritizationScheme = FrontBack + ReprioritizationEnabled = true + ReprioritizationInterval = 2000.0 + RootReprioritizationDistance = 10.0 + ChildReprioritizationDistance = 20.0 + + +[WebStats] +; View region statistics via a web page +; See http://opensimulator.org/wiki/FAQ#Region_Statistics_on_a_Web_Page +; Use a web browser and type in the "Login URI" + "/SStats/" +; For example- http://127.0.0.1:9000/SStats/ +; enabled=false + +[LandManagement] +; DefaultAdministratorGroupUUID = ""; +; DefaultAdministratorParcelName = ""; + +[MediaOnAPrim] + ; Enable media on a prim facilities + Enabled = true; + +[MOTD] +Enabled = false +Message = "The MOTD module is working!" + + +;; +;; These are defaults that are overwritten below in [Architecture]. +;; These defaults allow OpenSim to work out of the box with +;; zero configuration +;; +[AssetService] + DefaultAssetLoader = "OpenSim.Framework.AssetLoader.Filesystem.dll" + AssetLoaderArgs = "assets/AssetSets.xml" + + ; Disable this to prevent the default asset set from being inserted into the + ; asset store each time the region starts + AssetLoaderEnabled = true + +[GridService] + ;; default standalone, overridable in StandaloneCommon.ini + StorageProvider = "OpenSim.Data.Null.dll:NullRegionData" + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; The following is the configuration section for the new style services + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[Architecture] + ; Choose exactly one and only one of the architectures below. + + Include-Standalone = "config-include/Standalone.ini" + ;Include-HGStandalone = "config-include/StandaloneHypergrid.ini" + ;Include-Grid = "config-include/Grid.ini" + ;Include-HGGrid = "config-include/GridHypergrid.ini" + ;Include-SimianGrid = "config-include/SimianGrid.ini" + ;Include-HyperSimianGrid = "config-include/HyperSimianGrid.ini" + + ; Then choose + ; config-include/StandaloneCommon.ini.example (if you're in standlone) OR + ; config-include/GridCommon.ini.example (if you're connected to a grid) + ; Copy to your own .ini there (without .example extension) and edit it + ; to customize your data + + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; The below pulls in optional module config files + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +[Modules] + Include-modules = "addon-modules/*/config/*.ini" + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ENSURE [Architecture] and [Modules] Sections with their "includes" +;; are last to allow for overrides +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -- cgit v1.1 From 656e64b3ed4cf294b371739b315d7f603421788b Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 13 Sep 2010 23:22:25 +0100 Subject: Change the help message to point to copying OpenSimDefaults.ini.example. Provide a mostly empty OpenSim.ini.example --- OpenSim/Region/Application/ConfigurationLoader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index 9d6fef7..b76e85d 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -172,7 +172,7 @@ namespace OpenSim if (sources.Count == 0) { m_log.FatalFormat("[CONFIG]: Could not load any configuration"); - m_log.FatalFormat("[CONFIG]: Did you copy the OpenSim.ini.example file to OpenSim.ini?"); + m_log.FatalFormat("[CONFIG]: Did you copy the OpenSimDefaults.ini.example file to OpenSimDefaults.ini?"); Environment.Exit(1); } -- cgit v1.1 From ec305a48252b01e35a3ef4c2908fd229ccc7077d Mon Sep 17 00:00:00 2001 From: meta7 Date: Mon, 13 Sep 2010 17:43:45 -0700 Subject: LSL compatibility: Don't throw an exception if an invalid key is passed to llInstantMessage, instead shout about it and apply the usual delay. This now matches SL. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index a5b3cd0..e299f96 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3249,10 +3249,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID result; if (!UUID.TryParse(user, out result)) { - if (!m_debuggerSafe) - { - throw new Exception(String.Format("An invalid key of '{0} was passed to llInstantMessage", user)); - } + ShoutError("An invalid key was passed to llInstantMessage"); + ScriptSleep(2000); return; } -- cgit v1.1 From d299f8b55cb0e3848dbcbb941a5789d52459bc44 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 14 Sep 2010 19:41:53 +0200 Subject: Fix a small left over buglet and also add checking of the physics actor position on backup. This way, ant object that has been moved will be checked for ghost prims as soon as it is persisted. --- OpenSim/Region/Application/ConfigurationLoader.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index b76e85d..6e3d6af 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -100,7 +100,7 @@ namespace OpenSim if (masterFileName != String.Empty) { - if (File.Exists(masterFilePath) + if (File.Exists(masterFilePath)) { if (!sources.Contains(masterFilePath)) sources.Add(masterFilePath); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a952508..37630e0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1786,6 +1786,16 @@ namespace OpenSim.Region.Framework.Scenes // don't backup while it's selected or you're asking for changes mid stream. if (isTimeToPersist() || forcedBackup) { + if (m_rootPart.PhysActor != null && + (!m_rootPart.PhysActor.IsPhysical)) + { + if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition) + { + m_rootPart.PhysActor.Position = m_rootPart.GroupPosition; + m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; + m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); + } + } // m_log.DebugFormat( // "[SCENE]: Storing {0}, {1} in {2}", // Name, UUID, m_scene.RegionInfo.RegionName); -- cgit v1.1 From cc290abf7a2bd651205e8978a095cb83ffeddcf7 Mon Sep 17 00:00:00 2001 From: Melanie Thielker Date: Tue, 14 Sep 2010 22:13:44 +0200 Subject: Adjust the code for ghost prim removal to new information from Kitto --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 37630e0..e933e77 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1789,11 +1789,15 @@ namespace OpenSim.Region.Framework.Scenes if (m_rootPart.PhysActor != null && (!m_rootPart.PhysActor.IsPhysical)) { + // Possible ghost prim if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition) { - m_rootPart.PhysActor.Position = m_rootPart.GroupPosition; - m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; - m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); + foreach (SceneObjectPart part in Children.Values) + { + // Re-set physics actor positions and + // orientations + part.GroupPosition = m_rootPart.GroupPosition; + } } } // m_log.DebugFormat( -- cgit v1.1 From 2f41bc4ca738cd27730639c8cd49a154404c6a82 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 14 Sep 2010 22:14:08 +0100 Subject: Fix merge issues --- OpenSim/Region/Framework/Scenes/Scene.cs | 3 --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index abec699..12c7fea 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1348,15 +1348,12 @@ namespace OpenSim.Region.Framework.Scenes if (m_frame % m_update_presences == 0) m_sceneGraph.UpdatePresences(); -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/Scene.cs // Update SceneObjectGroups that have scheduled themselves for updates // Objects queue their updates onto all scene presences if (m_frame % m_update_objects == 0) m_sceneGraph.UpdateObjectGroups(); -======= // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) ->>>>>>> master:OpenSim/Region/Framework/Scenes/Scene.cs if (m_frame % m_update_coarse_locations == 0) { List coarseLocations; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index caf376b..ed92d86 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -4330,8 +4330,8 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju } m_log.InfoFormat( - "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})", - p, itemID, assetID, asset); + "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {3}", + p, itemID, asset); } catch (Exception e) { -- cgit v1.1 From e27f59cf422e4afef1b76af29d49f2c2770e3281 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 14 Sep 2010 22:15:16 +0100 Subject: reorder some code to avoid merge issues in the future --- OpenSim/Region/Framework/Scenes/Scene.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 12c7fea..ac2246c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1343,16 +1343,16 @@ namespace OpenSim.Region.Framework.Scenes // Check if any objects have reached their targets CheckAtTargets(); - // Run through all ScenePresences looking for updates - // Presence updates and queued object updates for each presence are sent to clients - if (m_frame % m_update_presences == 0) - m_sceneGraph.UpdatePresences(); - // Update SceneObjectGroups that have scheduled themselves for updates // Objects queue their updates onto all scene presences if (m_frame % m_update_objects == 0) m_sceneGraph.UpdateObjectGroups(); + // Run through all ScenePresences looking for updates + // Presence updates and queued object updates for each presence are sent to clients + if (m_frame % m_update_presences == 0) + m_sceneGraph.UpdatePresences(); + // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) if (m_frame % m_update_coarse_locations == 0) { -- cgit v1.1 From 7f7bbbb84a42d7fd984b637eaf7f1ce115d5fe19 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 14 Sep 2010 23:05:42 +0100 Subject: Fix the above --- OpenSim/Services/Connectors/Simulation/EstateDataService.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/OpenSim/Services/Connectors/Simulation/EstateDataService.cs b/OpenSim/Services/Connectors/Simulation/EstateDataService.cs index 2eedebb..8a8b46d 100644 --- a/OpenSim/Services/Connectors/Simulation/EstateDataService.cs +++ b/OpenSim/Services/Connectors/Simulation/EstateDataService.cs @@ -60,9 +60,8 @@ namespace OpenSim.Services.Connectors if (dbConfig != null) { dllName = dbConfig.GetString("StorageProvider", String.Empty); - connString = dbConfig.GetString("EstateConnectionString", String.Empty); - if (String.IsNullOrEmpty(connString)) - connString = dbConfig.GetString("ConnectionString", String.Empty); + connString = dbConfig.GetString("ConnectionString", String.Empty); + connString = dbConfig.GetString("EstateConnectionString", connString); } // Try reading the [EstateDataStore] section, if it exists @@ -70,7 +69,7 @@ namespace OpenSim.Services.Connectors if (estConfig != null) { dllName = estConfig.GetString("StorageProvider", dllName); - connString = dbConfig.GetString("ConnectionString", connString); + connString = estConfig.GetString("ConnectionString", connString); } // We tried, but this doesn't exist. We can't proceed -- cgit v1.1 From 1f74f013b23a8bbcc94d79aa57d35e1929b662d6 Mon Sep 17 00:00:00 2001 From: meta7 Date: Wed, 15 Sep 2010 07:59:28 -0700 Subject: Don't fart when deserializing a prim with no ParentGroup set yet --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 2de439b..a9a5c8a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -132,7 +132,11 @@ namespace OpenSim.Region.Framework.Scenes } HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; + if (m_part.ParentGroup != null) + { + m_part.ParentGroup.HasGroupChanged = true; + } + IList items = new List(Items.Values); Items.Clear(); -- cgit v1.1 From 77eb8ade8c030fd174bc24306e8c4adfd415b769 Mon Sep 17 00:00:00 2001 From: meta7 Date: Wed, 15 Sep 2010 08:08:29 -0700 Subject: Don't throw an exception if the authorizationservice is missing a serviceuri config entry. Not every authorization service will need a URI. --- .../Services/Connectors/Authorization/AuthorizationServiceConnector.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs b/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs index 4eb4bd2..8ae12ad 100644 --- a/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs @@ -77,7 +77,6 @@ namespace OpenSim.Services.Connectors if (serviceURI == String.Empty) { m_log.Error("[AUTHORIZATION CONNECTOR]: No Server URI named in section AuthorizationService"); - throw new Exception("Authorization connector init error"); } m_ServerURI = serviceURI; -- cgit v1.1 From 571693d7b6d9d7e138dbaf1e4dd958e453b8bd32 Mon Sep 17 00:00:00 2001 From: meta7 Date: Wed, 15 Sep 2010 08:16:38 -0700 Subject: Revert last commit --- .../Services/Connectors/Authorization/AuthorizationServiceConnector.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs b/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs index 8ae12ad..4eb4bd2 100644 --- a/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Authorization/AuthorizationServiceConnector.cs @@ -77,6 +77,7 @@ namespace OpenSim.Services.Connectors if (serviceURI == String.Empty) { m_log.Error("[AUTHORIZATION CONNECTOR]: No Server URI named in section AuthorizationService"); + throw new Exception("Authorization connector init error"); } m_ServerURI = serviceURI; -- cgit v1.1 From ec89dc99b705f86fb4ed2f984125c2196d8c6288 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Sep 2010 18:58:25 +0200 Subject: Some small bug fixes --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1 + OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 3411d18..142f5d8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Diagnostics; using System.Linq; using System.Threading; using System.Xml; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index ed92d86..8da9bdc 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -4330,7 +4330,7 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju } m_log.InfoFormat( - "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {3}", + "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}", p, itemID, asset); } catch (Exception e) -- cgit v1.1 From d50a072336f584f8e484160ba50042020f35d112 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Sep 2010 20:21:30 +0200 Subject: Suppress the strange "Result not Dictionary" messages that happen when a region queries for a nonexistent presence. --- OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs index 9f86078..f1c99ce 100644 --- a/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/Presence/PresenceServiceConnector.cs @@ -302,6 +302,9 @@ namespace OpenSim.Services.Connectors } else { + if (replyData["result"].ToString() == "null") + return null; + m_log.DebugFormat("[PRESENCE CONNECTOR]: Invalid reply (result not dictionary) received from presence server when querying for sessionID {0}", sessionID.ToString()); } } -- cgit v1.1 From 512ded6eb57019aed8aaa73d64b62d29450023cf Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Sep 2010 21:07:09 +0200 Subject: Catch a nullref --- OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 5378930..7c95658 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -334,7 +334,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (m_scene.InventoryService != null) item = m_scene.InventoryService.GetItem(item); - presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); + if (presence.Appearance != null) + presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); } return att.UUID; -- cgit v1.1 From a0c87b5af6bba104fe50de3006b5dd515a8eb833 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Sep 2010 23:12:32 +0200 Subject: JustinCC is evil. f7b28dd3 broke script persistence. This fixes it. --- .../Framework/Interfaces/IEntityInventory.cs | 9 +++++++ .../Region/Framework/Scenes/SceneObjectGroup.cs | 1 + OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 3 ++- .../Framework/Scenes/SceneObjectPartInventory.cs | 28 ++++++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 6289f7a..59ce090 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -58,6 +58,15 @@ namespace OpenSim.Region.Framework.Interfaces void ResetInventoryIDs(); /// + /// Reset parent object UUID for all the items in the prim's inventory. + /// + /// + /// If this method is called and there are inventory items, then we regard the inventory as having changed. + /// + /// Link number for the part + void ResetObjectID(); + + /// /// Change every item in this inventory to a new owner. /// /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 142f5d8..ab9cbd7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -696,6 +696,7 @@ namespace OpenSim.Region.Framework.Scenes if (node.Attributes["UUID"] != null) { UUID itemid = new UUID(node.Attributes["UUID"].Value); + m_log.DebugFormat("[SCRIPT STATE]: Adding state for oldID {0}", itemid); m_savedScriptState.Add(itemid, node.InnerXml); } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 5c4a2a3..40112c9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -514,7 +514,7 @@ namespace OpenSim.Region.Framework.Scenes // This is necessary so that TaskInventoryItem parent ids correctly reference the new uuid of this part if (Inventory != null) - Inventory.ResetInventoryIDs(); + Inventory.ResetObjectID(); } } @@ -2800,6 +2800,7 @@ namespace OpenSim.Region.Framework.Scenes UUID = UUID.Random(); LinkNum = linkNum; LocalId = 0; + Inventory.ResetInventoryIDs(); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index a9a5c8a..b205503 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -148,6 +148,34 @@ namespace OpenSim.Region.Framework.Scenes m_items.LockItemsForWrite(false); } + public void ResetObjectID() + { + m_items.LockItemsForWrite(true); + + if (Items.Count == 0) + { + m_items.LockItemsForWrite(false); + return; + } + + HasInventoryChanged = true; + if (m_part.ParentGroup != null) + { + m_part.ParentGroup.HasGroupChanged = true; + } + + IList items = new List(Items.Values); + Items.Clear(); + + foreach (TaskInventoryItem item in items) + { + item.ParentPartID = m_part.UUID; + item.ParentID = m_part.UUID; + Items.Add(item.ItemID, item); + } + m_items.LockItemsForWrite(false); + } + /// /// Change every item in this inventory to a new owner. /// -- cgit v1.1 From 1e4e978f7ff798292211c58ef07eee37cd76ef8e Mon Sep 17 00:00:00 2001 From: root Date: Thu, 16 Sep 2010 23:26:53 +0200 Subject: Removing debug --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index ab9cbd7..142f5d8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -696,7 +696,6 @@ namespace OpenSim.Region.Framework.Scenes if (node.Attributes["UUID"] != null) { UUID itemid = new UUID(node.Attributes["UUID"].Value); - m_log.DebugFormat("[SCRIPT STATE]: Adding state for oldID {0}", itemid); m_savedScriptState.Add(itemid, node.InnerXml); } } -- cgit v1.1 From 251f2444d049ed525ef41c4c4792ec446c53b973 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 17 Sep 2010 01:50:48 +0200 Subject: Revert "* Changed 11 calls for session info to the more optimized API method" This reverts commit 5dc9ea2f2487804d788b4b80d40d91bd792de4c2. Also makes online indicators and IM more robust --- .../CoreModules/Avatar/Friends/FriendsModule.cs | 103 ++++++++++++++------- .../Avatar/InstantMessage/MessageTransferModule.cs | 13 ++- .../Shared/Api/Implementation/LSL_Api.cs | 26 +++++- .../Connectors/SimianGrid/SimianProfiles.cs | 4 +- 4 files changed, 109 insertions(+), 37 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index a49e71e..21ed9dc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -317,7 +317,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends continue; UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, fromAgentID); - PresenceInfo presence = PresenceService.GetAgent(fromAgentID); + + PresenceInfo presence = null; + PresenceInfo[] presences = PresenceService.GetAgents(new string[] { fid }); + if (presences != null && presences.Length > 0) + presence = presences[0]; + if (presence != null) + im.offline = 0; im.fromAgentID = fromAgentID.Guid; im.fromAgentName = account.FirstName + " " + account.LastName; @@ -430,13 +436,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return; // The friend is not here [as root]. Let's forward. - PresenceInfo friendSession = PresenceService.GetAgent(friendID); - if (friendSession != null && friendSession.RegionID != UUID.Zero) // let's guard against sessions-gone-bad with the RegionID check + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad + { + friendSession = pinfo; + break; + } + + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + } } + + // Friend is not online. Ignore. } else { @@ -477,11 +496,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return; // The prospective friend is not here [as root]. Let's forward. - PresenceInfo friendSession = PresenceService.GetAgent(friendID); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + m_FriendsSimConnector.FriendshipOffered(region, agentID, friendID, im.message); + } } // If the prospective friend is not online, he'll get the message upon login. } @@ -508,12 +531,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } // The friend is not here - PresenceInfo friendSession = PresenceService.GetAgent(friendID); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID); - client.SendAgentOnline(new UUID[] { friendID }); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + m_FriendsSimConnector.FriendshipApproved(region, agentID, client.Name, friendID); + client.SendAgentOnline(new UUID[] { friendID }); + } } } @@ -532,14 +559,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (LocalFriendshipDenied(agentID, client.Name, friendID)) return; - PresenceInfo friendSession = PresenceService.GetAgent(friendID); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - if (region != null) - m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); - else - m_log.WarnFormat("[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + if (region != null) + m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); + else + m_log.WarnFormat("[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID); + } } } @@ -561,11 +592,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (LocalFriendshipTerminated(exfriendID)) return; - PresenceInfo friendSession = PresenceService.GetAgent(exfriendID); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { exfriendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + m_FriendsSimConnector.FriendshipTerminated(region, agentID, exfriendID); + } } } @@ -604,13 +639,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (LocalGrantRights(requester, target, myFlags, rights)) return; - PresenceInfo friendSession = PresenceService.GetAgent(target); - if (friendSession != null) + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - // TODO: You might want to send the delta to save the lookup - // on the other end!! - m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); + PresenceInfo friendSession = friendSessions[0]; + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + // TODO: You might want to send the delta to save the lookup + // on the other end!! + m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); + } } } } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index a6894ff..2a405ac 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -497,7 +497,18 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if (lookupAgent) { // Non-cached user agent lookup. - upd = PresenceService.GetAgent(toAgentID); + PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + if (presences != null && presences.Length > 0) + { + foreach (PresenceInfo p in presences) + { + if (p.RegionID != UUID.Zero) + { + upd = p; + break; + } + } + } if (upd != null) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e299f96..0dd1787 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4296,7 +4296,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } - pinfo = World.PresenceService.GetAgent(uuid); + PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); + if (pinfos != null && pinfos.Length > 0) + { + foreach (PresenceInfo p in pinfos) + { + if (p.RegionID != UUID.Zero) + { + pinfo = p; + } + } + } ce = new UserInfoCacheEntry(); ce.time = Util.EnvironmentTickCount(); @@ -4315,7 +4325,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) { - pinfo = World.PresenceService.GetAgent(uuid); + PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); + if (pinfos != null && pinfos.Length > 0) + { + foreach (PresenceInfo p in pinfos) + { + if (p.RegionID != UUID.Zero) + { + pinfo = p; + } + } + } + else + pinfo = null; ce.time = Util.EnvironmentTickCount(); ce.pinfo = pinfo; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs index b7e8538..0ef4974 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianProfiles.cs @@ -291,8 +291,8 @@ namespace OpenSim.Services.Connectors.SimianGrid // Check if the user is online if (client.Scene is Scene) { - OpenSim.Services.Interfaces.PresenceInfo presence = ((Scene)client.Scene).PresenceService.GetAgent(avatarID); - if (presence != null) + OpenSim.Services.Interfaces.PresenceInfo[] presences = ((Scene)client.Scene).PresenceService.GetAgents(new string[] { avatarID.ToString() }); + if (presences != null && presences.Length > 0) flags |= ProfileFlags.Online; } -- cgit v1.1 From 87a1e00f058f737628d50732ffbe46d5d6638779 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 17 Sep 2010 04:00:00 +0200 Subject: Remove the now unused partslock --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 3bc7834..f9bfffd 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -112,7 +112,6 @@ namespace OpenSim.Region.Framework.Scenes private long m_minPersistTime = 0; private Random m_rand; private bool m_suspendUpdates; - private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); private List m_linkedAvatars = new List(); public bool areUpdatesSuspended -- cgit v1.1 From 9f7aa7deef82fcace272002b06dad6c0929e999c Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 17 Sep 2010 21:40:49 +0100 Subject: Add LandServices to make landmarks work right in grids --- bin/config-include/Grid.ini | 1 + bin/config-include/GridHypergrid.ini | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index 1794573..5624a38 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -20,6 +20,7 @@ SimulationServices = "RemoteSimulationConnectorModule" EntityTransferModule = "BasicEntityTransferModule" InventoryAccessModule = "BasicInventoryAccessModule" + LandServices = "RemoteLandServicesConnector" LandServiceInConnector = true NeighbourServiceInConnector = true diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index cb9ead4..409b2a9 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -23,6 +23,7 @@ SimulationServices = "RemoteSimulationConnectorModule" EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" + LandServices = "RemoteLandServicesConnector" LandServiceInConnector = true NeighbourServiceInConnector = true -- cgit v1.1 From 3a760ad12bbb8fa3e48dde533744a1f2dd1c7871 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 17 Sep 2010 22:20:20 +0100 Subject: Overwrite the core version of the string parsing method with ours --- .../Shared/Api/Implementation/LSL_Api.cs | 97 +++++++++------------- 1 file changed, 37 insertions(+), 60 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cd8353f..caa39ba 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5949,6 +5949,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(5000); } + public LSL_List llParseString2List(string str, LSL_List separators, LSL_List in_spacers) + { + return ParseString2List(str, separators, in_spacers, false); + } + public LSL_Integer llOverMyLand(string id) { m_host.AddScriptLPS(1); @@ -8931,7 +8936,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // garbage generation. // - private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) + public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) { return ParseString2List(src, separators, spacers, true); } @@ -8952,19 +8957,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api int i, j; string d; - // All entries are initially valid - - for (int i = 0; i < mlen; i++) - active[i] = true; - - offset[mlen] = srclen; - - while (beginning < srclen) - { - - best = mlen; // as bad as it gets + m_host.AddScriptLPS(1); - // Scan for separators + /* + * Convert separator and spacer lists to C# strings. + * Also filter out null strings so we don't hang. + */ + for (i = 0; i < seplen; i ++) { + d = separray[i].ToString(); + if (d.Length > 0) { + delarray[dellen++] = d; + } + } + seplen = dellen; for (i = 0; i < spclen; i ++) { d = spcarray[i].ToString(); @@ -8999,45 +9004,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - // This is the normal exit from the scanning loop - - if (best == mlen) - { - // no markers were found on this pass - // so we're pretty much done - if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0)) - tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning))); - break; + /* + * Output source string starting at i through start of earliest delimeter. + */ + if (keepNulls || (earliestSrc > i)) { + outarray[outlen++] = src.Substring(i, earliestSrc - i); } - // Otherwise we just add the newly delimited token - // and recalculate where the search should continue. - if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) - tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); + /* + * If no delimeter found at or after i, we're done scanning. + */ + if (earliestDel < 0) break; - if (best < seplen) - { - beginning = offset[best] + (separray[best].ToString()).Length; - } - else - { - beginning = offset[best] + (spcarray[best - seplen].ToString()).Length; - string str = spcarray[best - seplen].ToString(); - if ((keepNulls) || ((!keepNulls) && (str.Length > 0))) - tokens.Add(new LSL_String(str)); + /* + * If delimeter was a spacer, output the spacer. + */ + if (earliestDel >= seplen) { + outarray[outlen++] = earliestStr; } - } - - // This an awkward an not very intuitive boundary case. If the - // last substring is a tokenizer, then there is an implied trailing - // null list entry. Hopefully the single comparison will not be too - // arduous. Alternatively the 'break' could be replced with a return - // but that's shabby programming. - if ((beginning == srclen) && (keepNulls)) - { - if (srclen != 0) - tokens.Add(new LSL_String("")); + /* + * Look at rest of src string following delimeter. + */ + i = earliestSrc + earliestStr.Length; } /* @@ -9049,19 +9038,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } return new LSL_List(outlist); } - - public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers) - { - m_host.AddScriptLPS(1); - return this.ParseString(src, separators, spacers, false); - } - - public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) - { - m_host.AddScriptLPS(1); - return this.ParseString(src, separators, spacers, true); - } - + public LSL_Integer llGetObjectPermMask(int mask) { m_host.AddScriptLPS(1); -- cgit v1.1 From 9cf8795ecf1a2f34f803babf318d9c1f394ee18b Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 19 Sep 2010 22:53:05 +0200 Subject: Fix a merge artefact that broke script state persistence in XAttachments --- OpenSim/Framework/TaskInventoryItem.cs | 8 +++----- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs index df5b936..883f61a 100644 --- a/OpenSim/Framework/TaskInventoryItem.cs +++ b/OpenSim/Framework/TaskInventoryItem.cs @@ -120,7 +120,7 @@ namespace OpenSim.Framework private UUID _permsGranter; private int _permsMask; private int _type = 0; - private UUID _oldID; + private UUID _oldID = UUID.Zero; private bool _ownerChanged = false; @@ -227,9 +227,6 @@ namespace OpenSim.Framework get { return _oldID; } - set { - _oldID = value; - } } public UUID LastOwnerID { @@ -348,7 +345,8 @@ namespace OpenSim.Framework /// The new part ID to which this item belongs public void ResetIDs(UUID partID) { - OldItemID = ItemID; + if (_oldID == UUID.Zero) + _oldID = ItemID; ItemID = UUID.Random(); ParentPartID = partID; ParentID = partID; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f9bfffd..41b0a42 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1029,7 +1029,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { - Dictionary pstates = parts[i].Inventory.GetScriptStates(); + Dictionary pstates = parts[i].Inventory.GetScriptStates(oldIDs); foreach (KeyValuePair kvp in pstates) states.Add(kvp.Key, kvp.Value); } -- cgit v1.1 From 7229bc4fbda804d41525356027269ca9a665b0bf Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 21 Sep 2010 02:08:55 +0200 Subject: Refactor script create permission into the perms module --- .../World/Permissions/PermissionsModule.cs | 28 ++++++++++++++++++---- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 10 -------- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index ecfd211..e46fb1c 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -1780,10 +1780,28 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - if ((int)InventoryType.LSL == invType) - if (m_allowedScriptCreators == UserSet.Administrators && !IsAdministrator(userID)) - return false; - + SceneObjectPart part = scene.GetSceneObjectPart(objectID); + ScenePresence p = scene.GetScenePresence(userID); + + if (part == null || p == null) + return false; + + if (!IsAdministrator(userID)) + { + if (part.OwnerID != userID) + { + // Group permissions + if ((part.GroupID == UUID.Zero) || (p.ControllingClient.GetGroupPowers(part.GroupID) == 0) || ((part.GroupMask & (uint)PermissionMask.Modify) == 0)) + return false; + } else { + if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + return false; + } + if ((int)InventoryType.LSL == invType) + if (m_allowedScriptCreators == UserSet.Administrators) + return false; + } + return true; } @@ -1980,4 +1998,4 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index ac82fda..18cfcbc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1532,16 +1532,6 @@ namespace OpenSim.Region.Framework.Scenes if (part == null) return; - if (part.OwnerID != remoteClient.AgentId) - { - // Group permissions - if ((part.GroupID == UUID.Zero) || (remoteClient.GetGroupPowers(part.GroupID) == 0) || ((part.GroupMask & (uint)PermissionMask.Modify) == 0)) - return; - } else { - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return; - } - if (!Permissions.CanCreateObjectInventory( itemBase.InvType, part.UUID, remoteClient.AgentId)) return; -- cgit v1.1 From 12f9b1df8c10f25b80f7cda7cccd7e3866653f49 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 21 Sep 2010 03:57:09 +0200 Subject: Fix a typo --- OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index e46fb1c..289741f 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -238,7 +238,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene.Permissions.OnEditNotecard += CanEditNotecard; //NOT YET IMPLEMENTED m_scene.Permissions.OnEditScript += CanEditScript; //NOT YET IMPLEMENTED - m_scene.Permissions.OnCreateObjectInventory += CanCreateObjectInventory; //NOT IMPLEMENTED HERE + m_scene.Permissions.OnCreateObjectInventory += CanCreateObjectInventory; m_scene.Permissions.OnEditObjectInventory += CanEditObjectInventory;//MAYBE FULLY IMPLEMENTED m_scene.Permissions.OnCopyObjectInventory += CanCopyObjectInventory; //NOT YET IMPLEMENTED m_scene.Permissions.OnDeleteObjectInventory += CanDeleteObjectInventory; //NOT YET IMPLEMENTED @@ -1780,8 +1780,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - ScenePresence p = scene.GetScenePresence(userID); + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + ScenePresence p = m_scene.GetScenePresence(userID); if (part == null || p == null) return false; -- cgit v1.1 From 33bd4fe789529e339db8954b29cf49ca7f7a0268 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 24 Sep 2010 22:00:51 +0200 Subject: When clearing the addin registry, respect a custom path --- OpenSim/Framework/PluginLoader.cs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/OpenSim/Framework/PluginLoader.cs b/OpenSim/Framework/PluginLoader.cs index 819cb7b..cc80943 100644 --- a/OpenSim/Framework/PluginLoader.cs +++ b/OpenSim/Framework/PluginLoader.cs @@ -244,13 +244,22 @@ namespace OpenSim.Framework // The Mono addin manager (in Mono.Addins.dll version 0.2.0.0) // occasionally seems to corrupt its addin cache // Hence, as a temporary solution we'll remove it before each startup + + string customDir = Environment.GetEnvironmentVariable ("MONO_ADDINS_REGISTRY"); + string v0 = "addin-db-000"; + string v1 = "addin-db-001"; + if (customDir != null && customDir != String.Empty) + { + v0 = Path.Combine(customDir, v0); + v1 = Path.Combine(customDir, v1); + } try { - if (Directory.Exists("addin-db-000")) - Directory.Delete("addin-db-000", true); + if (Directory.Exists(v0)) + Directory.Delete(v0, true); - if (Directory.Exists("addin-db-001")) - Directory.Delete("addin-db-001", true); + if (Directory.Exists(v1)) + Directory.Delete(v1, true); } catch (IOException) { -- cgit v1.1 From 1c1f3080526ed3e4845b4e98488d1d0c327dabb3 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 24 Sep 2010 23:48:52 +0200 Subject: if you can't edit a prim's inventory, you don't need to see the asset ids. Prevents stealing IDs of animations, sounds and textures from prim inventories. Prevents copybot from gathering the wearable UUIDs needed for pirating things from vendors. --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 8aa17a1..9359aea 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -975,6 +975,10 @@ namespace OpenSim.Region.Framework.Scenes // isn't available (such as drag from prim inventory to agent inventory) InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); + bool includeAssets = false; + if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId)) + includeAssets = true; + m_items.LockItemsForRead(true); foreach (TaskInventoryItem item in m_items.Values) @@ -1005,7 +1009,10 @@ namespace OpenSim.Region.Framework.Scenes invString.AddNameValueLine("group_id", item.GroupID.ToString()); invString.AddSectionEnd(); - invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + if (includeAssets) + invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + else + invString.AddNameValueLine("asset_id", UUID.Zero.ToString()); invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); -- cgit v1.1 From 83b16612ce13ee89f139df8fdc78ded14cb6a69e Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 25 Sep 2010 05:57:08 +0200 Subject: Experimental locking of taint processing --- OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs | 156 +++++++++++---------- 1 file changed, 80 insertions(+), 76 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs index ae63cfa..505d455 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODECharacter.cs @@ -143,6 +143,7 @@ namespace OpenSim.Region.Physics.OdePlugin // unique UUID of this character object public UUID m_uuid; public bool bad = false; + private Object m_syncRoot = new Object(); public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, CollisionLocker dode, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor) { @@ -1323,103 +1324,106 @@ Console.WriteLine("**** Create {2} Dicts: actor={0} name={1} height={3} ra public void ProcessTaints(float timestep) { - - if (m_tainted_isPhysical != m_isPhysical) + lock (m_syncRoot) { - if (m_tainted_isPhysical) - { - // Create avatar capsule and related ODE data - if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) - { - m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - " - + (Shell!=IntPtr.Zero ? "Shell ":"") - + (Body!=IntPtr.Zero ? "Body ":"") - + (Amotor!=IntPtr.Zero ? "Amotor ":"")); - } - AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor); - _parent_scene.AddCharacter(this); - } - else - { - _parent_scene.RemoveCharacter(this); - // destroy avatar capsule and related ODE data - if (Amotor != IntPtr.Zero) - { - // Kill the Amotor - d.JointDestroy(Amotor); - Amotor = IntPtr.Zero; - } - //kill the Geometry - _parent_scene.waitForSpaceUnlock(_parent_scene.space); - if (Body != IntPtr.Zero) + if (m_tainted_isPhysical != m_isPhysical) + { + if (m_tainted_isPhysical) { - //kill the body - d.BodyDestroy(Body); - Body = IntPtr.Zero; + // Create avatar capsule and related ODE data + if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) + { + m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - " + + (Shell!=IntPtr.Zero ? "Shell ":"") + + (Body!=IntPtr.Zero ? "Body ":"") + + (Amotor!=IntPtr.Zero ? "Amotor ":"")); + } + AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor); + _parent_scene.AddCharacter(this); } - - if(Shell != IntPtr.Zero) + else { - try + _parent_scene.RemoveCharacter(this); + // destroy avatar capsule and related ODE data + if (Amotor != IntPtr.Zero) { - d.GeomDestroy(Shell); + // Kill the Amotor + d.JointDestroy(Amotor); + Amotor = IntPtr.Zero; } - catch (System.AccessViolationException) + //kill the Geometry + _parent_scene.waitForSpaceUnlock(_parent_scene.space); + + if (Body != IntPtr.Zero) { - m_log.Error("[PHYSICS]: PrimGeom dead"); + //kill the body + d.BodyDestroy(Body); + Body = IntPtr.Zero; } - // Remove any old entries -//string tShell; -//_parent_scene.geom_name_map.TryGetValue(Shell, out tShell); -//Console.WriteLine("**** Remove {0}", tShell); - if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell); - if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell); - Shell = IntPtr.Zero; + if(Shell != IntPtr.Zero) + { + try + { + d.GeomDestroy(Shell); + } + catch (System.AccessViolationException) + { + m_log.Error("[PHYSICS]: PrimGeom dead"); + } + // Remove any old entries + //string tShell; + //_parent_scene.geom_name_map.TryGetValue(Shell, out tShell); + //Console.WriteLine("**** Remove {0}", tShell); + + if(_parent_scene.geom_name_map.ContainsKey(Shell)) _parent_scene.geom_name_map.Remove(Shell); + if(_parent_scene.actor_name_map.ContainsKey(Shell)) _parent_scene.actor_name_map.Remove(Shell); + Shell = IntPtr.Zero; + } } - } - m_isPhysical = m_tainted_isPhysical; - } + m_isPhysical = m_tainted_isPhysical; + } - if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH) - { - if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero) + if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH) { + if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero) + { - m_pidControllerActive = true; - // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate() - d.JointDestroy(Amotor); - float prevCapsule = CAPSULE_LENGTH; - CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; - //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); - d.BodyDestroy(Body); - AvatarGeomAndBodyCreation(_position.X, _position.Y, - _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); - Velocity = Vector3.Zero; - } - else - { - m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - " - + (Shell==IntPtr.Zero ? "Shell ":"") - + (Body==IntPtr.Zero ? "Body ":"") - + (Amotor==IntPtr.Zero ? "Amotor ":"")); + m_pidControllerActive = true; + // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate() + d.JointDestroy(Amotor); + float prevCapsule = CAPSULE_LENGTH; + CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; + //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); + d.BodyDestroy(Body); + AvatarGeomAndBodyCreation(_position.X, _position.Y, + _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); + Velocity = Vector3.Zero; + } + else + { + m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - " + + (Shell==IntPtr.Zero ? "Shell ":"") + + (Body==IntPtr.Zero ? "Body ":"") + + (Amotor==IntPtr.Zero ? "Amotor ":"")); + } } - } - if (!m_taintPosition.ApproxEquals(_position, 0.05f)) - { - if (Body != IntPtr.Zero) + if (!m_taintPosition.ApproxEquals(_position, 0.05f)) { - d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z); + if (Body != IntPtr.Zero) + { + d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z); - _position.X = m_taintPosition.X; - _position.Y = m_taintPosition.Y; - _position.Z = m_taintPosition.Z; + _position.X = m_taintPosition.X; + _position.Y = m_taintPosition.Y; + _position.Z = m_taintPosition.Z; + } } - } + } } internal void AddCollisionFrameTime(int p) -- cgit v1.1 From 6f689f591a295195cf8db3c37bcd382502d468d7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 26 Sep 2010 17:56:31 +0100 Subject: Merge Master --- .../Region/Physics/Manager/PhysicsPluginManager.cs | 4 ++-- OpenSim/Region/Physics/Manager/ZeroMesher.cs | 3 ++- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 13 +++++++++---- .../Region/Physics/OdePlugin/Tests/ODETestClass.cs | 6 +++++- .../Region/ScriptEngine/Interfaces/IScriptEngine.cs | 1 + .../Region/ScriptEngine/Shared/AssemblyResolver.cs | 7 ++++--- .../ScriptEngine/Shared/CodeTools/Compiler.cs | 5 +++-- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 21 ++++++++++++++------- bin/OpenSim.ini.example | 4 ++++ bin/OpenSimDefaults.ini | 6 ++++++ 10 files changed, 50 insertions(+), 20 deletions(-) diff --git a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs index 7130a3e..3763696 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsPluginManager.cs @@ -81,7 +81,7 @@ namespace OpenSim.Region.Physics.Manager if (_MeshPlugins.ContainsKey(meshEngineName)) { m_log.Info("[PHYSICS]: creating meshing engine " + meshEngineName); - meshEngine = _MeshPlugins[meshEngineName].GetMesher(); + meshEngine = _MeshPlugins[meshEngineName].GetMesher(config); } else { @@ -234,6 +234,6 @@ namespace OpenSim.Region.Physics.Manager public interface IMeshingPlugin { string GetName(); - IMesher GetMesher(); + IMesher GetMesher(IConfigSource config); } } diff --git a/OpenSim/Region/Physics/Manager/ZeroMesher.cs b/OpenSim/Region/Physics/Manager/ZeroMesher.cs index e6e75f9..ba19db6 100644 --- a/OpenSim/Region/Physics/Manager/ZeroMesher.cs +++ b/OpenSim/Region/Physics/Manager/ZeroMesher.cs @@ -28,6 +28,7 @@ using System; using OpenSim.Framework; using OpenMetaverse; +using Nini.Config; /* * This is the zero mesher. @@ -53,7 +54,7 @@ namespace OpenSim.Region.Physics.Manager return "ZeroMesher"; } - public IMesher GetMesher() + public IMesher GetMesher(IConfigSource config) { return new ZeroMesher(); } diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index fded95e..62f947c 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -35,6 +35,7 @@ using System.Drawing; using System.Drawing.Imaging; using PrimMesher; using log4net; +using Nini.Config; using System.Reflection; using System.IO; @@ -51,9 +52,9 @@ namespace OpenSim.Region.Physics.Meshing return "Meshmerizer"; } - public IMesher GetMesher() + public IMesher GetMesher(IConfigSource config) { - return new Meshmerizer(); + return new Meshmerizer(config); } } @@ -70,14 +71,18 @@ namespace OpenSim.Region.Physics.Meshing #endif private bool cacheSculptMaps = true; - private string decodedScultMapPath = "j2kDecodeCache"; + private string decodedScultMapPath = null; private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh private Dictionary m_uniqueMeshes = new Dictionary(); - public Meshmerizer() + public Meshmerizer(IConfigSource config) { + IConfig start_config = config.Configs["Startup"]; + + decodedScultMapPath = start_config.GetString("DecodedSculpMapPath","j2kDecodeCache"); + try { if (!Directory.Exists(decodedScultMapPath)) diff --git a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs index 69e2d03..ab8f8bf 100644 --- a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs +++ b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs @@ -48,6 +48,10 @@ namespace OpenSim.Region.Physics.OdePlugin [SetUp] public void Initialize() { + IConfigSource TopConfig = new IniConfigSource(); + IConfig config = TopConfig.AddConfig("Startup"); + config.Set("DecodedSculpMapPath","j2kDecodeCache"); + // Loading ODEPlugin cbt = new OdePlugin(); // Loading Zero Mesher @@ -55,7 +59,7 @@ namespace OpenSim.Region.Physics.OdePlugin // Getting Physics Scene ps = cbt.GetScene("test"); // Initializing Physics Scene. - ps.Initialise(imp.GetMesher(),null); + ps.Initialise(imp.GetMesher(TopConfig),null); float[] _heightmap = new float[(int)Constants.RegionSize * (int)Constants.RegionSize]; for (int i = 0; i < ((int)Constants.RegionSize * (int)Constants.RegionSize); i++) { diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs index 02d1511..581a9a9 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs @@ -82,6 +82,7 @@ namespace OpenSim.Region.ScriptEngine.Interfaces IConfig Config { get; } IConfigSource ConfigSource { get; } string ScriptEngineName { get; } + string ScriptEnginePath { get; } IScriptApi GetApi(UUID itemID, string name); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/AssemblyResolver.cs b/OpenSim/Region/ScriptEngine/Shared/AssemblyResolver.cs index ade1924..130e197 100644 --- a/OpenSim/Region/ScriptEngine/Shared/AssemblyResolver.cs +++ b/OpenSim/Region/ScriptEngine/Shared/AssemblyResolver.cs @@ -32,7 +32,7 @@ using System.Reflection; namespace OpenSim.Region.ScriptEngine.Shared { [Serializable] - public class AssemblyResolver + public class AssemblyResolver : MarshalByRefObject { public static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args) @@ -42,9 +42,10 @@ namespace OpenSim.Region.ScriptEngine.Shared AppDomain myDomain = (AppDomain)sender; string dirName = myDomain.FriendlyName; + string ScriptEnginesPath = myDomain.SetupInformation.PrivateBinPath; - string[] pathList = new string[] {"bin", "ScriptEngines", - Path.Combine("ScriptEngines", dirName)}; + string[] pathList = new string[] {"bin", ScriptEnginesPath, + Path.Combine(ScriptEnginesPath, dirName)}; string assemblyName = args.Name; if (assemblyName.IndexOf(",") != -1) diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index cd8c67e..49d6abe 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -72,7 +72,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools private Dictionary LanguageMapping = new Dictionary(StringComparer.CurrentCultureIgnoreCase); private string FilePrefix; - private string ScriptEnginesPath = "ScriptEngines"; + private string ScriptEnginesPath = null; // mapping between LSL and C# line/column numbers private ICodeConverter LSL_Converter; @@ -95,7 +95,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools public Compiler(IScriptEngine scriptEngine) { - m_scriptEngine = scriptEngine; + m_scriptEngine = scriptEngine;; + ScriptEnginesPath = scriptEngine.ScriptEnginePath; ReadConfig(); } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index e82d297..c0ec0e8 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -89,6 +89,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine private IXmlRpcRouter m_XmlRpcRouter; private int m_EventLimit; private bool m_KillTimedOutScripts; + private string m_ScriptEnginesPath = null; private static List m_ScriptEngines = new List(); @@ -224,6 +225,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine get { return m_ScriptConfig; } } + public string ScriptEnginePath + { + get { return m_ScriptEnginesPath; } + } + public IConfigSource ConfigSource { get { return m_ConfigSource; } @@ -281,6 +287,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; + m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); m_Prio = ThreadPriority.BelowNormal; switch (priority) @@ -478,7 +485,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine return 0; } - public Type ReplaceableInterface + public Type ReplaceableInterface { get { return null; } } @@ -1040,7 +1047,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine startInfo.IdleTimeout = idleTimeout*1000; // convert to seconds as stated in .ini startInfo.MaxWorkerThreads = maxThreads; startInfo.MinWorkerThreads = minThreads; - startInfo.ThreadPriority = threadPriority; + startInfo.ThreadPriority = threadPriority;; startInfo.StackSize = stackSize; startInfo.StartSuspended = true; @@ -1186,8 +1193,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (!(sender is System.AppDomain)) return null; - string[] pathList = new string[] {"bin", "ScriptEngines", - Path.Combine("ScriptEngines", + string[] pathList = new string[] {"bin", m_ScriptEnginesPath, + Path.Combine(m_ScriptEnginesPath, m_Scene.RegionInfo.RegionID.ToString())}; string assemblyName = args.Name; @@ -1564,7 +1571,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine string fn = assemE.GetAttribute("Filename"); string base64 = assemE.InnerText; - string path = Path.Combine("ScriptEngines", World.RegionInfo.RegionID.ToString()); + string path = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString()); path = Path.Combine(path, fn); if (!File.Exists(path)) @@ -1604,7 +1611,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine } } - string statepath = Path.Combine("ScriptEngines", World.RegionInfo.RegionID.ToString()); + string statepath = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString()); statepath = Path.Combine(statepath, itemID.ToString() + ".state"); try @@ -1630,7 +1637,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine { XmlElement mapE = (XmlElement)mapL[0]; - string mappath = Path.Combine("ScriptEngines", World.RegionInfo.RegionID.ToString()); + string mappath = Path.Combine(m_ScriptEnginesPath, World.RegionInfo.RegionID.ToString()); mappath = Path.Combine(mappath, mapE.GetAttribute("Filename")); try diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 109e0aa..2b78014 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -546,6 +546,10 @@ ;; prims ; DisableUndergroundMovement = true + ;; Path to script engine assemblies + ;; Default is ./bin/ScriptEngines + ; ScriptEnginesPath = "ScriptEngines" + [MRM] ;; Enables the Mini Region Modules Script Engine. ;; default is false diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index e78f25b..4c579c9 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -135,6 +135,10 @@ meshing = Meshmerizer ;meshing = ZeroMesher + + ;; Path to decoded sculpty maps + ;; Defaults to "j2kDecodeCache + ;DecodedSculpMapPath = "j2kDecodeCache" ; Choose one of the physics engines below ; OpenDynamicsEngine is by some distance the most developed physics engine @@ -1000,6 +1004,8 @@ ; prims ; DisableUndergroundMovement = true + ;; Path to script assemblies + ; ScriptEnginesPath = "ScriptEngines" [OpenGridProtocol] ;These are the settings for the Open Grid Protocol.. the Agent Domain, Region Domain, you know.. -- cgit v1.1 From aecac9bba9b89682f53ebde1e182ad04f5b2dc99 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 26 Sep 2010 18:05:55 +0100 Subject: Typo fixes --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 12 ++++++------ OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 62f947c..20a5bb4 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -71,7 +71,7 @@ namespace OpenSim.Region.Physics.Meshing #endif private bool cacheSculptMaps = true; - private string decodedScultMapPath = null; + private string decodedSculptMapPath = null; private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh @@ -81,16 +81,16 @@ namespace OpenSim.Region.Physics.Meshing { IConfig start_config = config.Configs["Startup"]; - decodedScultMapPath = start_config.GetString("DecodedSculpMapPath","j2kDecodeCache"); + decodedSculptMapPath = start_config.GetString("DecodedSculptMapPath","j2kDecodeCache"); try { - if (!Directory.Exists(decodedScultMapPath)) - Directory.CreateDirectory(decodedScultMapPath); + if (!Directory.Exists(decodedSculptMapPath)) + Directory.CreateDirectory(decodedSculptMapPath); } catch (Exception e) { - m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedScultMapPath, e.Message); + m_log.WarnFormat("[SCULPT]: Unable to create {0} directory: ", decodedSculptMapPath, e.Message); } } @@ -265,7 +265,7 @@ namespace OpenSim.Region.Physics.Meshing { if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero) { - decodedSculptFileName = System.IO.Path.Combine(decodedScultMapPath, "smap_" + primShape.SculptTexture.ToString()); + decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString()); try { if (File.Exists(decodedSculptFileName)) diff --git a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs index ab8f8bf..a7f8baa 100644 --- a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs +++ b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs @@ -50,7 +50,7 @@ namespace OpenSim.Region.Physics.OdePlugin { IConfigSource TopConfig = new IniConfigSource(); IConfig config = TopConfig.AddConfig("Startup"); - config.Set("DecodedSculpMapPath","j2kDecodeCache"); + config.Set("DecodedSculptMapPath","j2kDecodeCache"); // Loading ODEPlugin cbt = new OdePlugin(); -- cgit v1.1 From 34e8bf45b6f44c7e9c1e8fb824215214f6e9244c Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 27 Sep 2010 00:29:27 +0100 Subject: Restrict inventory items added in a transaction to folder belonging to the connected client. --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 18cfcbc..9a33993 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -834,6 +834,12 @@ namespace OpenSim.Region.Framework.Scenes if (!Permissions.CanCreateUserInventory(invType, remoteClient.AgentId)) return; + InventoryFolderBase f = new InventoryFolderBase(folderID, remoteClient.AgentId); + InventoryFolderBase folder = InventoryService.GetFolder(f); + + if (folder == null || folder.Owner != remoteClient.AgentId) + return; + if (transactionID == UUID.Zero) { ScenePresence presence; -- cgit v1.1 From 41051b3cc68f1b7cf92538bd2affbf4c838f1a1d Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 27 Sep 2010 02:11:55 +0100 Subject: Prevent setting arbitrary groups on your objects. --- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 5ef14bf..b61aed5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -590,6 +590,9 @@ namespace OpenSim.Region.Framework.Scenes protected internal void HandleObjectGroupUpdate( IClientAPI remoteClient, UUID GroupID, uint objectLocalID, UUID Garbage) { + if (!remoteClient.IsGroupMember(GroupID)) + return; + SceneObjectGroup group = GetGroupByPrim(objectLocalID); if (group != null) { -- cgit v1.1 From 841c84831fedcfa40e0b0fa9c99990f6754591fa Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 27 Sep 2010 19:34:16 +0200 Subject: Try to prevent threading issues in SP.SetAppearance by locking it --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 85 +++++++++++++----------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index b3df1ea..ec3f004 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -229,6 +229,8 @@ namespace OpenSim.Region.Framework.Scenes private const int NumMovementsBetweenRayCast = 5; private List m_lastColliders = new List(); + private object m_syncRoot = new Object(); + private bool CameraConstraintActive; //private int m_moveToPositionStateStatus; //***************************************************** @@ -2861,66 +2863,69 @@ namespace OpenSim.Region.Framework.Scenes /// public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams) { - if (m_physicsActor != null) + lock (m_syncRoot) { - if (!IsChildAgent) + if (m_physicsActor != null) { - // This may seem like it's redundant, remove the avatar from the physics scene - // just to add it back again, but it saves us from having to update - // 3 variables 10 times a second. - bool flyingTemp = m_physicsActor.Flying; - RemoveFromPhysicalScene(); - //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor); + if (!IsChildAgent) + { + // This may seem like it's redundant, remove the avatar from the physics scene + // just to add it back again, but it saves us from having to update + // 3 variables 10 times a second. + bool flyingTemp = m_physicsActor.Flying; + RemoveFromPhysicalScene(); + //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor); - //PhysicsActor = null; + //PhysicsActor = null; - AddToPhysicalScene(flyingTemp); + AddToPhysicalScene(flyingTemp); + } } - } - #region Bake Cache Check + #region Bake Cache Check - if (textureEntry != null) - { - for (int i = 0; i < BAKE_INDICES.Length; i++) + if (textureEntry != null) { - int j = BAKE_INDICES[i]; - Primitive.TextureEntryFace face = textureEntry.FaceTextures[j]; - - if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) + for (int i = 0; i < BAKE_INDICES.Length; i++) { - if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) + int j = BAKE_INDICES[i]; + Primitive.TextureEntryFace face = textureEntry.FaceTextures[j]; + + if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE) { - m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name); - this.ControllingClient.SendRebakeAvatarTextures(face.TextureID); + if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) + { + m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name); + this.ControllingClient.SendRebakeAvatarTextures(face.TextureID); + } } } - } - } + } - #endregion Bake Cache Check + #endregion Bake Cache Check - m_appearance.SetAppearance(textureEntry, visualParams); - if (m_appearance.AvatarHeight > 0) - SetHeight(m_appearance.AvatarHeight); + m_appearance.SetAppearance(textureEntry, visualParams); + if (m_appearance.AvatarHeight > 0) + SetHeight(m_appearance.AvatarHeight); - // This is not needed, because only the transient data changed - //AvatarData adata = new AvatarData(m_appearance); - //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); + // This is not needed, because only the transient data changed + //AvatarData adata = new AvatarData(m_appearance); + //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata); - SendAppearanceToAllOtherAgents(); - if (!m_startAnimationSet) - { - Animator.UpdateMovementAnimations(); - m_startAnimationSet = true; - } + SendAppearanceToAllOtherAgents(); + if (!m_startAnimationSet) + { + Animator.UpdateMovementAnimations(); + m_startAnimationSet = true; + } - Vector3 pos = m_pos; - pos.Z += m_appearance.HipOffset; + Vector3 pos = m_pos; + pos.Z += m_appearance.HipOffset; - m_controllingClient.SendAvatarDataImmediate(this); + m_controllingClient.SendAvatarDataImmediate(this); + } } public void SetWearable(int wearableId, AvatarWearable wearable) -- cgit v1.1 From 3d75e9addd50b9416a221282d7e24fc44ebda3a8 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 28 Sep 2010 02:22:32 +0200 Subject: Lock the iteration over the inventory items when saving script states --- OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index c88dda6..522f75e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -1241,6 +1241,7 @@ namespace OpenSim.Region.Framework.Scenes if (engines == null) // No engine at all return ret; + Items.LockItemsForRead(true); foreach (TaskInventoryItem item in m_items.Values) { if (item.InvType == (int)InventoryType.LSL) @@ -1268,6 +1269,7 @@ namespace OpenSim.Region.Framework.Scenes } } } + Items.LockItemsForRead(false); return ret; } -- cgit v1.1 From 9522881404e9496cb68d97fae537d60bbfa5233b Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 30 Sep 2010 02:46:47 +0200 Subject: Fix a potential key collision --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a9502ed..a00a7c4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1035,7 +1035,7 @@ namespace OpenSim.Region.Framework.Scenes { Dictionary pstates = parts[i].Inventory.GetScriptStates(oldIDs); foreach (KeyValuePair kvp in pstates) - states.Add(kvp.Key, kvp.Value); + states[kvp.Key] = kvp.Value; } if (states.Count > 0) -- cgit v1.1 From ac7a4a7d38454c9c2263b54f847b28a5a7567b83 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 30 Sep 2010 02:47:07 +0200 Subject: Fix an inventory fetch issue --- OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 4d97db7..21c36d3 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -515,6 +515,9 @@ namespace OpenSim.Region.Framework.Scenes public void HandleFetchInventoryDescendents(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder) { + if (folderID == UUID.Zero) + return; + // FIXME MAYBE: We're not handling sortOrder! // TODO: This code for looking in the folder for the library should be folded somewhere else -- cgit v1.1 From 7ad1b60ecaa64ae693be48df9a32cb93bb22e76f Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 30 Sep 2010 20:01:55 +0200 Subject: Enforce region agent limit as set in estate tools --- OpenSim/Region/Framework/Scenes/Scene.cs | 8 ++++++++ OpenSim/Region/Framework/Scenes/SceneGraph.cs | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 240d33c..e835281 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3856,6 +3856,14 @@ namespace OpenSim.Region.Framework.Scenes // We have to wait until the viewer contacts this region after receiving EAC. // That calls AddNewClient, which finally creates the ScenePresence + int num = m_sceneGraph.GetNumberOfScenePresences(); + + if (num >= RegionInfo.RegionSettings.AgentLimit) + { + if (!Permissions.IsAdministrator(cAgentData.AgentID)) + return false; + } + ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) { diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index b61aed5..1163ebf 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -826,6 +826,11 @@ namespace OpenSim.Region.Framework.Scenes return m_scenePresenceArray; } + public int GetNumberOfScenePresences() + { + return m_scenePresenceArray.Count; + } + /// /// Request a scene presence by UUID. Fast, indexed lookup. /// -- cgit v1.1 From 9f7f266f583cfd47f3c66aa56b0ba26e634e8d91 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 2 Oct 2010 00:18:52 +0200 Subject: Replace CalculateMass with a better, contributed version --- OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 471 +++++++++++++------------- 1 file changed, 228 insertions(+), 243 deletions(-) diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 2105be1..793774a 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -884,300 +884,285 @@ namespace OpenSim.Region.Physics.OdePlugin private float CalculateMass() { - float volume = 0; - - // No material is passed to the physics engines yet.. soo.. - // we're using the m_density constant in the class definition + float volume = _size.X * _size.Y * _size.Z; // default + float tmp; float returnMass = 0; - + float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; + float hollowVolume = hollowAmount * hollowAmount; + switch (_pbs.ProfileShape) { case ProfileShape.Square: - // Profile Volume + // default box + + if (_pbs.PathCurve == (byte)Extrusion.Straight) + { + if (hollowAmount > 0.0) + { + switch (_pbs.HollowShape) + { + case HollowShape.Square: + case HollowShape.Same: + break; - volume = _size.X*_size.Y*_size.Z; + case HollowShape.Circle: - // If the user has 'hollowed out' - // ProfileHollow is one of those 0 to 50000 values :P - // we like percentages better.. so turning into a percentage + hollowVolume *= 0.78539816339f; + break; - if (((float) _pbs.ProfileHollow/50000f) > 0.0) - { - float hollowAmount = (float) _pbs.ProfileHollow/50000f; + case HollowShape.Triangle: + + hollowVolume *= (0.5f * .5f); + break; + + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } + } - // calculate the hollow volume by it's shape compared to the prim shape - float hollowVolume = 0; - switch (_pbs.HollowShape) + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - case HollowShape.Square: - case HollowShape.Same: - // Cube Hollow volume calculation - float hollowsizex = _size.X*hollowAmount; - float hollowsizey = _size.Y*hollowAmount; - float hollowsizez = _size.Z*hollowAmount; - hollowVolume = hollowsizex*hollowsizey*hollowsizez; - break; - - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - float hRadius = _size.X/2; - float hLength = _size.Z; - - // pi * r2 * h - hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); - break; - - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y - - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); - break; - - default: - hollowVolume = 0; - break; + //a tube + + volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); + tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); + volume -= volume*tmp*tmp; + + if (hollowAmount > 0.0) + { + hollowVolume *= hollowAmount; + + switch (_pbs.HollowShape) + { + case HollowShape.Square: + case HollowShape.Same: + break; + + case HollowShape.Circle: + hollowVolume *= 0.78539816339f;; + break; + + case HollowShape.Triangle: + hollowVolume *= 0.5f * 0.5f; + break; + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } } - volume = volume - hollowVolume; - } break; + case ProfileShape.Circle: - if (_pbs.PathCurve == (byte)Extrusion.Straight) - { - // Cylinder - float volume1 = (float)(Math.PI * Math.Pow(_size.X/2, 2) * _size.Z); - float volume2 = (float)(Math.PI * Math.Pow(_size.Y/2, 2) * _size.Z); - // Approximating the cylinder's irregularity. - if (volume1 > volume2) - { - volume = (float)volume1 - (volume1 - volume2); - } - else if (volume2 > volume1) + if (_pbs.PathCurve == (byte)Extrusion.Straight) { - volume = (float)volume2 - (volume2 - volume1); + volume *= 0.78539816339f; // elipse base + + if (hollowAmount > 0.0) + { + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Circle: + break; + + case HollowShape.Square: + hollowVolume *= 0.5f * 2.5984480504799f; + break; + + case HollowShape.Triangle: + hollowVolume *= .5f * 1.27323954473516f; + break; + + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } } - else + + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - // Regular cylinder - volume = volume1; - } - } - else - { - // We don't know what the shape is yet, so use default - volume = _size.X * _size.Y * _size.Z; - } - // If the user has 'hollowed out' - // ProfileHollow is one of those 0 to 50000 values :P - // we like percentages better.. so turning into a percentage + volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= (1.0f - tmp * tmp); + + if (hollowAmount > 0.0) + { - if (((float)_pbs.ProfileHollow / 50000f) > 0.0) - { - float hollowAmount = (float)_pbs.ProfileHollow / 50000f; + // calculate the hollow volume by it's shape compared to the prim shape + hollowVolume *= hollowAmount; - // calculate the hollow volume by it's shape compared to the prim shape - float hollowVolume = 0; - switch (_pbs.HollowShape) - { - case HollowShape.Same: - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - float hRadius = _size.X / 2; - float hLength = _size.Z; - - // pi * r2 * h - hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount); - break; - - case HollowShape.Square: - // Cube Hollow volume calculation - float hollowsizex = _size.X * hollowAmount; - float hollowsizey = _size.Y * hollowAmount; - float hollowsizez = _size.Z * hollowAmount; - hollowVolume = hollowsizex * hollowsizey * hollowsizez; - break; - - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y - - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); - break; - - default: - hollowVolume = 0; - break; + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Circle: + break; + + case HollowShape.Square: + hollowVolume *= 0.5f * 2.5984480504799f; + break; + + case HollowShape.Triangle: + hollowVolume *= .5f * 1.27323954473516f; + break; + + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } } - volume = volume - hollowVolume; - } break; case ProfileShape.HalfCircle: if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - if (_size.X == _size.Y && _size.Y == _size.Z) - { - // regular sphere - // v = 4/3 * pi * r^3 - float sradius3 = (float)Math.Pow((_size.X / 2), 3); - volume = (float)((4f / 3f) * Math.PI * sradius3); - } - else - { - // we treat this as a box currently - volume = _size.X * _size.Y * _size.Z; - } - } - else - { - // We don't know what the shape is yet, so use default - volume = _size.X * _size.Y * _size.Z; + volume *= 0.52359877559829887307710723054658f; } break; case ProfileShape.EquilateralTriangle: - /* - v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h - // seed mesh - Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); - Vertex PM = new Vertex(+0.5f, 0f, 0.0f); - Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); - */ - float xA = -0.25f * _size.X; - float yA = -0.45f * _size.Y; + if (_pbs.PathCurve == (byte)Extrusion.Straight) + { + volume *= 0.32475953f; - float xB = 0.5f * _size.X; - float yB = 0; + if (hollowAmount > 0.0) + { - float xC = -0.25f * _size.X; - float yC = 0.45f * _size.Y; + // calculate the hollow volume by it's shape compared to the prim shape + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Triangle: + hollowVolume *= .25f; + break; - volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z); + case HollowShape.Square: + hollowVolume *= 0.499849f * 3.07920140172638f; + break; - // If the user has 'hollowed out' - // ProfileHollow is one of those 0 to 50000 values :P - // we like percentages better.. so turning into a percentage - float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f); - if (((float)fhollowFactor / 50000f) > 0.0) - { - float hollowAmount = (float)fhollowFactor / 50000f; + case HollowShape.Circle: + // Hollow shape is a perfect cyllinder in respect to the cube's scale + // Cyllinder hollow volume calculation - // calculate the hollow volume by it's shape compared to the prim shape - float hollowVolume = 0; - switch (_pbs.HollowShape) - { - case HollowShape.Same: - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y - - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); - break; - - case HollowShape.Square: - // Cube Hollow volume calculation - float hollowsizex = _size.X * hollowAmount; - float hollowsizey = _size.Y * hollowAmount; - float hollowsizez = _size.Z * hollowAmount; - hollowVolume = hollowsizex * hollowsizey * hollowsizez; - break; - - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - float hRadius = _size.X / 2; - float hLength = _size.Z; - - // pi * r2 * h - hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength)/2) * hollowAmount); - break; - - default: - hollowVolume = 0; - break; + hollowVolume *= 0.1963495f * 3.07920140172638f; + break; + + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } } - volume = volume - hollowVolume; - } - break; + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + { + volume *= 0.32475953f; + volume *= 0.01f * (float)(200 - _pbs.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= (1.0f - tmp * tmp); - default: - // we don't have all of the volume formulas yet so - // use the common volume formula for all - volume = _size.X*_size.Y*_size.Z; - break; - } + if (hollowAmount > 0.0) + { - // Calculate Path cut effect on volume - // Not exact, in the triangle hollow example - // They should never be zero or less then zero.. - // we'll ignore it if it's less then zero + hollowVolume *= hollowAmount; - // ProfileEnd and ProfileBegin are values - // from 0 to 50000 + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Triangle: + hollowVolume *= .25f; + break; - // Turning them back into percentages so that I can cut that percentage off the volume + case HollowShape.Square: + hollowVolume *= 0.499849f * 3.07920140172638f; + break; - float PathCutEndAmount = _pbs.ProfileEnd; - float PathCutStartAmount = _pbs.ProfileBegin; - if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) - { - float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f); + case HollowShape.Circle: - // Check the return amount for sanity - if (pathCutAmount >= 0.99f) - pathCutAmount = 0.99f; + hollowVolume *= 0.1963495f * 3.07920140172638f; + break; - volume = volume - (volume*pathCutAmount); - } - UInt16 taperX = _pbs.PathScaleX; - UInt16 taperY = _pbs.PathScaleY; - float taperFactorX = 0; - float taperFactorY = 0; + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } + } + break; - // Mass = density * volume - if (taperX != 100) - { - if (taperX > 100) - { - taperFactorX = 1.0f - ((float)taperX / 200); - //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); - } - else - { - taperFactorX = 1.0f - ((100 - (float)taperX) / 100); - //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); + default: + break; } - volume = (float)volume * ((taperFactorX / 3f) + 0.001f); - } - if (taperY != 100) - { - if (taperY > 100) + + + float taperX1; + float taperY1; + float taperX; + float taperY; + float pathBegin; + float pathEnd; + float profileBegin; + float profileEnd; + + if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) { - taperFactorY = 1.0f - ((float)taperY / 200); - //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); + taperX1 = _pbs.PathScaleX * 0.01f; + if (taperX1 > 1.0f) + taperX1 = 2.0f - taperX1; + taperX = 1.0f - taperX1; + + taperY1 = _pbs.PathScaleY * 0.01f; + if (taperY1 > 1.0f) + taperY1 = 2.0f - taperY1; + taperY = 1.0f - taperY1; } - else + else { - taperFactorY = 1.0f - ((100 - (float)taperY) / 100); - //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); + taperX = _pbs.PathTaperX * 0.01f; + if (taperX < 0.0f) + taperX = -taperX; + taperX1 = 1.0f - taperX; + + taperY = _pbs.PathTaperY * 0.01f; + if (taperY < 0.0f) + taperY = -taperY; + taperY1 = 1.0f - taperY; + } - volume = (float)volume * ((taperFactorY / 3f) + 0.001f); - } - returnMass = m_density*volume; - if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. + + + volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); + + pathBegin = (float)_pbs.PathBegin * 2.0e-5f; + pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; + volume *= (pathEnd - pathBegin); + +// this is crude aproximation + profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; + profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; + volume *= (profileEnd - profileBegin); + + returnMass = m_density * volume; + + if (returnMass <= 0) + returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. +// else if (returnMass > _parent_scene.maximumMassObject) +// returnMass = _parent_scene.maximumMassObject; + -- cgit v1.1 From b40c91777cf272b485da0cdfba2ffec868cfc7cf Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 2 Oct 2010 00:19:30 +0200 Subject: Replace CalculateMass with a more accurate version, contributed by Ubit. Thank you. --- OpenSim/Region/Physics/OdePlugin/ODEPrim.cs | 453 ++++++++++++++-------------- 1 file changed, 219 insertions(+), 234 deletions(-) diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index daf7fb0..319a951 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -403,300 +403,285 @@ namespace OpenSim.Region.Physics.OdePlugin private float CalculateMass() { - float volume = 0; - - // No material is passed to the physics engines yet.. soo.. - // we're using the m_density constant in the class definition + float volume = _size.X * _size.Y * _size.Z; // default + float tmp; float returnMass = 0; - + float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; + float hollowVolume = hollowAmount * hollowAmount; + switch (_pbs.ProfileShape) { case ProfileShape.Square: - // Profile Volume + // default box - volume = _size.X*_size.Y*_size.Z; + if (_pbs.PathCurve == (byte)Extrusion.Straight) + { + if (hollowAmount > 0.0) + { + switch (_pbs.HollowShape) + { + case HollowShape.Square: + case HollowShape.Same: + break; - // If the user has 'hollowed out' - // ProfileHollow is one of those 0 to 50000 values :P - // we like percentages better.. so turning into a percentage + case HollowShape.Circle: - if (((float) _pbs.ProfileHollow/50000f) > 0.0) - { - float hollowAmount = (float) _pbs.ProfileHollow/50000f; + hollowVolume *= 0.78539816339f; + break; - // calculate the hollow volume by it's shape compared to the prim shape - float hollowVolume = 0; - switch (_pbs.HollowShape) - { - case HollowShape.Square: - case HollowShape.Same: - // Cube Hollow volume calculation - float hollowsizex = _size.X*hollowAmount; - float hollowsizey = _size.Y*hollowAmount; - float hollowsizez = _size.Z*hollowAmount; - hollowVolume = hollowsizex*hollowsizey*hollowsizez; - break; + case HollowShape.Triangle: - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - float hRadius = _size.X/2; - float hLength = _size.Z; - - // pi * r2 * h - hollowVolume = ((float) (Math.PI*Math.Pow(hRadius, 2)*hLength)*hollowAmount); - break; + hollowVolume *= (0.5f * .5f); + break; - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } + } - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float) ((0.5*aLength*_size.X*_size.Z)*hollowAmount); - break; + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) + { + //a tube - default: - hollowVolume = 0; - break; + volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); + tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); + volume -= volume*tmp*tmp; + + if (hollowAmount > 0.0) + { + hollowVolume *= hollowAmount; + + switch (_pbs.HollowShape) + { + case HollowShape.Square: + case HollowShape.Same: + break; + + case HollowShape.Circle: + hollowVolume *= 0.78539816339f;; + break; + + case HollowShape.Triangle: + hollowVolume *= 0.5f * 0.5f; + break; + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } } - volume = volume - hollowVolume; - } break; + case ProfileShape.Circle: - if (_pbs.PathCurve == (byte)Extrusion.Straight) - { - // Cylinder - float volume1 = (float)(Math.PI * Math.Pow(_size.X/2, 2) * _size.Z); - float volume2 = (float)(Math.PI * Math.Pow(_size.Y/2, 2) * _size.Z); - // Approximating the cylinder's irregularity. - if (volume1 > volume2) - { - volume = (float)volume1 - (volume1 - volume2); - } - else if (volume2 > volume1) - { - volume = (float)volume2 - (volume2 - volume1); - } - else + if (_pbs.PathCurve == (byte)Extrusion.Straight) { - // Regular cylinder - volume = volume1; - } - } - else - { - // We don't know what the shape is yet, so use default - volume = _size.X * _size.Y * _size.Z; - } - // If the user has 'hollowed out' - // ProfileHollow is one of those 0 to 50000 values :P - // we like percentages better.. so turning into a percentage + volume *= 0.78539816339f; // elipse base - if (((float)_pbs.ProfileHollow / 50000f) > 0.0) - { - float hollowAmount = (float)_pbs.ProfileHollow / 50000f; + if (hollowAmount > 0.0) + { + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Circle: + break; - // calculate the hollow volume by it's shape compared to the prim shape - float hollowVolume = 0; - switch (_pbs.HollowShape) + case HollowShape.Square: + hollowVolume *= 0.5f * 2.5984480504799f; + break; + + case HollowShape.Triangle: + hollowVolume *= .5f * 1.27323954473516f; + break; + + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } + } + + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - case HollowShape.Same: - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - float hRadius = _size.X / 2; - float hLength = _size.Z; - - // pi * r2 * h - hollowVolume = ((float)(Math.PI * Math.Pow(hRadius, 2) * hLength) * hollowAmount); - break; + volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= (1.0f - tmp * tmp); + + if (hollowAmount > 0.0) + { - case HollowShape.Square: - // Cube Hollow volume calculation - float hollowsizex = _size.X * hollowAmount; - float hollowsizey = _size.Y * hollowAmount; - float hollowsizez = _size.Z * hollowAmount; - hollowVolume = hollowsizex * hollowsizey * hollowsizez; - break; + // calculate the hollow volume by it's shape compared to the prim shape + hollowVolume *= hollowAmount; - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Circle: + break; - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); - break; + case HollowShape.Square: + hollowVolume *= 0.5f * 2.5984480504799f; + break; - default: - hollowVolume = 0; - break; + case HollowShape.Triangle: + hollowVolume *= .5f * 1.27323954473516f; + break; + + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } } - volume = volume - hollowVolume; - } break; case ProfileShape.HalfCircle: if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - if (_size.X == _size.Y && _size.Y == _size.Z) - { - // regular sphere - // v = 4/3 * pi * r^3 - float sradius3 = (float)Math.Pow((_size.X / 2), 3); - volume = (float)((4f / 3f) * Math.PI * sradius3); - } - else - { - // we treat this as a box currently - volume = _size.X * _size.Y * _size.Z; - } - } - else - { - // We don't know what the shape is yet, so use default - volume = _size.X * _size.Y * _size.Z; + volume *= 0.52359877559829887307710723054658f; } break; case ProfileShape.EquilateralTriangle: - /* - v = (abs((xB*yA-xA*yB)+(xC*yB-xB*yC)+(xA*yC-xC*yA))/2) * h - // seed mesh - Vertex MM = new Vertex(-0.25f, -0.45f, 0.0f); - Vertex PM = new Vertex(+0.5f, 0f, 0.0f); - Vertex PP = new Vertex(-0.25f, +0.45f, 0.0f); - */ - float xA = -0.25f * _size.X; - float yA = -0.45f * _size.Y; + if (_pbs.PathCurve == (byte)Extrusion.Straight) + { + volume *= 0.32475953f; - float xB = 0.5f * _size.X; - float yB = 0; + if (hollowAmount > 0.0) + { - float xC = -0.25f * _size.X; - float yC = 0.45f * _size.Y; + // calculate the hollow volume by it's shape compared to the prim shape + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Triangle: + hollowVolume *= .25f; + break; - volume = (float)((Math.Abs((xB * yA - xA * yB) + (xC * yB - xB * yC) + (xA * yC - xC * yA)) / 2) * _size.Z); + case HollowShape.Square: + hollowVolume *= 0.499849f * 3.07920140172638f; + break; - // If the user has 'hollowed out' - // ProfileHollow is one of those 0 to 50000 values :P - // we like percentages better.. so turning into a percentage - float fhollowFactor = ((float)_pbs.ProfileHollow / 1.9f); - if (((float)fhollowFactor / 50000f) > 0.0) - { - float hollowAmount = (float)fhollowFactor / 50000f; + case HollowShape.Circle: + // Hollow shape is a perfect cyllinder in respect to the cube's scale + // Cyllinder hollow volume calculation - // calculate the hollow volume by it's shape compared to the prim shape - float hollowVolume = 0; - switch (_pbs.HollowShape) + hollowVolume *= 0.1963495f * 3.07920140172638f; + break; + + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } + } + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - case HollowShape.Same: - case HollowShape.Triangle: - // Equilateral Triangular Prism volume hollow calculation - // Triangle is an Equilateral Triangular Prism with aLength = to _size.Y - - float aLength = _size.Y; - // 1/2 abh - hollowVolume = (float)((0.5 * aLength * _size.X * _size.Z) * hollowAmount); - break; + volume *= 0.32475953f; + volume *= 0.01f * (float)(200 - _pbs.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); + volume *= (1.0f - tmp * tmp); - case HollowShape.Square: - // Cube Hollow volume calculation - float hollowsizex = _size.X * hollowAmount; - float hollowsizey = _size.Y * hollowAmount; - float hollowsizez = _size.Z * hollowAmount; - hollowVolume = hollowsizex * hollowsizey * hollowsizez; - break; + if (hollowAmount > 0.0) + { - case HollowShape.Circle: - // Hollow shape is a perfect cyllinder in respect to the cube's scale - // Cyllinder hollow volume calculation - float hRadius = _size.X / 2; - float hLength = _size.Z; + hollowVolume *= hollowAmount; - // pi * r2 * h - hollowVolume = ((float)((Math.PI * Math.Pow(hRadius, 2) * hLength)/2) * hollowAmount); - break; + switch (_pbs.HollowShape) + { + case HollowShape.Same: + case HollowShape.Triangle: + hollowVolume *= .25f; + break; - default: - hollowVolume = 0; - break; - } - volume = volume - hollowVolume; - } - break; + case HollowShape.Square: + hollowVolume *= 0.499849f * 3.07920140172638f; + break; - default: - // we don't have all of the volume formulas yet so - // use the common volume formula for all - volume = _size.X*_size.Y*_size.Z; - break; - } + case HollowShape.Circle: - // Calculate Path cut effect on volume - // Not exact, in the triangle hollow example - // They should never be zero or less then zero.. - // we'll ignore it if it's less then zero + hollowVolume *= 0.1963495f * 3.07920140172638f; + break; - // ProfileEnd and ProfileBegin are values - // from 0 to 50000 + default: + hollowVolume = 0; + break; + } + volume *= (1.0f - hollowVolume); + } + } + break; - // Turning them back into percentages so that I can cut that percentage off the volume + default: + break; + } - float PathCutEndAmount = _pbs.ProfileEnd; - float PathCutStartAmount = _pbs.ProfileBegin; - if (((PathCutStartAmount + PathCutEndAmount)/50000f) > 0.0f) - { - float pathCutAmount = ((PathCutStartAmount + PathCutEndAmount)/50000f); - // Check the return amount for sanity - if (pathCutAmount >= 0.99f) - pathCutAmount = 0.99f; - volume = volume - (volume*pathCutAmount); - } - UInt16 taperX = _pbs.PathScaleX; - UInt16 taperY = _pbs.PathScaleY; - float taperFactorX = 0; - float taperFactorY = 0; + float taperX1; + float taperY1; + float taperX; + float taperY; + float pathBegin; + float pathEnd; + float profileBegin; + float profileEnd; - // Mass = density * volume - if (taperX != 100) - { - if (taperX > 100) + if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) { - taperFactorX = 1.0f - ((float)taperX / 200); - //m_log.Warn("taperTopFactorX: " + extr.taperTopFactorX.ToString()); - } - else - { - taperFactorX = 1.0f - ((100 - (float)taperX) / 100); - //m_log.Warn("taperBotFactorX: " + extr.taperBotFactorX.ToString()); - } - volume = (float)volume * ((taperFactorX / 3f) + 0.001f); - } + taperX1 = _pbs.PathScaleX * 0.01f; + if (taperX1 > 1.0f) + taperX1 = 2.0f - taperX1; + taperX = 1.0f - taperX1; - if (taperY != 100) - { - if (taperY > 100) - { - taperFactorY = 1.0f - ((float)taperY / 200); - //m_log.Warn("taperTopFactorY: " + extr.taperTopFactorY.ToString()); + taperY1 = _pbs.PathScaleY * 0.01f; + if (taperY1 > 1.0f) + taperY1 = 2.0f - taperY1; + taperY = 1.0f - taperY1; } - else + else { - taperFactorY = 1.0f - ((100 - (float)taperY) / 100); - //m_log.Warn("taperBotFactorY: " + extr.taperBotFactorY.ToString()); + taperX = _pbs.PathTaperX * 0.01f; + if (taperX < 0.0f) + taperX = -taperX; + taperX1 = 1.0f - taperX; + + taperY = _pbs.PathTaperY * 0.01f; + if (taperY < 0.0f) + taperY = -taperY; + taperY1 = 1.0f - taperY; + } - volume = (float)volume * ((taperFactorY / 3f) + 0.001f); - } - returnMass = m_density*volume; - if (returnMass <= 0) returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. + + + volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); + + pathBegin = (float)_pbs.PathBegin * 2.0e-5f; + pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; + volume *= (pathEnd - pathBegin); + +// this is crude aproximation + profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; + profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; + volume *= (profileEnd - profileBegin); + + returnMass = m_density * volume; + + if (returnMass <= 0) + returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. +// else if (returnMass > _parent_scene.maximumMassObject) +// returnMass = _parent_scene.maximumMassObject; + -- cgit v1.1 From b4fe6da4eb5152e2023410f47aa1fe3cac715673 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 3 Oct 2010 16:57:45 +0100 Subject: Add the Warp3D dll --- bin/Warp3D.dll | Bin 0 -> 77824 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 bin/Warp3D.dll diff --git a/bin/Warp3D.dll b/bin/Warp3D.dll new file mode 100644 index 0000000..8781a82 Binary files /dev/null and b/bin/Warp3D.dll differ -- cgit v1.1 From 50b03d08a8cdec9359adcece5b4645a6dc821d26 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 4 Oct 2010 00:04:42 +0200 Subject: Add linden prim renderer and update libOMV --- .../LindenUDP/UnackedPacketCollection.cs | 4 +- .../Region/CoreModules/Asset/FlotsamAssetCache.cs | 4 +- .../UserAccounts/UserAccountCache.cs | 4 +- .../SimianUserAccountServiceConnector.cs | 6 +- bin/OpenMetaverse.Rendering.Linden.dll | Bin 0 -> 40960 bytes bin/OpenMetaverse.StructuredData.XML | 398 +- bin/OpenMetaverse.StructuredData.dll | Bin 102400 -> 95232 bytes bin/OpenMetaverse.XML | 36146 ++++++++++--------- bin/OpenMetaverse.dll | Bin 1691648 -> 1768960 bytes bin/OpenMetaverse.dll.config | 14 +- bin/OpenMetaverseTypes.XML | 3302 +- bin/OpenMetaverseTypes.dll | Bin 106496 -> 105984 bytes 12 files changed, 20586 insertions(+), 19292 deletions(-) create mode 100644 bin/OpenMetaverse.Rendering.Linden.dll diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index c120a12..043e7d3 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs @@ -143,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutgoingPacket pendingAdd; if (m_pendingAdds != null) { - while (m_pendingAdds.Dequeue(out pendingAdd)) + while (m_pendingAdds.TryDequeue(out pendingAdd)) { if (pendingAdd != null && m_packets != null) { @@ -157,7 +157,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutgoingPacket ackedPacket; if (m_pendingRemoves != null) { - while (m_pendingRemoves.Dequeue(out pendingRemove)) + while (m_pendingRemoves.TryDequeue(out pendingRemove)) { if (m_pendingRemoves != null && m_packets != null) { diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 9eaa758..6ed4867 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -252,7 +252,7 @@ namespace Flotsam.RegionModules.AssetCache } else { - m_MemoryCache.AddOrUpdate(key, asset, DateTime.MaxValue); + m_MemoryCache.AddOrUpdate(key, asset, Double.MaxValue); } } } @@ -863,4 +863,4 @@ namespace Flotsam.RegionModules.AssetCache #endregion } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs index 64788db..0da3f5f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs @@ -53,9 +53,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts public void Cache(UUID userID, UserAccount account) { // Cache even null accounts - m_UUIDCache.AddOrUpdate(userID, account, DateTime.Now + TimeSpan.FromSeconds(CACHE_EXPIRATION_SECONDS)); + m_UUIDCache.AddOrUpdate(userID, account, CACHE_EXPIRATION_SECONDS); if (account != null) - m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, DateTime.Now + TimeSpan.FromSeconds(CACHE_EXPIRATION_SECONDS)); + m_NameCache.AddOrUpdate(account.Name, account.PrincipalID, CACHE_EXPIRATION_SECONDS); // m_log.DebugFormat("[USER CACHE]: cached user {0}", userID); } diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs index ddd2322..9c150ee 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianUserAccountServiceConnector.cs @@ -147,7 +147,7 @@ namespace OpenSim.Services.Connectors.SimianGrid if (account == null) { // Store null responses too, to avoid repeated lookups for missing accounts - m_accountCache.AddOrUpdate(userID, null, DateTime.Now + TimeSpan.FromSeconds(CACHE_EXPIRATION_SECONDS)); + m_accountCache.AddOrUpdate(userID, null, CACHE_EXPIRATION_SECONDS); } return account; @@ -225,7 +225,7 @@ namespace OpenSim.Services.Connectors.SimianGrid if (success) { // Cache the user account info - m_accountCache.AddOrUpdate(data.PrincipalID, data, DateTime.Now + TimeSpan.FromSeconds(CACHE_EXPIRATION_SECONDS)); + m_accountCache.AddOrUpdate(data.PrincipalID, data, CACHE_EXPIRATION_SECONDS); } else { @@ -290,7 +290,7 @@ namespace OpenSim.Services.Connectors.SimianGrid GetFirstLastName(response["Name"].AsString(), out account.FirstName, out account.LastName); // Cache the user account info - m_accountCache.AddOrUpdate(account.PrincipalID, account, DateTime.Now + TimeSpan.FromSeconds(CACHE_EXPIRATION_SECONDS)); + m_accountCache.AddOrUpdate(account.PrincipalID, account, CACHE_EXPIRATION_SECONDS); return account; } diff --git a/bin/OpenMetaverse.Rendering.Linden.dll b/bin/OpenMetaverse.Rendering.Linden.dll new file mode 100644 index 0000000..9642a8d Binary files /dev/null and b/bin/OpenMetaverse.Rendering.Linden.dll differ diff --git a/bin/OpenMetaverse.StructuredData.XML b/bin/OpenMetaverse.StructuredData.XML index b8f45b1..927e960 100644 --- a/bin/OpenMetaverse.StructuredData.XML +++ b/bin/OpenMetaverse.StructuredData.XML @@ -1,333 +1,363 @@ - OpenMetaverse.StructuredData + /home/root/libopenmetaverse/bin/OpenMetaverse.StructuredData - + - + + - + + - - + - - - - + - - - - + - - - - + - - - - + - - - - - + - - - - - - + - - - - - + - - - - - + - - - - + - - - - + - - - - + - + Uses reflection to create an SDMap from all of the SD + serializable types in an object - - + Class or struct containing serializable types + An SDMap holding the serialized values from the + container object - + - + Uses reflection to deserialize member variables in an object from + an SDMap - + Reference to an object to fill with deserialized + values + Serialized values to put in the target + object - + - - - - - + - - - - - + - - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - - - - - - - - - - - - + - - - + + + + - + - + + + + - - + + + + + + + - - + + + + + + + - - + + + + + - - + + + + + + + + + - - + + + + + + + + + - - + + + + + + + + + - - + + + + + + + - - + + + + + + + - - + + + + + + + - - + + + + + + + - - + + + + + + + - + - + + + + - + - + + + + - + - Uses reflection to create an SDMap from all of the SD - serializable types in an object - Class or struct containing serializable types - An SDMap holding the serialized values from the - container object + + + + + + - + - Uses reflection to deserialize member variables in an object from - an SDMap - Reference to an object to fill with deserialized - values - Serialized values to put in the target - object + + + + + + + + - + - + + + + + + - + - + + + + + + - + - + + + + - + - + + + + - + - + + + + - + - + + + + - + - + + + + - + - + + + + - + - + + + + + + - + - + + + + diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index 54681e4..27ccfbc 100644 Binary files a/bin/OpenMetaverse.StructuredData.dll and b/bin/OpenMetaverse.StructuredData.dll differ diff --git a/bin/OpenMetaverse.XML b/bin/OpenMetaverse.XML index ca9f359..fa1057a 100644 --- a/bin/OpenMetaverse.XML +++ b/bin/OpenMetaverse.XML @@ -1,4438 +1,4072 @@ - OpenMetaverse + /home/root/libopenmetaverse/bin/OpenMetaverse - + - Capability to load TGAs to Bitmap + Permission request flags, asked when a script wants to control an Avatar - - - Represents a primitive asset - + + Placeholder for empty values, shouldn't ever see this - - - Base class for all Asset types - + + Script wants ability to take money from you - - A byte array containing the raw asset data + + Script wants to take camera controls for you - - True if the asset it only stored on the server temporarily + + Script wants to remap avatars controls - - A unique ID + + Script wants to trigger avatar animations + This function is not implemented on the grid - - - Construct a new Asset object - + + Script wants to attach or detach the prim or primset to your avatar - - - Construct a new Asset object - - A unique specific to this asset - A byte array containing the raw asset data + + Script wants permission to release ownership + This function is not implemented on the grid + The concept of "public" objects does not exist anymore. - - - Regenerates the AssetData byte array from the properties - of the derived class. - + + Script wants ability to link/delink with other prims - - - Decodes the AssetData, placing it in appropriate properties of the derived - class. - - True if the asset decoding succeeded, otherwise false + + Script wants permission to change joints + This function is not implemented on the grid - - The assets unique ID + + Script wants permissions to change permissions + This function is not implemented on the grid - - - The "type" of asset, Notecard, Animation, etc - + + Script wants to track avatars camera position and rotation - - Initializes a new instance of an AssetPrim object + + Script wants to control your camera - + - + Special commands used in Instant Messages - - - - - + + Indicates a regular IM from another agent - - Override the base classes AssetType + + Simple notification box with an OK button - - - Only used internally for XML serialization/deserialization - + + You've been invited to join a group. - - - pre-defined built in sounds - + + Inventory offer - - + + Accepted inventory offer - - + + Declined inventory offer - - + + Group vote - - + + An object is offering its inventory - - + + Accept an inventory offer from an object - - + + Decline an inventory offer from an object - - + + Unknown - - + + Start a session, or add users to a session - - coins + + Start a session, but don't prune offline users - - cash register bell + + Start a session with your group - - + + Start a session without a calling card (finder or objects) - - + + Send a message to a session - - rubber + + Leave a session - - plastic + + Indicates that the IM is from an object - - flesh + + Sent an IM to a busy user, this is the auto response - - wood splintering? + + Shows the message in the console and chat history - - glass break + + Send a teleport lure - - metal clunk + + Response sent to the agent which inititiated a teleport invitation - - whoosh + + Response sent to the agent which inititiated a teleport invitation - - shake + + Only useful if you have Linden permissions - - + + A placeholder type for future expansion, currently not + used - - ding + + IM to tell the user to go to an URL - - + + IM for help - - + + IM sent automatically on call for help, sends a lure + to each Helper reached - - + + Like an IM but won't go to email - - + + IM from a group officer to all group members - - + + Unknown - - + + Unknown - - + + Accept a group invitation - - + + Decline a group invitation - - + + Unknown - - + + An avatar is offering you friendship - - + + An avatar has accepted your friendship offer - - + + An avatar has declined your friendship offer - - + + Indicates that a user has started typing - - + + Indicates that a user has stopped typing - + - A dictionary containing all pre-defined sounds + Flag in Instant Messages, whether the IM should be delivered to + offline avatars as well - A dictionary containing the pre-defined sounds, - where the key is the sounds ID, and the value is a string - containing a name to identify the purpose of the sound - + + Only deliver to online avatars + + + If the avatar is offline the message will be held until + they login next, and possibly forwarded to their e-mail account + + - Type of return to use when returning objects from a parcel + Conversion type to denote Chat Packet types in an easier-to-understand format - - - - - Return objects owned by parcel owner + + Whisper (5m radius) - - Return objects set to group + + Normal chat (10/20m radius), what the official viewer typically sends - - Return objects not owned by parcel owner or set to group + + Shouting! (100m radius) - - Return a specific list of objects on parcel + + Event message when an Avatar has begun to type - - Return objects that are marked for-sale + + Event message when an Avatar has stopped typing - + + Send the message to the debug channel + + + Event message when an object uses llOwnerSay + + + Special value to support llRegionSay, never sent to the client + + - Blacklist/Whitelist flags used in parcels Access List + Identifies the source of a chat message - - Agent is denied access + + Chat from the grid or simulator - - Agent is granted access + + Chat from another avatar - + + Chat from an object + + - The result of a request for parcel properties - - No matches were found for the request + + + - - Request matched a single parcel + + + - - Request matched multiple parcels + + + - + - Flags used in the ParcelAccessListRequest packet to specify whether - we want the access list (whitelist), ban list (blacklist), or both + Effect type used in ViewerEffect packets - - Request the access list + + + - - Request the ban list + + + - - Request both White and Black lists + + + - + - Sequence ID in ParcelPropertiesReply packets (sent when avatar - tries to cross a parcel border) - - Parcel is currently selected + + + - - Parcel restricted to a group the avatar is not a - member of + + + - - Avatar is banned from the parcel + + + - - Parcel is restricted to an access list that the - avatar is not on + + Project a beam from a source to a destination, such as + the one used when editing an object - - Response to hovering over a parcel + + + - + - The tool to use when modifying terrain levels - - Level the terrain + + + - - Raise the terrain + + Create a swirl of particles around an object - - Lower the terrain + + + - - Smooth the terrain + + + - - Add random noise to the terrain + + Cause an avatar to look at an object - - Revert terrain to simulator default + + Cause an avatar to point at an object - + - The tool size to use when changing terrain levels + The action an avatar is doing when looking at something, used in + ViewerEffect packets for the LookAt effect - - Small + + + - - Medium + + + - - Large + + + - + - Reasons agent is denied access to a parcel on the simulator - - Agent is not denied, access is granted + + + - - Agent is not a member of the group set for the parcel, or which owns the parcel + + + - - Agent is not on the parcels specific allow list + + Deprecated - - Agent is on the parcels ban list + + + - - Unknown + + + - - Agent is not age verified and parcel settings deny access to non age verified avatars + + + - + - Parcel overlay type. This is used primarily for highlighting and - coloring which is why it is a single integer instead of a set of - flags - These values seem to be poorly thought out. The first three - bits represent a single value, not flags. For example Auction (0x05) is - not a combination of OwnedByOther (0x01) and ForSale(0x04). However, - the BorderWest and BorderSouth values are bit flags that get attached - to the value stored in the first three bits. Bits four, five, and six - are unused - - Public land + + + The action an avatar is doing when pointing at something, used in + ViewerEffect packets for the PointAt effect + - - Land is owned by another avatar + + + - - Land is owned by a group + + + - - Land is owned by the current avatar + + + - - Land is for sale + + + - - Land is being auctioned + + + Money transaction types + - - To the west of this area is a parcel border + + + - - To the south of this area is a parcel border + + + - + - Various parcel properties - - No flags set + + + - - Allow avatars to fly (a client-side only restriction) + + + - - Allow foreign scripts to run + + + - - This parcel is for sale + + + - - Allow avatars to create a landmark on this parcel + + + - - Allows all avatars to edit the terrain on this parcel + + + - - Avatars have health and can take damage on this parcel. - If set, avatars can be killed and sent home here + + + - - Foreign avatars can create objects here + + + - - All objects on this parcel can be purchased + + + - - Access is restricted to a group + + + - - Access is restricted to a whitelist + + + - - Ban blacklist is enabled + + + - - Unknown + + + - - List this parcel in the search directory + + + - - Allow personally owned parcels to be deeded to group + + + - - If Deeded, owner contributes required tier to group parcel is deeded to + + + - - Restrict sounds originating on this parcel to the - parcel boundaries + + + - - Objects on this parcel are sold when the land is - purchsaed + + + - - Allow this parcel to be published on the web + + + - - The information for this parcel is mature content + + + - - The media URL is an HTML page + + + - - The media URL is a raw HTML string + + + - - Restrict foreign object pushes + + + - - Ban all non identified/transacted avatars + + + - - Allow group-owned scripts to run + + + - - Allow object creation by group members or group - objects + + + - - Allow all objects to enter this parcel + + + - - Only allow group and owner objects to enter this parcel + + + - - Voice Enabled on this parcel + + + - - Use Estate Voice channel for Voice on this parcel + + + - - Deny Age Unverified Users + + + - + - Parcel ownership status - - Placeholder + + + - - Parcel is leased (owned) by an avatar or group + + + - - Parcel is in process of being leased (purchased) by an avatar or group + + + - - Parcel has been abandoned back to Governor Linden + + + - + - Category parcel is listed in under search - - No assigned category + + + - - Linden Infohub or public area + + + - - Adult themed area + + + - - Arts and Culture + + + - - Business + + + - - Educational + + + - - Gaming + + + - - Hangout or Club + + + - - Newcomer friendly + + + - - Parks and Nature + + + - - Residential + + + - - Shopping + + + - - Not Used? + + + - - Other + + + - - Not an actual category, only used for queries + + + - + - Type of teleport landing for a parcel - - Unset, simulator default + + + - - Specific landing point set for this parcel + + + - - No landing point set, direct teleports enabled for - this parcel + + + - + - Parcel Media Command used in ParcelMediaCommandMessage - - Stop the media stream and go back to the first frame + + + - - Pause the media stream (stop playing but stay on current frame) + + + - - Start the current media stream playing and stop when the end is reached + + + - - Start the current media stream playing, - loop to the beginning when the end is reached and continue to play + + + - - Specifies the texture to replace with video - If passing the key of a texture, it must be explicitly typecast as a key, - not just passed within double quotes. + + + Flags sent when a script takes or releases a control + + NOTE: (need to verify) These might be a subset of the ControlFlags enum in Movement, - - Specifies the movie URL (254 characters max) + + No Flags set - - Specifies the time index at which to begin playing + + Forward (W or up Arrow) - - Specifies a single agent to apply the media command to + + Back (S or down arrow) - - Unloads the stream. While the stop command sets the texture to the first frame of the movie, - unload resets it to the real texture that the movie was replacing. + + Move left (shift+A or left arrow) - - Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties - (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter. + + Move right (shift+D or right arrow) - - Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only). - Use "text/html" for HTML. + + Up (E or PgUp) - - Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only). - This might still not be working + + Down (C or PgDown) - - Sets a description for the media being displayed (1.19.1 RC0 and later only). + + Rotate left (A or left arrow) - + + Rotate right (D or right arrow) + + + Left Mouse Button + + + Left Mouse button in MouseLook + + - Some information about a parcel of land returned from a DirectoryManager search + Currently only used to hide your group title - - Global Key of record + + No flags set - - Parcel Owners + + Hide your group title - - Name field of parcel, limited to 128 characters + + + Action state of the avatar, which can currently be typing and + editing + - - Description field of parcel, limited to 256 characters + + + - - Total Square meters of parcel + + + - - Total area billable as Tier, for group owned land this will be 10% less than ActualArea + + + - - True of parcel is in Mature simulator + + + Current teleport status + - - Grid global X position of parcel + + Unknown status - - Grid global Y position of parcel + + Teleport initialized - - Grid global Z position of parcel (not used) + + Teleport in progress - - Name of simulator parcel is located in + + Teleport failed - - Texture of parcels display picture + + Teleport completed - - Float representing calculated traffic based on time spent on parcel by avatars + + Teleport cancelled - - Sale price of parcel (not used) + + + - - Auction ID of parcel + + No flags set, or teleport failed - + + Set when newbie leaves help island for first time + + - Parcel Media Information - - A byte, if 0x1 viewer should auto scale media to fit object + + Via Lure - - A boolean, if true the viewer should loop the media + + Via Landmark - - The Asset UUID of the Texture which when applied to a - primitive will display the media + + Via Location - - A URL which points to any Quicktime supported media type + + Via Home - - A description of the media + + Via Telehub - - An Integer which represents the height of the media + + Via Login - - An integer which represents the width of the media + + Linden Summoned - - A string which contains the mime type of the media + + Linden Forced me - + - Parcel of land, a portion of virtual real estate in a simulator - - The total number of contiguous 4x4 meter blocks your agent owns within this parcel + + Agent Teleported Home via Script - - The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own + + + - - Deprecated, Value appears to always be 0 + + + - - Simulator-local ID of this parcel + + + - - UUID of the owner of this parcel + + forced to new location for example when avatar is banned or ejected - - Whether the land is deeded to a group or not + + Teleport Finished via a Lure - - + + Finished, Sim Changed - - Date land was claimed + + Finished, Same Sim - - Appears to always be zero + + + - - This field is no longer used + + + - - Minimum corner of the axis-aligned bounding box for this - parcel + + + - - Maximum corner of the axis-aligned bounding box for this - parcel + + + - - Bitmap describing land layout in 4x4m squares across the - entire region + + + - - Total parcel land area + + + - - + + + - - Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used + + + - - Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel - owned by the agent or group that owns this parcel + + + - - Maximum number of primitives this parcel supports + + + Instant Message + - - Total number of primitives on this parcel + + Key of sender - - For group-owned parcels this indicates the total number of prims deeded to the group, - for parcels owned by an individual this inicates the number of prims owned by the individual + + Name of sender - - Total number of primitives owned by the parcel group on - this parcel, or for parcels owned by an individual with a group set the - total number of prims set to that group. + + Key of destination avatar - - Total number of prims owned by other avatars that are not set to group, or not the parcel owner + + ID of originating estate - - A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect - the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed + + Key of originating region - - Autoreturn value in minutes for others' objects + + Coordinates in originating region - - + + Instant message type - - Sale price of the parcel, only useful if ForSale is set - The SalePrice will remain the same after an ownership - transfer (sale), so it can be used to see the purchase price after - a sale if the new owner has not changed it + + Group IM session toggle - - Parcel Name + + Key of IM session, for Group Messages, the groups UUID - - Parcel Description + + Timestamp of the instant message - - URL For Music Stream + + Instant message text - - + + Whether this message is held for offline avatars - - Price for a temporary pass + + Context specific packed data - - How long is pass valid for + + Print the struct data as a string + A string containing the field name, and field value - - + + + Manager class for our own avatar + - - Key of authorized buyer + + + Constructor, setup callbacks for packets related to our avatar + + A reference to the Class - - Key of parcel snapshot + + + Agent movement and camera control + Agent movement is controlled by setting specific + After the control flags are set, An AgentUpdate is required to update the simulator of the specified flags + This is most easily accomplished by setting one or more of the AgentMovement properties + Movement of an avatar is always based on a compass direction, for example AtPos will move the + agent from West to East or forward on the X Axis, AtNeg will of course move agent from + East to West or backward on the X Axis, LeftPos will be South to North or forward on the Y Axis + The Z axis is Up, finer grained control of movements can be done using the Nudge properties + - - The landing point location + + Default constructor - - The landing point LookAt + + + Camera controls for the agent, mostly a thin wrapper around + CoordinateFrame. This class is only responsible for state + tracking and math, it does not send any packets + - - The type of landing enforced from the enum + + + Default constructor + - - + + + - - + + The camera is a local frame of reference inside of + the larger grid space. This is where the math happens - - + + + - - Access list of who is whitelisted on this - parcel + + + - - Access list of who is blacklisted on this - parcel + + + - - TRUE of region denies access to age unverified users + + + - - true to obscure (hide) media url + + Agent camera controls - - true to obscure (hide) music url + + Currently only used for hiding your group title - - A struct containing media details + + Action state of the avatar, which can currently be + typing and editing - + - Displays a parcel object in string format - string containing key=value pairs of a parcel object - + - Defalt constructor - Local ID of this parcel - + - Update the simulator with any local changes to this Parcel object - Simulator to send updates to - Whether we want the simulator to confirm - the update with a reply packet or not - + - Set Autoreturn time - Simulator to send the update to - + - Parcel (subdivided simulator lots) subsystem - - The event subscribers. null if no subcribers + + + - - Raises the ParcelDwellReply event - A ParcelDwellReplyEventArgs object containing the - data returned from the simulator + + + - - Thread sync lock object + + + - - The event subscribers. null if no subcribers + + + - - Raises the ParcelInfoReply event - A ParcelInfoReplyEventArgs object containing the - data returned from the simulator + + Timer for sending AgentUpdate packets - - Thread sync lock object + + Move agent positive along the X axis - - The event subscribers. null if no subcribers + + Move agent negative along the X axis - - Raises the ParcelProperties event - A ParcelPropertiesEventArgs object containing the - data returned from the simulator + + Move agent positive along the Y axis - - Thread sync lock object + + Move agent negative along the Y axis - - The event subscribers. null if no subcribers + + Move agent positive along the Z axis - - Raises the ParcelAccessListReply event - A ParcelAccessListReplyEventArgs object containing the - data returned from the simulator + + Move agent negative along the Z axis - - Thread sync lock object + + + - - The event subscribers. null if no subcribers + + + - - Raises the ParcelObjectOwnersReply event - A ParcelObjectOwnersReplyEventArgs object containing the - data returned from the simulator + + + - - Thread sync lock object + + + - - The event subscribers. null if no subcribers + + + - - Raises the SimParcelsDownloaded event - A SimParcelsDownloadedEventArgs object containing the - data returned from the simulator + + + - - Thread sync lock object + + + - - The event subscribers. null if no subcribers + + Causes simulator to make agent fly - - Raises the ForceSelectObjectsReply event - A ForceSelectObjectsReplyEventArgs object containing the - data returned from the simulator + + Stop movement - - Thread sync lock object + + Finish animation - - The event subscribers. null if no subcribers + + Stand up from a sit - - Raises the ParcelMediaUpdateReply event - A ParcelMediaUpdateReplyEventArgs object containing the - data returned from the simulator + + Tells simulator to sit agent on ground - - Thread sync lock object + + Place agent into mouselook mode - - The event subscribers. null if no subcribers + + Nudge agent positive along the X axis - - Raises the ParcelMediaCommand event - A ParcelMediaCommandEventArgs object containing the - data returned from the simulator + + Nudge agent negative along the X axis - - Thread sync lock object + + Nudge agent positive along the Y axis - - - Default constructor - - A reference to the GridClient object + + Nudge agent negative along the Y axis - - - Request basic information for a single parcel - - Simulator-local ID of the parcel + + Nudge agent positive along the Z axis - - - Request properties of a single parcel - - Simulator containing the parcel - Simulator-local ID of the parcel - An arbitrary integer that will be returned - with the ParcelProperties reply, useful for distinguishing between - multiple simultaneous requests + + Nudge agent negative along the Z axis - + - Request the access list for a single parcel - Simulator containing the parcel - Simulator-local ID of the parcel - An arbitrary integer that will be returned - with the ParcelAccessList reply, useful for distinguishing between - multiple simultaneous requests - - + - Request properties of parcels using a bounding box selection - Simulator containing the parcel - Northern boundary of the parcel selection - Eastern boundary of the parcel selection - Southern boundary of the parcel selection - Western boundary of the parcel selection - An arbitrary integer that will be returned - with the ParcelProperties reply, useful for distinguishing between - different types of parcel property requests - A boolean that is returned with the - ParcelProperties reply, useful for snapping focus to a single - parcel - - - Request all simulator parcel properties (used for populating the Simulator.Parcels - dictionary) - - Simulator to request parcels from (must be connected) + + Tell simulator to mark agent as away - + - Request all simulator parcel properties (used for populating the Simulator.Parcels - dictionary) - Simulator to request parcels from (must be connected) - If TRUE, will force a full refresh - Number of milliseconds to pause in between each request - + - Request the dwell value for a parcel - Simulator containing the parcel - Simulator-local ID of the parcel - + - Send a request to Purchase a parcel of land - The Simulator the parcel is located in - The parcels region specific local ID - true if this parcel is being purchased by a group - The groups - true to remove tier contribution if purchase is successful - The parcels size - The purchase price of the parcel - - + - Reclaim a parcel of land - The simulator the parcel is in - The parcels region specific local ID - + - Deed a parcel to a group + Returns "always run" value, or changes it by sending a SetAlwaysRunPacket - The simulator the parcel is in - The parcels region specific local ID - The groups - - - Request prim owners of a parcel of land. - - Simulator parcel is in - The parcels region specific local ID + + The current value of the agent control flags - - - Return objects from a parcel - - Simulator parcel is in - The parcels region specific local ID - the type of objects to return, - A list containing object owners s to return + + Gets or sets the interval in milliseconds at which + AgentUpdate packets are sent to the current simulator. Setting + this to a non-zero value will also enable the packet sending if + it was previously off, and setting it to zero will disable - + + Gets or sets whether AgentUpdate packets are sent to + the current simulator + + + Reset movement controls every time we send an update + + - Subdivide (split) a parcel + Send an AgentUpdate with the camera set at the current agent + position and pointing towards the heading specified - - - - - + Camera rotation in radians + Whether to send the AgentUpdate reliable + or not - + - Join two parcels of land creating a single parcel + Rotates the avatar body and camera toward a target position. + This will also anchor the camera position on the avatar - - - - - + Region coordinates to turn toward - + - Get a parcels LocalID + Send new AgentUpdate packet to update our current camera + position and rotation - Simulator parcel is in - Vector3 position in simulator (Z not used) - 0 on failure, or parcel LocalID on success. - A call to Parcels.RequestAllSimParcels is required to populate map and - dictionary. - + - Terraform (raise, lower, etc) an area or whole parcel of land + Send new AgentUpdate packet to update our current camera + position and rotation - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() + Whether to require server acknowledgement + of this packet - + - Terraform (raise, lower, etc) an area or whole parcel of land + Send new AgentUpdate packet to update our current camera + position and rotation - Simulator land area is in. - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() + Whether to require server acknowledgement + of this packet + Simulator to send the update to - + - Terraform (raise, lower, etc) an area or whole parcel of land + Builds an AgentUpdate packet entirely from parameters. This + will not touch the state of Self.Movement or + Self.Movement.Camera in any way - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - How many meters + or - to lower, 1 = 1 meter - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() + + + + + + + + + + + + + + + + + + + + + + - + - Terraform (raise, lower, etc) an area or whole parcel of land + Used to specify movement actions for your agent - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - How many meters + or - to lower, 1 = 1 meter - Height at which the terraform operation is acting at - - - - Sends a request to the simulator to return a list of objects owned by specific owners - - Simulator local ID of parcel - Owners, Others, Etc - List containing keys of avatars objects to select; - if List is null will return Objects of type selectType - Response data is returned in the event - - - - Eject and optionally ban a user from a parcel - - target key of avatar to eject - true to also ban target - - - - Freeze or unfreeze an avatar over your land - - target key to freeze - true to freeze, false to unfreeze - - - - Abandon a parcel of land - - Simulator parcel is in - Simulator local ID of parcel - - - - Requests the UUID of the parcel in a remote region at a specified location - - Location of the parcel in the remote region - Remote region handle - Remote region UUID - If successful UUID of the remote parcel, UUID.Zero otherwise - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + Empty flag - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + Move Forward (SL Keybinding: W/Up Arrow) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + Move Backward (SL Keybinding: S/Down Arrow) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + Move Left (SL Keybinding: Shift-(A/Left Arrow)) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Move Right (SL Keybinding: Shift-(D/Right Arrow)) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + Not Flying: Jump/Flying: Move Up (SL Keybinding: E) - - Raised when the simulator responds to a request + + Not Flying: Croutch/Flying: Move Down (SL Keybinding: C) - - Raised when the simulator responds to a request + + Unused - - Raised when the simulator responds to a request + + Unused - - Raised when the simulator responds to a request + + Unused - - Raised when the simulator responds to a request + + Unused - - Raised when the simulator responds to a request + + ORed with AGENT_CONTROL_AT_* if the keyboard is being used - - Raised when the simulator responds to a request + + ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used - - Raised when the simulator responds to a Parcel Update request + + ORed with AGENT_CONTROL_UP_* if the keyboard is being used - - Raised when the parcel your agent is located sends a ParcelMediaCommand + + Fly - + - Parcel Accesslist - - Agents + + Finish our current animation - - + + Stand up from the ground or a prim seat - - Flags for specific entry in white/black lists + + Sit on the ground at our current location - - - Owners of primitives on parcel - + + Whether mouselook is currently enabled - - Prim Owners + + Legacy, used if a key was pressed for less than a certain amount of time - - True of owner is group + + Legacy, used if a key was pressed for less than a certain amount of time - - Total count of prims owned by OwnerID + + Legacy, used if a key was pressed for less than a certain amount of time - - true of OwnerID is currently online and is not a group + + Legacy, used if a key was pressed for less than a certain amount of time - - The date of the most recent prim left by OwnerID + + Legacy, used if a key was pressed for less than a certain amount of time - - Contains a parcels dwell data returned from the simulator in response to an + + Legacy, used if a key was pressed for less than a certain amount of time - + - Construct a new instance of the ParcelDwellReplyEventArgs class - The global ID of the parcel - The simulator specific ID of the parcel - The calculated dwell for the parcel - - Get the global ID of the parcel - - - Get the simulator specific ID of the parcel + + + - - Get the calculated dwell + + Set when the avatar is idled or set to away. Note that the away animation is + activated separately from setting this flag - - Contains basic parcel information data returned from the - simulator in response to an request + + + - + - Construct a new instance of the ParcelInfoReplyEventArgs class - The object containing basic parcel info - - Get the object containing basic parcel info + + + - - Contains basic parcel information data returned from the simulator in response to an request + + + - + - Construct a new instance of the ParcelPropertiesEventArgs class + Called once attachment resource usage information has been collected - The object containing the details - The object containing the details - The result of the request - The number of primitieves your agent is - currently selecting and or sitting on in this parcel - The user assigned ID used to correlate a request with - these results - TODO: + Indicates if operation was successfull + Attachment resource usage information - - Get the simulator the parcel is located in + + The event subscribers. null if no subcribers - - Get the object containing the details - If Result is NoData, this object will not contain valid data + + Thread sync lock object - - Get the result of the request + + The event subscribers. null if no subcribers - - Get the number of primitieves your agent is - currently selecting and or sitting on in this parcel + + Thread sync lock object - - Get the user assigned ID used to correlate a request with - these results + + The event subscribers. null if no subcribers - - TODO: + + Thread sync lock object - - Contains blacklist and whitelist data returned from the simulator in response to an request + + The event subscribers. null if no subcribers - - - Construct a new instance of the ParcelAccessListReplyEventArgs class - - The simulator the parcel is located in - The user assigned ID used to correlate a request with - these results - The simulator specific ID of the parcel - TODO: - The list containing the white/blacklisted agents for the parcel + + Thread sync lock object - - Get the simulator the parcel is located in + + The event subscribers. null if no subcribers - - Get the user assigned ID used to correlate a request with - these results + + Thread sync lock object - - Get the simulator specific ID of the parcel + + The event subscribers. null if no subcribers - - TODO: + + Thread sync lock object - - Get the list containing the white/blacklisted agents for the parcel + + The event subscribers. null if no subcribers - - Contains blacklist and whitelist data returned from the - simulator in response to an request + + Thread sync lock object - - - Construct a new instance of the ParcelObjectOwnersReplyEventArgs class - - The simulator the parcel is located in - The list containing prim ownership counts - - - Get the simulator the parcel is located in + + The event subscribers. null if no subcribers - - Get the list containing prim ownership counts + + Thread sync lock object - - Contains the data returned when all parcel data has been retrieved from a simulator + + The event subscribers. null if no subcribers - - - Construct a new instance of the SimParcelsDownloadedEventArgs class - - The simulator the parcel data was retrieved from - The dictionary containing the parcel data - The multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. + + Thread sync lock object - - Get the simulator the parcel data was retrieved from + + The event subscribers. null if no subcribers - - A dictionary containing the parcel data where the key correlates to the ParcelMap entry + + Thread sync lock object - - Get the multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. + + The event subscribers. null if no subcribers - - Contains the data returned when a request + + Thread sync lock object - - - Construct a new instance of the ForceSelectObjectsReplyEventArgs class - - The simulator the parcel data was retrieved from - The list of primitive IDs - true if the list is clean and contains the information - only for a given request + + The event subscribers. null if no subcribers - - Get the simulator the parcel data was retrieved from + + Thread sync lock object - - Get the list of primitive IDs + + The event subscribers. null if no subcribers - - true if the list is clean and contains the information - only for a given request + + Thread sync lock object - - Contains data when the media data for a parcel the avatar is on changes + + The event subscribers. null if no subcribers - - - Construct a new instance of the ParcelMediaUpdateReplyEventArgs class - - the simulator the parcel media data was updated in - The updated media information + + Thread sync lock object - - Get the simulator the parcel media data was updated in + + The event subscribers. null if no subcribers - - Get the updated media information + + Thread sync lock object - - Contains the media command for a parcel the agent is currently on + + The event subscribers. null if no subcribers - - - Construct a new instance of the ParcelMediaCommandEventArgs class - - The simulator the parcel media command was issued in - - - The media command that was sent - + + Thread sync lock object - - Get the simulator the parcel media command was issued in + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - Get the media command that was sent + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - - - + + Thread sync lock object - - - - + + The event subscribers. null if no subcribers - - - - + + Thread sync lock object - - - - + + Reference to the GridClient instance - - - - - - + + Used for movement and camera tracking - - - The ObservableDictionary class is used for storing key/value pairs. It has methods for firing - events to subscribers when items are added, removed, or changed. - - Key - Value + + Currently playing animations for the agent. Can be used to + check the current movement status such as walking, hovering, aiming, + etc. by checking against system animations found in the Animations class - - - A dictionary of callbacks to fire when specified action occurs - + + Dictionary containing current Group Chat sessions and members - - - Register a callback to be fired when an action occurs - - The action - The callback to fire + + Raised when a scripted object or agent within range sends a public message - - - Unregister a callback - - The action - The callback to fire + + Raised when a scripted object sends a dialog box containing possible + options an agent can respond to - - - - - - + + Raised when an object requests a change in the permissions an agent has permitted - - Internal dictionary that this class wraps around. Do not - modify or enumerate the contents of this dictionary without locking + + Raised when a script requests an agent open the specified URL - - - Initializes a new instance of the Class - with the specified key/value, has the default initial capacity. - - - - // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value. - public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(); - - + + Raised when an agents currency balance is updated - - - Initializes a new instance of the Class - with the specified key/value, With its initial capacity specified. - - Initial size of dictionary - - - // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value, - // initially allocated room for 10 entries. - public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(10); - - + + Raised when a transaction occurs involving currency such as a land purchase - - - Try to get entry from the with specified key - - Key to use for lookup - Value returned - if specified key exists, if not found - - - // find your avatar using the Simulator.ObjectsAvatars ObservableDictionary: - Avatar av; - if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) - Console.WriteLine("Found Avatar {0}", av.Name); - - - + + Raised when an ImprovedInstantMessage packet is recieved from the simulator, this is used for everything from + private messaging to friendship offers. The Dialog field defines what type of message has arrived - - - Finds the specified match. - - The match. - Matched value - - - // use a delegate to find a prim in the ObjectsPrimitives ObservableDictionary - // with the ID 95683496 - uint findID = 95683496; - Primitive findPrim = sim.ObjectsPrimitives.Find( - delegate(Primitive prim) { return prim.ID == findID; }); - - + + Raised when an agent has requested a teleport to another location, or when responding to a lure. Raised multiple times + for each teleport indicating the progress of the request - - Find All items in an - return matching items. - a containing found items. - - Find All prims within 20 meters and store them in a List - - int radius = 20; - List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( - delegate(Primitive prim) { - Vector3 pos = prim.Position; - return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); - } - ); - - + + Raised when a simulator sends agent specific information for our avatar. - - Find All items in an - return matching keys. - a containing found keys. - - Find All keys which also exist in another dictionary - - List<UUID> matches = myDict.FindAll( - delegate(UUID id) { - return myOtherDict.ContainsKey(id); - } - ); - - + + Raised when our agents animation playlist changes - - Check if Key exists in Dictionary - Key to check for - if found, otherwise + + Raised when an object or avatar forcefully collides with our agent - - Check if Value exists in Dictionary - Value to check for - if found, otherwise + + Raised when our agent crosses a region border into another region - - - Adds the specified key to the dictionary, dictionary locking is not performed, - - - The key - The value - - - - Removes the specified key, dictionary locking is not performed - - The key. - if successful, otherwise + + Raised when our agent succeeds or fails to join a group chat session - - - Clear the contents of the dictionary - + + Raised when a simulator sends an urgent message usually indication the recent failure of + another action we have attempted to take such as an attempt to enter a parcel where we are denied access - - - Enumerator for iterating dictionary entries - - + + Raised when a script attempts to take or release specified controls for our agent - - - Gets the number of Key/Value pairs contained in the - + + Raised when the simulator detects our agent is trying to view something + beyond its limits - - - Indexer for the dictionary - - The key - The value + + Raised when a script sensor reply is received from a simulator - - - A Wrapper around openjpeg to encode and decode images to and from byte arrays - + + Raised in response to a request - - TGA Header size + + Raised when an avatar enters a group chat session we are participating in - - OpenJPEG is not threadsafe, so this object is used to lock - during calls into unmanaged code + + Raised when an agent exits a group chat session we are participating in - - - Encode a object into a byte array - - The object to encode - true to enable lossless conversion, only useful for small images ie: sculptmaps - A byte array containing the encoded Image object + + Your (client) avatars + "client", "agent", and "avatar" all represent the same thing - - - Encode a object into a byte array - - The object to encode - a byte array of the encoded image + + Temporary assigned to this session, used for + verifying our identity in packets - - - Decode JPEG2000 data to an and - - - JPEG2000 encoded data - ManagedImage object to decode to - Image object to decode to - True if the decode succeeds, otherwise false + + Shared secret that is never sent over the wire - - - - - - - + + Your (client) avatar ID, local to the current region/sim - - - - - - - - + + Where the avatar started at login. Can be "last", "home" + or a login - - - Encode a object into a byte array - - The source object to encode - true to enable lossless decoding - A byte array containing the source Bitmap object + + The access level of this agent, usually M or PG - - - Defines the beginning and ending file positions of a layer in an - LRCP-progression JPEG2000 file - + + The CollisionPlane of Agent - - - This structure is used to marshal both encoded and decoded images. - MUST MATCH THE STRUCT IN dotnet.h! - + + An representing the velocity of our agent - - - Information about a single packet in a JPEG2000 stream - + + An representing the acceleration of our agent - - Packet start position + + A which specifies the angular speed, and axis about which an Avatar is rotating. - - Packet header end position + + Position avatar client will goto when login to 'home' or during + teleport request to 'home' region. - - Packet end position + + LookAt point saved/restored with HomePosition - - - Represents a Sound Asset - + + Avatar First Name (i.e. Philip) - - Initializes a new instance of an AssetSound object + + Avatar Last Name (i.e. Linden) - - Initializes a new instance of an AssetSound object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + Avatar Full Name (i.e. Philip Linden) - - - TODO: Encodes a sound file - + + Gets the health of the agent - - - TODO: Decode a sound file - - true + + Gets the current balance of the agent - - Override the base classes AssetType + + Gets the local ID of the prim the agent is sitting on, + zero if the avatar is not currently sitting - - - Represents a Landmark with RegionID and Position vector - + + Gets the of the agents active group. - - UUID of the Landmark target region + + Gets the Agents powers in the currently active group - - Local position of the target + + Current status message for teleporting - - Construct an Asset of type Landmark + + Current position of the agent as a relative offset from + the simulator, or the parent object if we are sitting on something - - - Construct an Asset object of type Landmark - - A unique specific to this asset - A byte array containing the raw asset data + + Current rotation of the agent as a relative rotation from + the simulator, or the parent object if we are sitting on something - - - Constuct an asset of type Landmark - - UUID of the target region - Local position of landmark + + Current position of the agent in the simulator - + - Encode the raw contents of a string with the specific Landmark format + A representing the agents current rotation - - - Decode the raw asset data, populating the RegionID and Position - - true if the AssetData was successfully decoded to a UUID and Vector + + Returns the global grid position of the avatar - - Override the base classes AssetType + + Raises the ChatFromSimulator event + A ChatEventArgs object containing the + data returned from the data server - - - Represents an that can be worn on an avatar - such as a Shirt, Pants, etc. - + + Raises the ScriptDialog event + A SctriptDialogEventArgs object containing the + data returned from the data server - - - Represents a Wearable Asset, Clothing, Hair, Skin, Etc - + + Raises the ScriptQuestion event + A ScriptQuestionEventArgs object containing the + data returned from the data server - - A string containing the name of the asset + + Raises the LoadURL event + A LoadUrlEventArgs object containing the + data returned from the data server - - A string containing a short description of the asset + + Raises the MoneyBalance event + A BalanceEventArgs object containing the + data returned from the data server - - The Assets WearableType + + Raises the MoneyBalanceReply event + A MoneyBalanceReplyEventArgs object containing the + data returned from the data server - - The For-Sale status of the object + + Raises the IM event + A InstantMessageEventArgs object containing the + data returned from the data server - - An Integer representing the purchase price of the asset + + Raises the TeleportProgress event + A TeleportEventArgs object containing the + data returned from the data server - - The of the assets creator + + Raises the AgentDataReply event + A AgentDataReplyEventArgs object containing the + data returned from the data server - - The of the assets current owner + + Raises the AnimationsChanged event + A AnimationsChangedEventArgs object containing the + data returned from the data server - - The of the assets prior owner + + Raises the MeanCollision event + A MeanCollisionEventArgs object containing the + data returned from the data server - - The of the Group this asset is set to + + Raises the RegionCrossed event + A RegionCrossedEventArgs object containing the + data returned from the data server - - True if the asset is owned by a + + Raises the GroupChatJoined event + A GroupChatJoinedEventArgs object containing the + data returned from the data server - - The Permissions mask of the asset + + Raises the AlertMessage event + A AlertMessageEventArgs object containing the + data returned from the data server - - A Dictionary containing Key/Value pairs of the objects parameters + + Raises the ScriptControlChange event + A ScriptControlEventArgs object containing the + data returned from the data server - - A Dictionary containing Key/Value pairs where the Key is the textures Index and the Value is the Textures + + Raises the CameraConstraint event + A CameraConstraintEventArgs object containing the + data returned from the data server - - Initializes a new instance of an AssetWearable object + + Raises the ScriptSensorReply event + A ScriptSensorReplyEventArgs object containing the + data returned from the data server - - Initializes a new instance of an AssetWearable object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + Raises the AvatarSitResponse event + A AvatarSitResponseEventArgs object containing the + data returned from the data server - - Initializes a new instance of an AssetWearable object with parameters - A string containing the asset parameters + + Raises the ChatSessionMemberAdded event + A ChatSessionMemberAddedEventArgs object containing the + data returned from the data server - + + Raises the ChatSessionMemberLeft event + A ChatSessionMemberLeftEventArgs object containing the + data returned from the data server + + - Decode an assets byte encoded data to a string + Send a text message from the Agent to the Simulator - true if the asset data was decoded successfully + A containing the message + The channel to send the message on, 0 is the public channel. Channels above 0 + can be used however only scripts listening on the specified channel will see the message + Denotes the type of message being sent, shout, whisper, etc. - + - Encode the assets string represantion into a format consumable by the asset server + Request any instant messages sent while the client was offline to be resent. - - Initializes a new instance of an AssetScriptBinary object - - - Initializes a new instance of an AssetScriptBinary object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - Initializes a new instance of an AssetScriptBinary object with parameters - A string containing the Clothings data - - - Override the base classes AssetType - - + - Represents an Animation + Send an Instant Message to another Avatar + The recipients + A containing the message to send - - Default Constructor + + + Send an Instant Message to an existing group chat or conference chat + + The recipients + A containing the message to send + IM session ID (to differentiate between IM windows) - + - Construct an Asset object of type Animation + Send an Instant Message - A unique specific to this asset - A byte array containing the raw asset data + The name this IM will show up as being from + Key of Avatar + Text message being sent + IM session ID (to differentiate between IM windows) + IDs of sessions for a conference - - Override the base classes AssetType + + + Send an Instant Message + + The name this IM will show up as being from + Key of Avatar + Text message being sent + IM session ID (to differentiate between IM windows) + Type of instant message to send + Whether to IM offline avatars as well + Senders Position + RegionID Sender is In + Packed binary data that is specific to + the dialog type - + - Operation to apply when applying color to texture + Send an Instant Message to a group + + of the group to send message to + Text Message being sent. - + - Information needed to translate visual param value to RGBA color + Send an Instant Message to a group the agent is a member of + The name this IM will show up as being from + + of the group to send message to + Text message being sent - + - Construct VisualColorParam + Send a request to join a group chat session - Operation to apply when applying color to texture - Colors + + of Group to leave - + - Represents alpha blending and bump infor for a visual parameter - such as sleive length + Exit a group chat session. This will stop further Group chat messages + from being sent until session is rejoined. + + of Group chat session to leave - - Stregth of the alpha to apply + + + Reply to script dialog questions. + + Channel initial request came on + Index of button you're "clicking" + Label of button you're "clicking" + + of Object that sent the dialog request + - - File containing the alpha channel + + + Accept invite for to a chatterbox session + + + of session to accept invite to - - Skip blending if parameter value is 0 + + + Start a friends conference + + + List of UUIDs to start a conference with + the temportary session ID returned in the callback> - - Use miltiply insted of alpha blending + + + Start a particle stream between an agent and an object + + + Key of the source agent + + Key of the target object + + + The type from the enum + A unique for this effect - + - Create new alhpa information for a visual param + Start a particle stream between an agent and an object - Stregth of the alpha to apply - File containing the alpha channel - Skip blending if parameter value is 0 - Use miltiply insted of alpha blending + + Key of the source agent + + Key of the target object + A representing the beams offset from the source + A which sets the avatars lookat animation + + of the Effect - + - A single visual characteristic of an avatar mesh, such as eyebrow height + Create a particle beam between an avatar and an primitive + The ID of source avatar + The ID of the target primitive + global offset + A object containing the combined red, green, blue and alpha + color values of particle beam + a float representing the duration the parcicle beam will last + A Unique ID for the beam + - - Index of this visual param + + + Create a particle swirl around a target position using a packet + + global offset + A object containing the combined red, green, blue and alpha + color values of particle beam + a float representing the duration the parcicle beam will last + A Unique ID for the beam - - Internal name + + + Sends a request to sit on the specified object + + + of the object to sit on + Sit at offset - - Group ID this parameter belongs to + + + Follows a call to to actually sit on the object + - - Name of the wearable this parameter belongs to + + Stands up from sitting on a prim or the ground + true of AgentUpdate was sent - - Displayable label of this characteristic + + + Does a "ground sit" at the avatar's current position + - - Displayable label for the minimum value of this characteristic + + + Starts or stops flying + + True to start flying, false to stop flying - - Displayable label for the maximum value of this characteristic + + + Starts or stops crouching + + True to start crouching, false to stop crouching - - Default value + + + Starts a jump (begin holding the jump key) + - - Minimum value + + + Use the autopilot sim function to move the avatar to a new + position. Uses double precision to get precise movements + + The z value is currently not handled properly by the simulator + Global X coordinate to move to + Global Y coordinate to move to + Z coordinate to move to - - Maximum value + + + Use the autopilot sim function to move the avatar to a new position + + The z value is currently not handled properly by the simulator + Integer value for the global X coordinate to move to + Integer value for the global Y coordinate to move to + Floating-point value for the Z coordinate to move to - - Is this param used for creation of bump layer? - - - Alpha blending/bump info - - - Color information + + + Use the autopilot sim function to move the avatar to a new position + + The z value is currently not handled properly by the simulator + Integer value for the local X coordinate to move to + Integer value for the local Y coordinate to move to + Floating-point value for the Z coordinate to move to - - Array of param IDs that are drivers for this parameter + + Macro to cancel autopilot sim function + Not certain if this is how it is really done + true if control flags were set and AgentUpdate was sent to the simulator - + - Set all the values through the constructor + Grabs an object - Index of this visual param - Internal name - - - Displayable label of this characteristic - Displayable label for the minimum value of this characteristic - Displayable label for the maximum value of this characteristic - Default value - Minimum value - Maximum value - Is this param used for creation of bump layer? - Array of param IDs that are drivers for this parameter - Alpha blending/bump info - Color information + an unsigned integer of the objects ID within the simulator + - + - Holds the Params array of all the avatar appearance parameters + Overload: Grab a simulated object + an unsigned integer of the objects ID within the simulator + + + The texture coordinates to grab + The surface coordinates to grab + The face of the position to grab + The region coordinates of the position to grab + The surface normal of the position to grab (A normal is a vector perpindicular to the surface) + The surface binormal of the position to grab (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - - X position of this patch - - - Y position of this patch - - - A 16x16 array of floats holding decompressed layer data - - + - Creates a LayerData packet for compressed land data given a full - simulator heightmap and an array of indices of patches to compress + Drag an object - A 256 * 256 array of floating point values - specifying the height at each meter in the simulator - Array of indexes in the 16x16 grid of patches - for this simulator. For example if 1 and 17 are specified, patches - x=1,y=0 and x=1,y=1 are sent - + + of the object to drag + Drag target in region coordinates - + - Add a patch of terrain to a BitPacker + Overload: Drag an object - BitPacker to write the patch to - Heightmap of the simulator, must be a 256 * - 256 float array - X offset of the patch to create, valid values are - from 0 to 15 - Y offset of the patch to create, valid values are - from 0 to 15 + + of the object to drag + Drag target in region coordinates + + + The texture coordinates to grab + The surface coordinates to grab + The face of the position to grab + The region coordinates of the position to grab + The surface normal of the position to grab (A normal is a vector perpindicular to the surface) + The surface binormal of the position to grab (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - + - A Name Value pair with additional settings, used in the protocol - primarily to transmit avatar names and active group in object packets + Release a grabbed object + The Objects Simulator Local ID + + + - - - - - - - - - - - - - - - - + - Constructor that takes all the fields as parameters + Release a grabbed object - - - - - + The Objects Simulator Local ID + The texture coordinates to grab + The surface coordinates to grab + The face of the position to grab + The region coordinates of the position to grab + The surface normal of the position to grab (A normal is a vector perpindicular to the surface) + The surface binormal of the position to grab (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - + - Constructor that takes a single line from a NameValue field + Touches an object - - - - Type of the value - - - Unknown - - - String value - - - - - - - - - - - - - - - Deprecated - - - String value, but designated as an asset - - - + an unsigned integer of the objects ID within the simulator + - + - + Request the current L$ balance - - - - - - - - - - - - - + - + Give Money to destination Avatar + UUID of the Target Avatar + Amount in L$ - - - - - - - - - - - - - - - - + - Starts a thread that keeps the daemon running + Give Money to destination Avatar - - + UUID of the Target Avatar + Amount in L$ + Description that will show up in the + recipients transaction history - + - Stops the daemon and the thread keeping it running + Give L$ to an object + object to give money to + amount of L$ to give + name of object - + - + Give L$ to a group - - - + group to give money to + amount of L$ to give - + - This is used to initialize and stop the Connector as a whole. The Connector - Create call must be completed successfully before any other requests are made - (typically during application initialization). The shutdown should be called - when the application is shutting down to gracefully release resources + Give L$ to a group - A string value indicting the Application name - URL for the management server - LoggingSettings - - + group to give money to + amount of L$ to give + description of transaction - + - Shutdown Connector -- Should be called when the application is shutting down - to gracefully release resources + Pay texture/animation upload fee - Handle returned from successful Connector ‘create’ request - + - Mute or unmute the microphone + Pay texture/animation upload fee - Handle returned from successful Connector ‘create’ request - true (mute) or false (unmute) + description of the transaction - + - Mute or unmute the speaker + Give Money to destination Object or Avatar - Handle returned from successful Connector ‘create’ request - true (mute) or false (unmute) + UUID of the Target Object/Avatar + Amount in L$ + Reason (Optional normally) + The type of transaction + Transaction flags, mostly for identifying group + transactions - + - Set microphone volume + Plays a gesture - Handle returned from successful Connector ‘create’ request - The level of the audio, a number between -100 and 100 where - 0 represents ‘normal’ speaking volume + Asset of the gesture - + - Set local speaker volume + Mark gesture active - Handle returned from successful Connector ‘create’ request - The level of the audio, a number between -100 and 100 where - 0 represents ‘normal’ speaking volume + Inventory of the gesture + Asset of the gesture - + - Create a Session - Sessions typically represent a connection to a media session with one or more - participants. This is used to generate an ‘outbound’ call to another user or - channel. The specifics depend on the media types involved. A session handle is - required to control the local user functions within the session (or remote - users if the current account has rights to do so). Currently creating a - session automatically connects to the audio media, there is no need to call - Session.Connect at this time, this is reserved for future use. + Mark gesture inactive - Handle returned from successful Connector ‘create’ request - This is the URI of the terminating point of the session (ie who/what is being called) - This is the display name of the entity being called (user or channel) - Only needs to be supplied when the target URI is password protected - This indicates the format of the password as passed in. This can either be - “ClearText†or “SHA1UserNameâ€. If this element does not exist, it is assumed to be “ClearTextâ€. If it is - “SHA1UserNameâ€, the password as passed in is the SHA1 hash of the password and username concatenated together, - then base64 encoded, with the final “=†character stripped off. - - - + Inventory of the gesture - + - Used to accept a call + Send an AgentAnimation packet that toggles a single animation on - SessionHandle such as received from SessionNewEvent - "default" - + The of the animation to start playing + Whether to ensure delivery of this packet or not - + - This command is used to start the audio render process, which will then play - the passed in file through the selected audio render device. This command - should not be issued if the user is on a call. + Send an AgentAnimation packet that toggles a single animation off - The fully qualified path to the sound file. - True if the file is to be played continuously and false if it is should be played once. - + The of a + currently playing animation to stop playing + Whether to ensure delivery of this packet or not - + - This command is used to stop the audio render process. + Send an AgentAnimation packet that will toggle animations on or off - The fully qualified path to the sound file issued in the start render command. - + A list of animation s, and whether to + turn that animation on or off + Whether to ensure delivery of this packet or not - + - This is used to ‘end’ an established session (i.e. hang-up or disconnect). + Teleports agent to their stored home location - Handle returned from successful Session ‘create’ request or a SessionNewEvent - + true on successful teleport to home location - + - Set the combined speaking and listening position in 3D space. + Teleport agent to a landmark - Handle returned from successful Session ‘create’ request or a SessionNewEvent - Speaking position - Listening position - + + of the landmark to teleport agent to + true on success, false on failure - + - Set User Volume for a particular user. Does not affect how other users hear that user. + Attempt to look up a simulator name and teleport to the discovered + destination - Handle returned from successful Session ‘create’ request or a SessionNewEvent - - The level of the audio, a number between -100 and 100 where 0 represents ‘normal’ speaking volume - + Region name to look up + Position to teleport to + True if the lookup and teleport were successful, otherwise + false - + - Start up the Voice service. + Attempt to look up a simulator name and teleport to the discovered + destination + Region name to look up + Position to teleport to + Target to look at + True if the lookup and teleport were successful, otherwise + false - + - Handle miscellaneous request status + Teleport agent to another region - - - ///If something goes wrong, we log it. + handle of region to teleport agent to + + position in destination sim to teleport to + true on success, false on failure + This call is blocking - + - Cleanup oject resources + Teleport agent to another region + handle of region to teleport agent to + + position in destination sim to teleport to + + direction in destination sim agent will look at + true on success, false on failure + This call is blocking - + - Request voice cap when changing regions + Request teleport to a another simulator + handle of region to teleport agent to + + position in destination sim to teleport to - + - Handle a change in session state + Request teleport to a another simulator + handle of region to teleport agent to + + position in destination sim to teleport to + + direction in destination sim agent will look at - + - Close a voice session + Teleport agent to a landmark - + + of the landmark to teleport agent to - + - Locate a Session context from its handle + Send a teleport lure to another avatar with default "Join me in ..." invitation message - Creates the session context if it does not exist. + target avatars to lure - + - Handle completion of main voice cap request. + Send a teleport lure to another avatar with custom invitation message - - - + target avatars to lure + custom message to send with invitation - + - Daemon has started so connect to it. + Respond to a teleport lure by either accepting it and initiating + the teleport, or denying it + + of the avatar sending the lure + true to accept the lure, false to decline it - + - The daemon TCP connection is open. + Update agent profile + + struct containing updated + profile information - + - Handle creation of the Connector. + Update agents profile interests + selection of interests from struct - + - Handle response to audio output device query + Set the height and the width of the client window. This is used + by the server to build a virtual camera frustum for our avatar + New height of the viewer window + New width of the viewer window - + - Handle response to audio input device query + Request the list of muted objects and avatars for this agent - - - Set voice channel for new parcel - - + + + Sets home location to agents current position + + will fire an AlertMessage () with + success or failure message - + - Request info from a parcel capability Uri. + Move an agent in to a simulator. This packet is the last packet + needed to complete the transition in to a new simulator - + + Object - + - Receive parcel voice cap + Reply to script permissions request - - - + + Object + + of the itemID requesting permissions + + of the taskID requesting permissions + + list of permissions to allow - + - Tell Vivox where we are standing + Respond to a group invitation by either accepting or denying it - This has to be called when we move or turn. + UUID of the group (sent in the AgentID field of the invite message) + IM Session ID from the group invitation message + Accept the group invitation or deny it - + - Start and stop updating out position. + Requests script detection of objects and avatars - + name of the object/avatar to search for + UUID of the object or avatar to search for + Type of search from ScriptSensorTypeFlags + range of scan (96 max?) + the arc in radians to search within + an user generated ID to correlate replies with + Simulator to perform search in - + - This is used to login a specific user account(s). It may only be called after - Connector initialization has completed successfully + Create or update profile pick - Handle returned from successful Connector ‘create’ request - User's account name - User's account password - Values may be “AutoAnswer†or “VerifyAnswer†- "" - This is an integer that specifies how often - the daemon will send participant property events while in a channel. If this is not set - the default will be “on state changeâ€, which means that the events will be sent when - the participant starts talking, stops talking, is muted, is unmuted. - The valid values are: - 0 – Never - 5 – 10 times per second - 10 – 5 times per second - 50 – 1 time per second - 100 – on participant state change (this is the default) - false - + UUID of the pick to update, or random UUID to create a new pick + Is this a top pick? (typically false) + UUID of the parcel (UUID.Zero for the current parcel) + Name of the pick + Global position of the pick landmark + UUID of the image displayed with the pick + Long description of the pick - + - This is used to logout a user session. It should only be called with a valid AccountHandle. + Delete profile pick - Handle returned from successful Connector ‘login’ request - + UUID of the pick to delete - + - This is used to get a list of audio devices that can be used for capture (input) of voice. + Create or update profile Classified - + UUID of the classified to update, or random UUID to create a new classified + Defines what catagory the classified is in + UUID of the image displayed with the classified + Price that the classified will cost to place for a week + Global position of the classified landmark + Name of the classified + Long description of the classified + if true, auto renew classified after expiration - + - This is used to get a list of audio devices that can be used for render (playback) of voice. + Create or update profile Classified + UUID of the classified to update, or random UUID to create a new classified + Defines what catagory the classified is in + UUID of the image displayed with the classified + Price that the classified will cost to place for a week + Name of the classified + Long description of the classified + if true, auto renew classified after expiration - + - This command is used to select the render device. + Delete a classified ad - The name of the device as returned by the Aux.GetRenderDevices command. + The classified ads ID - + - This command is used to select the capture device. + Fetches resource usage by agents attachmetns - The name of the device as returned by the Aux.GetCaptureDevices command. + Called when the requested information is collected - + - This command is used to start the audio capture process which will cause - AuxAudioProperty Events to be raised. These events can be used to display a - microphone VU meter for the currently selected capture device. This command - should not be issued if the user is on a call. + Take an incoming ImprovedInstantMessage packet, auto-parse, and if + OnInstantMessage is defined call that with the appropriate arguments - (unused but required) - + The sender + The EventArgs object containing the packet data - + - This command is used to stop the audio capture process. + Take an incoming Chat packet, auto-parse, and if OnChat is defined call + that with the appropriate arguments. - + The sender + The EventArgs object containing the packet data - + - This command is used to set the mic volume while in the audio tuning process. - Once an acceptable mic level is attained, the application must issue a - connector set mic volume command to have that level be used while on voice - calls. + Used for parsing llDialogs - the microphone volume (-100 to 100 inclusive) - + The sender + The EventArgs object containing the packet data - + - This command is used to set the speaker volume while in the audio tuning - process. Once an acceptable speaker level is attained, the application must - issue a connector set speaker volume command to have that level be used while - on voice calls. + Used for parsing llRequestPermissions dialogs - the speaker volume (-100 to 100 inclusive) - + The sender + The EventArgs object containing the packet data - + - Event for most mundane request reposnses. + Handles Script Control changes when Script with permissions releases or takes a control + The sender + The EventArgs object containing the packet data - - Response to Connector.Create request + + + Used for parsing llLoadURL Dialogs + + The sender + The EventArgs object containing the packet data - - Response to Aux.GetCaptureDevices request - - - Response to Aux.GetRenderDevices request + + + Update client's Position, LookAt and region handle from incoming packet + + The sender + The EventArgs object containing the packet data + This occurs when after an avatar moves into a new sim - - Audio Properties Events are sent after audio capture is started. - These events are used to display a microphone VU meter + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Response to Account.Login request + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - This event message is sent whenever the login state of the - particular Account has transitioned from one value to another + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - List of audio input devices + Process TeleportFailed message sent via EventQueue, informs agent its last teleport has failed and why. + The Message Key + An IMessage object Deserialized from the recieved message event + The simulator originating the event message - + - List of audio output devices + Process TeleportFinish from Event Queue and pass it onto our TeleportHandler + The message system key for this event + IMessage object containing decoded data from OSD + The simulator originating the event message - - - Set audio test mode - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Enable logging + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - The folder where any logs will be created + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - This will be prepended to beginning of each log file + + + Crossed region handler for message that comes across the EventQueue. Sent to an agent + when the agent crosses a sim border into a new region. + + The message key + the IMessage object containing the deserialized data sent from the simulator + The which originated the packet - - The suffix or extension to be appended to each log file + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + This packet is now being sent via the EventQueue - + - 0: NONE - No logging - 1: ERROR - Log errors only - 2: WARNING - Log errors and warnings - 3: INFO - Log errors, warnings and info - 4: DEBUG - Log errors, warnings, info and debug + Group Chat event handler + The capability Key + IMessage object containing decoded data from OSD + + - + - Constructor for default logging settings + Response from request to join a group chat + + + IMessage object containing decoded data from OSD + + - - Audio Properties Events are sent after audio capture is started. These events are used to display a microphone VU meter - - + - Interface requirements for Messaging system + Someone joined or left group chat + + + IMessage object containing decoded data from OSD + + - + - The current status of a texture request as it moves through the pipeline or final result of a texture request. + Handle a group chat Invitation + Caps Key + IMessage object containing decoded data from OSD + Originating Simulator - - The initial state given to a request. Requests in this state - are waiting for an available slot in the pipeline - - - A request that has been added to the pipeline and the request packet - has been sent to the simulator - - - A request that has received one or more packets back from the simulator + + + Moderate a chat session + + the of the session to moderate, for group chats this will be the groups UUID + the of the avatar to moderate + Either "voice" to moderate users voice, or "text" to moderate users text session + true to moderate (silence user), false to allow avatar to speak - - A request that has received all packets back from the simulator + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - A request that has taken longer than - to download OR the initial packet containing the packet information was never received + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - The texture request was aborted by request of the agent + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - The simulator replied to the request that it was not able to find the requested texture + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - A callback fired to indicate the status or final state of the requested texture. For progressive - downloads this will fire each time new asset data is returned from the simulator. - The indicating either Progress for textures not fully downloaded, - or the final result of the request after it has been processed through the TexturePipeline - The object containing the Assets ID, raw data - and other information. For progressive rendering the will contain - the data from the beginning of the file. For failed, aborted and timed out requests it will contain - an empty byte array. - + - Texture request download handler, allows a configurable number of download slots which manage multiple - concurrent texture downloads from the + Construct a new instance of the ChatEventArgs object - This class makes full use of the internal - system for full texture downloads. + Sim from which the message originates + The message sent + The audible level of the message + The type of message sent: whisper, shout, etc + The source type of the message sender + The name of the agent or object sending the message + The ID of the agent or object sending the message + The ID of the object owner, or the agent ID sending the message + The position of the agent or object sending the message - - A dictionary containing all pending and in-process transfer requests where the Key is both the RequestID - and also the Asset Texture ID, and the value is an object containing the current state of the request and also - the asset data as it is being re-assembled + + Get the simulator sending the message - - Holds the reference to the client object + + Get the message sent - - Maximum concurrent texture requests allowed at a time + + Get the audible level of the message - - An array of objects used to manage worker request threads + + Get the type of message sent: whisper, shout, etc - - An array of worker slots which shows the availablity status of the slot + + Get the source type of the message sender - - The primary thread which manages the requests. + + Get the name of the agent or object sending the message - - true if the TexturePipeline is currently running + + Get the ID of the agent or object sending the message - - A synchronization object used by the primary thread + + Get the ID of the object owner, or the agent ID sending the message - - A refresh timer used to increase the priority of stalled requests + + Get the position of the agent or object sending the message - - - Default constructor, Instantiates a new copy of the TexturePipeline class - - Reference to the instantiated object + + Contains the data sent when a primitive opens a dialog with this agent - + - Initialize callbacks required for the TexturePipeline to operate + Construct a new instance of the ScriptDialogEventArgs + The dialog message + The name of the object that sent the dialog request + The ID of the image to be displayed + The ID of the primitive sending the dialog + The first name of the senders owner + The last name of the senders owner + The communication channel the dialog was sent on + The string labels containing the options presented in this dialog - - - Shutdown the TexturePipeline and cleanup any callbacks or transfers - + + Get the dialog message - - - Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - A float indicating the requested priority for the transfer. Higher priority values tell the simulator - to prioritize the request before lower valued requests. An image already being transferred using the can have - its priority changed by resending the request with the new priority value - Number of quality layers to discard. - This controls the end marker of the data sent - The packet number to begin the request at. A value of 0 begins the request - from the start of the asset texture - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request + + Get the name of the object that sent the dialog request - - - Sends the actual request packet to the simulator - - The image to download - Type of the image to download, either a baked - avatar texture or a normal texture - Priority level of the download. Default is - 1,013,000.0f - Number of quality layers to discard. - This controls the end marker of the data sent - Packet number to start the download at. - This controls the start marker of the data sent - Sending a priority of 0 and a discardlevel of -1 aborts - download - - - - Cancel a pending or in process texture request - - The texture assets unique ID + + Get the ID of the image to be displayed - - - Master Download Thread, Queues up downloads in the threadpool - + + Get the ID of the primitive sending the dialog - - - The worker thread that sends the request and handles timeouts - - A object containing the request details + + Get the first name of the senders owner - - - Handle responses from the simulator that tell us a texture we have requested is unable to be located - or no longer exists. This will remove the request from the pipeline and free up a slot if one is in use - - The sender - The EventArgs object containing the packet data + + Get the last name of the senders owner - - - Handles the remaining Image data that did not fit in the initial ImageData packet - - The sender - The EventArgs object containing the packet data + + Get the communication channel the dialog was sent on, responses + should also send responses on this same channel - - - Handle the initial ImageDataPacket sent from the simulator - - The sender - The EventArgs object containing the packet data + + Get the string labels containing the options presented in this dialog - - Current number of pending and in-process transfers + + Contains the data sent when a primitive requests debit or other permissions + requesting a YES or NO answer - + - A request task containing information and status of a request as it is processed through the + Construct a new instance of the ScriptQuestionEventArgs + The simulator containing the object sending the request + The ID of the script making the request + The ID of the primitive containing the script making the request + The name of the primitive making the request + The name of the owner of the object making the request + The permissions being requested - - The current which identifies the current status of the request - - - The Unique Request ID, This is also the Asset ID of the texture being requested + + Get the simulator containing the object sending the request - - The slot this request is occupying in the threadpoolSlots array + + Get the ID of the script making the request - - The ImageType of the request. + + Get the ID of the primitive containing the script making the request - - The callback to fire when the request is complete, will include - the and the - object containing the result data + + Get the name of the primitive making the request - - If true, indicates the callback will be fired whenever new data is returned from the simulator. - This is used to progressively render textures as portions of the texture are received. + + Get the name of the owner of the object making the request - - An object that maintains the data of an request thats in-process. + + Get the permissions being requested - - - Type of gesture step - + + Contains the data sent when a primitive sends a request + to an agent to open the specified URL - + - Base class for gesture steps + Construct a new instance of the LoadUrlEventArgs + The name of the object sending the request + The ID of the object sending the request + The ID of the owner of the object sending the request + True if the object is owned by a group + The message sent with the request + The URL the object sent - - - Retururns what kind of gesture step this is - + + Get the name of the object sending the request - - - Describes animation step of a gesture - + + Get the ID of the object sending the request - - - If true, this step represents start of animation, otherwise animation stop - + + Get the ID of the owner of the object sending the request - - - Animation asset - + + True if the object is owned by a group - - - Animation inventory name - + + Get the message sent with the request - - - Returns what kind of gesture step this is - + + Get the URL the object sent - - - Describes sound step of a gesture - + + The date received from an ImprovedInstantMessage - + - Sound asset + Construct a new instance of the InstantMessageEventArgs object + the InstantMessage object + the simulator where the InstantMessage origniated - - - Sound inventory name - + + Get the InstantMessage object - - - Returns what kind of gesture step this is - + + Get the simulator where the InstantMessage origniated - - - Describes sound step of a gesture - + + Contains the currency balance - + - Text to output in chat + Construct a new BalanceEventArgs object + The currenct balance - + - Returns what kind of gesture step this is + Get the currenct balance - - - Describes sound step of a gesture - + + Contains the transaction summary when an item is purchased, + money is given, or land is purchased - + - If true in this step we wait for all animations to finish + Construct a new instance of the MoneyBalanceReplyEventArgs object + The ID of the transaction + True of the transaction was successful + The current currency balance + The meters credited + The meters comitted + A brief description of the transaction - - - If true gesture player should wait for the specified amount of time - + + Get the ID of the transaction - - - Time in seconds to wait if WaitForAnimation is false - + + True of the transaction was successful - - - Returns what kind of gesture step this is - + + Get the remaining currency balance - - - Describes the final step of a gesture - + + Get the meters credited - - - Returns what kind of gesture step this is - + + Get the meters comitted - - - Represents a sequence of animations, sounds, and chat actions - + + Get the description of the transaction - - - Keyboard key that triggers the gestyre - + + Data sent from the simulator containing information about your agent and active group information - + - Modifier to the trigger key + Construct a new instance of the AgentDataReplyEventArgs object + The agents first name + The agents last name + The agents active group ID + The group title of the agents active group + The combined group powers the agent has in the active group + The name of the group the agent has currently active - - - String that triggers playing of the gesture sequence - + + Get the agents first name - - - Text that replaces trigger in chat once gesture is triggered - + + Get the agents last name - - - Sequence of gesture steps - + + Get the active group ID of your agent - - - Constructs guesture asset - + + Get the active groups title of your agent - - - Constructs guesture asset - - A unique specific to this asset - A byte array containing the raw asset data + + Get the combined group powers of your agent - - - Encodes gesture asset suitable for uplaod - + + Get the active group name of your agent - - - Decodes gesture assset into play sequence - - true if the asset data was decoded successfully + + Data sent by the simulator to indicate the active/changed animations + applied to your agent - + - Returns asset type + Construct a new instance of the AnimationsChangedEventArgs class + The dictionary that contains the changed animations - - - Permissions for control of object media - + + Get the dictionary that contains the changed animations - + - Style of cotrols that shold be displayed to the user + Data sent from a simulator indicating a collision with your agent - + - Class representing media data for a single face + Construct a new instance of the MeanCollisionEventArgs class + The type of collision that occurred + The ID of the agent or object that perpetrated the agression + The ID of the Victim + The strength of the collision + The Time the collision occurred - - Is display of the alternative image enabled + + Get the Type of collision - - Should media auto loop + + Get the ID of the agent or object that collided with your agent - - Shoule media be auto played + + Get the ID of the agent that was attacked - - Auto scale media to prim face + + A value indicating the strength of the collision - - Should viewer automatically zoom in on the face when clicked + + Get the time the collision occurred - - Should viewer interpret first click as interaction with the media - or when false should the first click be treated as zoom in commadn + + Data sent to your agent when it crosses region boundaries - - Style of controls viewer should display when - viewer media on this face + + + Construct a new instance of the RegionCrossedEventArgs class + + The simulator your agent just left + The simulator your agent is now in - - Starting URL for the media + + Get the simulator your agent just left - - Currently navigated URL + + Get the simulator your agent is now in - - Media height in pixes + + Data sent from the simulator when your agent joins a group chat session - - Media width in pixels + + + Construct a new instance of the GroupChatJoinedEventArgs class + + The ID of the session + The name of the session + A temporary session id used for establishing new sessions + True of your agent successfully joined the session - - Who can controls the media + + Get the ID of the group chat session - - Who can interact with the media + + Get the name of the session - - Is URL whitelist enabled + + Get the temporary session ID used for establishing new sessions - - Array of URLs that are whitelisted + + True if your agent successfully joined the session - + + Data sent by the simulator containing urgent messages + + - Serialize to OSD + Construct a new instance of the AlertMessageEventArgs class - OSDMap with the serialized data + The alert message - + + Get the alert message + + + Data sent by a script requesting to take or release specified controls to your agent + + - Deserialize from OSD data + Construct a new instance of the ScriptControlEventArgs class - Serialized OSD data - Deserialized object + The controls the script is attempting to take or release to the agent + True if the script is passing controls back to the agent + True if the script is requesting controls be released to the script - + + Get the controls the script is attempting to take or release to the agent + + + True if the script is passing controls back to the agent + + + True if the script is requesting controls be released to the script + + - Particle system specific enumerators, flags and methods. + Data sent from the simulator to an agent to indicate its view limits - + - Current version of the media data for the prim + Construct a new instance of the CameraConstraintEventArgs class + The collision plane - + + Get the collision plane + + - Array of media entries indexed by face number + Data containing script sensor requests which allow an agent to know the specific details + of a primitive sending script sensor requests - - + + + Construct a new instance of the ScriptSensorReplyEventArgs + + The ID of the primitive sending the sensor + The ID of the group associated with the primitive + The name of the primitive sending the sensor + The ID of the primitive sending the sensor + The ID of the owner of the primitive sending the sensor + The position of the primitive sending the sensor + The range the primitive specified to scan + The rotation of the primitive sending the sensor + The type of sensor the primitive sent + The velocity of the primitive sending the sensor - - + + Get the ID of the primitive sending the sensor - - + + Get the ID of the group associated with the primitive - - + + Get the name of the primitive sending the sensor - - + + Get the ID of the primitive sending the sensor - - + + Get the ID of the owner of the primitive sending the sensor - - + + Get the position of the primitive sending the sensor - - + + Get the range the primitive specified to scan - - + + Get the rotation of the primitive sending the sensor - - Foliage type for this primitive. Only applicable if this - primitive is foliage + + Get the type of sensor the primitive sent - - Unknown + + Get the velocity of the primitive sending the sensor - - + + Contains the response data returned from the simulator in response to a - - + + Construct a new instance of the AvatarSitResponseEventArgs object - - + + Get the ID of the primitive the agent will be sitting on - - + + True if the simulator Autopilot functions were involved - - + + Get the camera offset of the agent when seated - - + + Get the camera eye offset of the agent when seated - - + + True of the agent will be in mouselook mode when seated - - + + Get the position of the agent when seated - - - - - - - - - - - - - - Identifies the owner if audio or a particle system is - active - - - - - - - - - - - - + + Get the rotation of the agent when seated - - + + Data sent when an agent joins a chat session your agent is currently participating in - - + + + Construct a new instance of the ChatSessionMemberAddedEventArgs object + + The ID of the chat session + The ID of the agent joining - - + + Get the ID of the chat session - - + + Get the ID of the agent that joined - - + + Data sent when an agent exits a chat session your agent is currently participating in - - + + + Construct a new instance of the ChatSessionMemberLeftEventArgs object + + The ID of the chat session + The ID of the Agent that left - - + + Get the ID of the chat session - - + + Get the ID of the agent that left - + - Default constructor + Throttles the network traffic for various different traffic types. + Access this class through GridClient.Throttle - + - Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew - parameters in to signed eight bit values + Default constructor, uses a default high total of 1500 KBps (1536000) - Floating point parameter to pack - Signed eight bit value containing the packed parameter - + - Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew - parameters from signed eight bit integers to floating point values + Constructor that decodes an existing AgentThrottle packet in to + individual values - Signed eight bit value to unpack - Unpacked floating point value - - - Uses basic heuristics to estimate the primitive shape + Reference to the throttle data in an AgentThrottle + packet + Offset position to start reading at in the + throttle data + This is generally not needed in clients as the server will + never send a throttle packet to the client - - - Texture animation mode - + + Maximum bits per second for resending unacknowledged packets - - Disable texture animation + + Maximum bits per second for LayerData terrain - - Enable texture animation + + Maximum bits per second for LayerData wind data - - Loop when animating textures + + Maximum bits per second for LayerData clouds - - Animate in reverse direction + + Unknown, includes object data - - Animate forward then reverse + + Maximum bits per second for textures - - Slide texture smoothly instead of frame-stepping + + Maximum bits per second for downloaded assets - - Rotate texture instead of using frames + + Maximum bits per second the entire connection, divided up + between invidiual streams using default multipliers - - Scale texture instead of using frames + + + Send an AgentThrottle packet to the current server using the + current values + - + - A single textured face. Don't instantiate this class yourself, use the - methods in TextureEntry + Send an AgentThrottle packet to the specified server using the + current values - + - Contains the definition for individual faces + Convert the current throttle values to a byte array that can be put + in an AgentThrottle packet - + Byte array containing all the throttle values - + - + Static pre-defined animations available to all agents - - - + + Agent with afraid expression on face - - + + Agent aiming a bazooka (right handed) - - + + Agent aiming a bow (left handed) - - + + Agent aiming a hand gun (right handed) - - + + Agent aiming a rifle (right handed) - - + + Agent with angry expression on face - - + + Agent hunched over (away) - - + + Agent doing a backflip - - + + Agent laughing while holding belly - - + + Agent blowing a kiss - - In the future this will specify whether a webpage is - attached to this face + + Agent with bored expression on face - - + + Agent bowing to audience - - - Represents all of the texturable faces for an object - - Grid objects have infinite faces, with each face - using the properties of the default face unless set otherwise. So if - you have a TextureEntry with a default texture uuid of X, and face 18 - has a texture UUID of Y, every face would be textured with X except for - face 18 that uses Y. In practice however, primitives utilize a maximum - of nine faces + + Agent brushing himself/herself off - - + + Agent in busy mode - - + + Agent clapping hands - - - Constructor that takes a default texture UUID - - Texture UUID to use as the default texture + + Agent doing a curtsey bow - - - Constructor that takes a TextureEntryFace for the - default face - - Face to use as the default face + + Agent crouching - - - Constructor that creates the TextureEntry class from a byte array - - Byte array containing the TextureEntry field - Starting position of the TextureEntry field in - the byte array - Length of the TextureEntry field, in bytes + + Agent crouching while walking - - - This will either create a new face if a custom face for the given - index is not defined, or return the custom face for that index if - it already exists - - The index number of the face to create or - retrieve - A TextureEntryFace containing all the properties for that - face + + Agent crying - - - - - - + + Agent unanimated with arms out (e.g. setting appearance) - - - - - + + Agent re-animated after set appearance finished - - - - - + + Agent dancing - - - - - + + Agent dancing - - - Controls the texture animation of a particular prim - + + Agent dancing - - + + Agent dancing - - - - - - - - - - - - - - + + Agent dancing - - + + Agent dancing - - - - - - + + Agent dancing - - - - - + + Agent dancing - - - Complete structure for the particle system - + + Agent on ground unanimated - - Particle Flags - There appears to be more data packed in to this area - for many particle systems. It doesn't appear to be flag values - and serialization breaks unless there is a flag for every - possible bit so it is left as an unsigned integer + + Agent boozing it up - - pattern of particles + + Agent with embarassed expression on face - - A representing the maximimum age (in seconds) particle will be displayed - Maximum value is 30 seconds + + Agent with afraid expression on face - - A representing the number of seconds, - from when the particle source comes into view, - or the particle system's creation, that the object will emits particles; - after this time period no more particles are emitted + + Agent with angry expression on face - - A in radians that specifies where particles will not be created + + Agent with bored expression on face - - A in radians that specifies where particles will be created + + Agent crying - - A representing the number of seconds between burts. + + Agent showing disdain (dislike) for something - - A representing the number of meters - around the center of the source where particles will be created. + + Agent with embarassed expression on face - - A representing in seconds, the minimum speed between bursts of new particles - being emitted + + Agent with frowning expression on face - - A representing in seconds the maximum speed of new particles being emitted. + + Agent with kissy face - - A representing the maximum number of particles emitted per burst + + Agent expressing laughgter - - A which represents the velocity (speed) from the source which particles are emitted + + Agent with open mouth - - A which represents the Acceleration from the source which particles are emitted + + Agent with repulsed expression on face - - The Key of the texture displayed on the particle + + Agent expressing sadness - - The Key of the specified target object or avatar particles will follow + + Agent shrugging shoulders - - Flags of particle from + + Agent with a smile - - Max Age particle system will emit particles for + + Agent expressing surprise - - The the particle has at the beginning of its lifecycle + + Agent sticking tongue out - - The the particle has at the ending of its lifecycle + + Agent with big toothy smile - - A that represents the starting X size of the particle - Minimum value is 0, maximum value is 4 + + Agent winking - - A that represents the starting Y size of the particle - Minimum value is 0, maximum value is 4 + + Agent expressing worry - - A that represents the ending X size of the particle - Minimum value is 0, maximum value is 4 + + Agent falling down - - A that represents the ending Y size of the particle - Minimum value is 0, maximum value is 4 + + Agent walking (feminine version) - - - Decodes a byte[] array into a ParticleSystem Object - - ParticleSystem object - Start position for BitPacker + + Agent wagging finger (disapproval) - - - Generate byte[] array from particle data - - Byte array + + I'm not sure I want to know - - - Particle source pattern - + + Agent in superman position - - None + + Agent in superman position - - Drop particles from source position with no force + + Agent greeting another - - "Explode" particles in all directions + + Agent holding bazooka (right handed) - - Particles shoot across a 2D area + + Agent holding a bow (left handed) - - Particles shoot across a 3D Cone + + Agent holding a handgun (right handed) - - Inverse of AngleCone (shoot particles everywhere except the 3D cone defined + + Agent holding a rifle (right handed) - - - Particle Data Flags - + + Agent throwing an object (right handed) - - None + + Agent in static hover - - Interpolate color and alpha from start to end + + Agent hovering downward - - Interpolate scale from start to end + + Agent hovering upward - - Bounce particles off particle sources Z height + + Agent being impatient - - velocity of particles is dampened toward the simulators wind + + Agent jumping - - Particles follow the source + + Agent jumping with fervor - - Particles point towards the direction of source's velocity + + Agent point to lips then rear end - - Target of the particles + + Agent landing from jump, finished flight, etc - - Particles are sent in a straight line + + Agent laughing - - Particles emit a glow + + Agent landing from jump, finished flight, etc - - used for point/grab/touch + + Agent sitting on a motorcycle - + - Particle Flags Enum - - None + + Agent moving head side to side - - Acceleration and velocity for particles are - relative to the object rotation + + Agent moving head side to side with unhappy expression - - Particles use new 'correct' angle parameters + + Agent taunting another - + - Parameters used to construct a visual representation of a primitive - - - - - + + Agent giving peace sign - - + + Agent pointing at self - - + + Agent pointing at another - - + + Agent preparing for jump (bending knees) - - + + Agent punching with left hand - - + + Agent punching with right hand - - + + Agent acting repulsed - - + + Agent trying to be Chuck Norris - - + + Rocks, Paper, Scissors 1, 2, 3 - - + + Agent with hand flat over other hand - - + + Agent with fist over other hand - - + + Agent with two fingers spread over other hand - - + + Agent running - - + + Agent appearing sad - - + + Agent saluting - - + + Agent shooting bow (left handed) - - + + Agent cupping mouth as if shouting - - + + Agent shrugging shoulders - - + + Agent in sit position - - + + Agent in sit position (feminine) - - Attachment point to an avatar + + Agent in sit position (generic) - - + + Agent sitting on ground - - + + Agent sitting on ground - - + + + - - + + Agent sleeping on side - + + Agent smoking + + + Agent inhaling smoke + + - Information on the flexible properties of a primitive - - + + Agent taking a picture - - + + Agent standing - - + + Agent standing up - - + + Agent standing - - + + Agent standing - - + + Agent standing - - - Default constructor - + + Agent standing - - - - - - + + Agent stretching - - - - - + + Agent in stride (fast walk) - - - - - + + Agent surfing - - - Information on the light properties of a primitive - + + Agent acting surprised - - + + Agent striking with a sword - - + + Agent talking (lips moving) - - + + Agent throwing a tantrum - - + + Agent throwing an object (right handed) - - + + Agent trying on a shirt - - - Default constructor - + + Agent turning to the left - - - - - - + + Agent turning to the right - + + Agent typing + + + Agent walking + + + Agent whispering + + + Agent whispering with fingers in mouth + + + Agent winking + + + Agent winking + + + Agent worried + + + Agent nodding yes + + + Agent nodding yes with happy face + + + Agent floating with legs and arms crossed + + - + A dictionary containing all pre-defined animations - + A dictionary containing the pre-defined animations, + where the key is the animations ID, and the value is a string + containing a name to identify the purpose of the animation - + - + Index of TextureEntry slots for avatar appearances - - + - Information on the sculpt properties of a sculpted primitive + Bake layers for avatar appearance - + Default constructor + A reference to our agent - + - + Contains information about a wearable inventory item - - - - - Render inside out (inverts the normals). - + + Inventory ItemID of the wearable - + + AssetID of the wearable asset + + + WearableType of the wearable + + + AssetType of the wearable + + + Asset data for the wearable + + - Render an X axis mirror of the sculpty. + Data collected from visual params for each wearable + needed for the calculation of the color - + - Extended properties to describe an object + Holds a texture assetID and the data needed to bake this layer into + an outfit texture. Used to keep track of currently worn textures + and baking data - - + + A texture AssetID - - + + Asset data for the texture - - + + Collection of alpha masks that needs applying - - + + Tint that should be applied to the texture - - + + Maximum number of concurrent downloads for wearable assets and textures - - + + Maximum number of concurrent uploads for baked textures - - + + Timeout for fetching inventory listings - - + + Timeout for fetching a single wearable, or receiving a single packet response - - + + Timeout for fetching a single texture - - + + Timeout for uploading a single baked texture - - + + Number of times to retry bake upload - - + + When changing outfit, kick off rebake after + 20 seconds has passed since the last change - - + + Total number of wearables for each avatar - - + + Total number of baked textures on each avatar - - + + Total number of wearables per bake layer - - + + Total number of textures on an avatar, baked or not - - + + Mapping between BakeType and AvatarTextureIndex - - + + Map of what wearables are included in each bake - - + + Magic values to finalize the cache check hashes for each + bake - - + + Default avatar texture, used to detect when a custom + texture is not set for a face - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - - Default constructor - + + Thread sync lock object - - - Set the properties that are set in an ObjectPropertiesFamily packet - - that has - been partially filled by an ObjectPropertiesFamily packet + + The event subscribers. null if no subcribers - - - - + + Thread sync lock object - - - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + A cache of wearables currently being worn - - + + A cache of textures currently being worn - - + + Incrementing serial number for AgentCachedTexture packets - - + + Incrementing serial number for AgentSetAppearance packets - - + + Indicates whether or not the appearance thread is currently + running, to prevent multiple appearance threads from running + simultaneously - + + Reference to our agent + + - + Timer used for delaying rebake on changing outfit - + - Map layer request type + Main appearance thread - - Objects and terrain are shown - - - Only the terrain is shown, no objects + + Triggered when an AgentWearablesUpdate packet is received, + telling us what our avatar is currently wearing + request. - - Overlay showing land for sale and for auction + + Raised when an AgentCachedTextureResponse packet is + received, giving a list of cached bakes that were found on the + simulator + request. - + - Type of grid item, such as telehub, event, populator location, etc. + Raised when appearance data is sent to the simulator, also indicates + the main appearance thread is finished. - - - Telehub - - - PG rated event - - - Mature rated event - - - Popular location - - - Locations of avatar groups in a region - - - Land for sale - - - Classified ad - - - Adult rated event - - - Adult land for sale - - + request. + - Information about a region on the grid map + Triggered when the simulator requests the agent rebake its appearance. + - - Sim X position on World Map - - - Sim Y position on World Map - - - Sim Name (NOTE: In lowercase!) - - - - - - Appears to always be zero (None) + + + Returns true if AppearanceManager is busy and trying to set or change appearance will fail + - - Sim's defined Water Height + + Raises the AgentWearablesReply event + An AgentWearablesReplyEventArgs object containing the + data returned from the data server - - + + Raises the CachedBakesReply event + An AgentCachedBakesReplyEventArgs object containing the + data returned from the data server AgentCachedTextureResponse - - UUID of the World Map image + + Raises the AppearanceSet event + An AppearanceSetEventArgs object indicating if the operatin was successfull - - Unique identifier for this region, a combination of the X - and Y position + + Raises the RebakeAvatarRequested event + An RebakeAvatarTexturesEventArgs object containing the + data returned from the data server - + - + Obsolete method for setting appearance. This function no longer does anything. + Use RequestSetAppearance() to manually start the appearance thread - - + - + Obsolete method for setting appearance. This function no longer does anything. + Use RequestSetAppearance() to manually start the appearance thread - + Unused parameter - + - + Starts the appearance setting thread - - - + - Visual chunk of the grid map + Starts the appearance setting thread + True to force rebaking, otherwise false - + - Base class for Map Items + Ask the server what textures our agent is currently wearing - - The Global X position of the item - - - The Global Y position of the item - - - Get the Local X position of the item - - - Get the Local Y position of the item - - - Get the Handle of the region - - + - Represents an agent or group of agents location + Build hashes out of the texture assetIDs for each baking layer to + ask the simulator whether it has cached copies of each baked texture - + - Represents a Telehub location + Returns the AssetID of the asset that is currently being worn in a + given WearableType slot + WearableType slot to get the AssetID for + The UUID of the asset being worn in the given slot, or + UUID.Zero if no wearable is attached to the given slot or wearables + have not been downloaded yet - + - Represents a non-adult parcel of land for sale + Add a wearable to the current outfit and set appearance + Wearable to be added to the outfit - + - Represents an Adult parcel of land for sale + Add a list of wearables to the current outfit and set appearance + List of wearable inventory items to + be added to the outfit - + - Represents a PG Event + Remove a wearable from the current outfit and set appearance + Wearable to be removed from the outfit - + - Represents a Mature event + Removes a list of wearables from the current outfit and set appearance + List of wearable inventory items to + be removed from the outfit - + - Represents an Adult event + Replace the current outfit with a list of wearables and set appearance + List of wearable inventory items that + define a new outfit - + - Manages grid-wide tasks such as the world map + Checks if an inventory item is currently being worn + The inventory item to check against the agent + wearables + The WearableType slot that the item is being worn in, + or WearbleType.Invalid if it is not currently being worn - - The event subscribers. null if no subcribers - - - Raises the CoarseLocationUpdate event - A CoarseLocationUpdateEventArgs object containing the - data sent by simulator + + + Returns a copy of the agents currently worn wearables + + A copy of the agents currently worn wearables + Avoid calling this function multiple times as it will make + a copy of all of the wearable data each time - - Thread sync lock object + + + Calls either or + depending on the value of + replaceItems + + List of wearable inventory items to add + to the outfit or become a new outfit + True to replace existing items with the + new list of items, false to add these items to the existing outfit - - The event subscribers. null if no subcribers + + + Adds a list of attachments to our agent + + A List containing the attachments to add + If true, tells simulator to remove existing attachment + first - - Raises the GridRegion event - A GridRegionEventArgs object containing the - data sent by simulator + + + Attach an item to our agent at a specific attach point + + A to attach + the on the avatar + to attach the item to - - Thread sync lock object + + + Attach an item to our agent specifying attachment details + + The of the item to attach + The attachments owner + The name of the attachment + The description of the attahment + The to apply when attached + The of the attachment + The on the agent + to attach the item to - - The event subscribers. null if no subcribers + + + Detach an item from our agent using an object + + An object - - Raises the GridLayer event - A GridLayerEventArgs object containing the - data sent by simulator + + + Detach an item from our agent + + The inventory itemID of the item to detach - - Thread sync lock object + + + Inform the sim which wearables are part of our current outfit + - - The event subscribers. null if no subcribers + + + Replaces the Wearables collection with a list of new wearable items + + Wearable items to replace the Wearables collection with - - Raises the GridItems event - A GridItemEventArgs object containing the - data sent by simulator + + + Calculates base color/tint for a specific wearable + based on its params + + All the color info gathered from wearable's VisualParams + passed as list of ColorParamInfo tuples + Base color/tint for the wearable - - Thread sync lock object + + + Blocking method to populate the Wearables dictionary + + True on success, otherwise false - - The event subscribers. null if no subcribers + + + Blocking method to populate the Textures array with cached bakes + + True on success, otherwise false - - Raises the RegionHandleReply event - A RegionHandleReplyEventArgs object containing the - data sent by simulator + + + Populates textures and visual params from a decoded asset + + Wearable to decode - - Thread sync lock object + + + Blocking method to download and parse currently worn wearable assets + + True on success, otherwise false - - A dictionary of all the regions, indexed by region name + + + Get a list of all of the textures that need to be downloaded for a + single bake layer + + Bake layer to get texture AssetIDs for + A list of texture AssetIDs to download - - A dictionary of all the regions, indexed by region handle + + + Helper method to lookup the TextureID for a single layer and add it + to a list if it is not already present + + + + + - + - Constructor + Blocking method to download all of the textures needed for baking + the given bake layers - Instance of GridClient object to associate with this GridManager instance + A list of layers that need baking + No return value is given because the baking will happen + whether or not all textures are successfully downloaded - + - + Blocking method to create and upload baked textures for all of the + missing bakes - + True on success, otherwise false - + - Request a map layer + Blocking method to create and upload a baked texture for a single + bake layer - The name of the region - The type of layer + Layer to bake + True on success, otherwise false - + - + Blocking method to upload a baked texture - - - - - - + Five channel JPEG2000 texture data to upload + UUID of the newly created asset on success, otherwise UUID.Zero - + - + Creates a dictionary of visual param values from the downloaded wearables - - - - - + A dictionary of visual param indices mapping to visual param + values for our agent that can be fed to the Baker class - + - + Create an AgentSetAppearance packet from Wearables data and the + Textures array and send it - - - - + - Request data for all mainland (Linden managed) simulators + Converts a WearableType to a bodypart or clothing WearableType + A WearableType + AssetType.Bodypart or AssetType.Clothing or AssetType.Unknown - + - Request the region handle for the specified region UUID + Converts a BakeType to the corresponding baked texture slot in AvatarTextureIndex - UUID of the region to look up + A BakeType + The AvatarTextureIndex slot that holds the given BakeType - + - Get grid region information using the region name, this function - will block until it can find the region or gives up + Gives the layer number that is used for morph mask - Name of sim you're looking for - Layer that you are requesting - Will contain a GridRegion for the sim you're - looking for if successful, otherwise an empty structure - True if the GridRegion was successfully fetched, otherwise - false + >A BakeType + Which layer number as defined in BakeTypeToTextures is used for morph mask - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Converts a BakeType to a list of the texture slots that make up that bake + + A BakeType + A list of texture slots that are inputs for the given bake - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Contains the Event data returned from the data server from an AgentWearablesRequest - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Construct a new instance of the AgentWearablesReplyEventArgs class - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Contains the Event data returned from the data server from an AgentCachedTextureResponse - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Construct a new instance of the AgentCachedBakesReplyEventArgs class - - Raised when the simulator sends a - containing the location of agents in the simulator + + Contains the Event data returned from an AppearanceSetRequest - - Raised when the simulator sends a Region Data in response to - a Map request + + + Triggered when appearance data is sent to the sim and + the main appearance thread is done. + Indicates whether appearance setting was successful - - Raised when the simulator sends GridLayer object containing - a map tile coordinates and texture information + + Indicates whether appearance setting was successful - - Raised when the simulator sends GridItems object containing - details on events, land sales at a specific location + + Contains the Event data returned from the data server from an RebakeAvatarTextures - - Raised in response to a Region lookup + + + Triggered when the simulator sends a request for this agent to rebake + its appearance + + The ID of the Texture Layer to bake - - Unknown - - - Current direction of the sun - - - Current angular velocity of the sun - - - Current world time + + The ID of the Texture Layer to bake - + - Main class to expose grid functionality to clients. All of the - classes needed for sending and receiving data are accessible through - this class. + Class that handles the local asset cache - - - // Example minimum code required to instantiate class and - // connect to a simulator. - using System; - using System.Collections.Generic; - using System.Text; - using OpenMetaverse; - - namespace FirstBot - { - class Bot - { - public static GridClient Client; - static void Main(string[] args) - { - Client = new GridClient(); // instantiates the GridClient class - // to the global Client object - // Login to Simulator - Client.Network.Login("FirstName", "LastName", "Password", "FirstBot", "1.0"); - // Wait for a Keypress - Console.ReadLine(); - // Logout of simulator - Client.Network.Logout(); - } - } - } - - - - - Networking subsystem - - - Settings class including constant values and changeable - parameters for everything - - - Parcel (subdivided simulator lots) subsystem - - - Our own avatars subsystem - - - Other avatars subsystem - - - Estate subsystem - - - Friends list subsystem - - - Grid (aka simulator group) subsystem - - - Object subsystem - - - Group subsystem - - - Asset subsystem - - - Appearance subsystem - - - Inventory subsystem - - - Directory searches including classifieds, people, land - sales, etc - - - Handles land, wind, and cloud heightmaps - - - Handles sound-related networking - - - Throttling total bandwidth usage, or allocating bandwidth - for specific data stream types - + Default constructor + A reference to the GridClient object - - - Return the full name of this instance - - Client avatars full name - - + - Attempts to convert an LLSD structure to a known Packet type + Helper class for sorting files by their last accessed time - Event name, this must match an actual - packet name for a Packet to be successfully built - LLSD to convert to a Packet - A Packet on success, otherwise null - + - Class that handles the local asset cache + Allows setting weather to periodicale prune the cache if it grows too big + Default is enabled, when caching is enabled - + - Default constructor + How long (in ms) between cache checks (default is 5 min.) - A reference to the GridClient object @@ -4525,20726 +4159,21636 @@ Byte size we want to output String with humanly readable file size - + - Allows setting weather to periodicale prune the cache if it grows too big - Default is enabled, when caching is enabled - + + OK + + + Transfer completed + + - How long (in ms) between cache checks (default is 5 min.) - + - Helper class for sorting files by their last accessed time - + + Unknown error occurred + + + Equivalent to a 404 error + + + Client does not have permission for that resource + + + Unknown status + + - Extract the avatar UUID encoded in a SIP URI - - - + - Represents an LSL Text object containing a string of UTF encoded characters - - A string of characters represting the script contents + + Unknown - - Initializes a new AssetScriptText object + + Virtually all asset transfers use this channel - + - Initializes a new AssetScriptText object with parameters - A unique specific to this asset - A byte array containing the raw asset data - + - Initializes a new AssetScriptText object with parameters - A string containing the scripts contents - + + Asset from the asset server + + + Inventory item + + + Estate asset, such as an estate covenant + + - Encode a string containing the scripts contents into byte encoded AssetData - + - Decode a byte array containing the scripts contents into a string - true if decoding is successful - - Override the base classes AssetType + + + - + - NetworkManager is responsible for managing the network layer of - OpenMetaverse. It tracks all the server connections, serializes - outgoing traffic and deserializes incoming traffic, and provides - instances of delegates for network-related events. + + - Login Routines - - The event subscribers, null of no subscribers + + + - - Raises the PacketSent Event - A PacketSentEventArgs object containing - the data sent from the simulator + + + - - Thread sync lock object + + + Image file format + - - The event subscribers, null of no subscribers + + + - - Raises the LoggedOut Event - A LoggedOutEventArgs object containing - the data sent from the simulator + + Number of milliseconds passed since the last transfer + packet was received - - Thread sync lock object + + + - - The event subscribers, null of no subscribers + + + - - Raises the SimConnecting Event - A SimConnectingEventArgs object containing - the data sent from the simulator + + + - - Thread sync lock object + + + - - The event subscribers, null of no subscribers + + + - - Raises the SimConnected Event - A SimConnectedEventArgs object containing - the data sent from the simulator + + + + + + + + + + + - - Thread sync lock object + + + - - The event subscribers, null of no subscribers + + + Default constructor + + A reference to the GridClient object - - Raises the SimDisconnected Event - A SimDisconnectedEventArgs object containing - the data sent from the simulator + + + Callback used for various asset download requests + + Transfer information + Downloaded asset, null on fail - - Thread sync lock object + + + Callback used upon competition of baked texture upload + + Asset UUID of the newly uploaded baked texture - - The event subscribers, null of no subscribers + + Number of milliseconds to wait for a transfer header packet if out of order data was received - - Raises the Disconnected Event - A DisconnectedEventArgs object containing - the data sent from the simulator + + The event subscribers. null if no subcribers - + Thread sync lock object - - The event subscribers, null of no subscribers + + The event subscribers. null if no subcribers - - Raises the SimChanged Event - A SimChangedEventArgs object containing - the data sent from the simulator + + Thread sync lock object - + + The event subscribers. null if no subcribers + + Thread sync lock object - - The event subscribers, null of no subscribers + + The event subscribers. null if no subcribers - - Raises the EventQueueRunning Event - A EventQueueRunningEventArgs object containing - the data sent from the simulator + + Thread sync lock object - + + The event subscribers. null if no subcribers + + Thread sync lock object - - All of the simulators we are currently connected to + + Texture download cache - - Handlers for incoming capability events + + Raised when the simulator responds sends - - Handlers for incoming packets + + Raised during upload completes - - Incoming packets that are awaiting handling + + Raised during upload with progres update - - Outgoing packets that are awaiting handling + + Fired when the simulator sends an InitiateDownloadPacket, used to download terrain .raw files - - - Default constructor - - Reference to the GridClient object + + Fired when a texture is in the process of being downloaded by the TexturePipeline class - - - Register an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library - - Packet type to trigger events for - Callback to fire when a packet of this type - is received + + Raises the XferReceived event + A XferReceivedEventArgs object containing the + data returned from the simulator - - - Unregister an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library - - Packet type this callback is registered with - Callback to stop firing events for + + Raises the AssetUploaded event + A AssetUploadedEventArgs object containing the + data returned from the simulator - - - Register a CAPS event handler. This is a low level event interface - and should only be used if you are doing something not supported in - the library - - Name of the CAPS event to register a handler for - Callback to fire when a CAPS event is received + + Raises the UploadProgress event + A UploadProgressEventArgs object containing the + data returned from the simulator - + + Raises the InitiateDownload event + A InitiateDownloadEventArgs object containing the + data returned from the simulator + + + Raises the ImageReceiveProgress event + A ImageReceiveProgressEventArgs object containing the + data returned from the simulator + + - Unregister a CAPS event handler. This is a low level event interface - and should only be used if you are doing something not supported in - the library + Request an asset download - Name of the CAPS event this callback is - registered with - Callback to stop firing events for + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + The callback to fire when the simulator responds with the asset data - + - Send a packet to the simulator the avatar is currently occupying + Request an asset download - Packet to send + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + Source location of the requested asset + The callback to fire when the simulator responds with the asset data - + - Send a packet to a specified simulator + Request an asset download - Packet to send - Simulator to send the packet to + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + Source location of the requested asset + UUID of the transaction + The callback to fire when the simulator responds with the asset data - + - Connect to a simulator + Request an asset download through the almost deprecated Xfer system - IP address to connect to - Port to connect to - Handle for this simulator, to identify its - location in the grid - Whether to set CurrentSim to this new - connection, use this if the avatar is moving in to this simulator - URL of the capabilities server to use for - this sim connection - A Simulator object on success, otherwise null + Filename of the asset to request + Whether or not to delete the asset + off the server after it is retrieved + Use large transfer packets or not + UUID of the file to request, if filename is + left empty + Asset type of vFileID, or + AssetType.Unknown if filename is not empty + Sets the FilePath in the request to Cache + (4) if true, otherwise Unknown (0) is used + + - + - Connect to a simulator - IP address and port to connect to - Handle for this simulator, to identify its - location in the grid - Whether to set CurrentSim to this new - connection, use this if the avatar is moving in to this simulator - URL of the capabilities server to use for - this sim connection - A Simulator object on success, otherwise null + Use UUID.Zero if you do not have the + asset ID but have all the necessary permissions + The item ID of this asset in the inventory + Use UUID.Zero if you are not requesting an + asset from an object inventory + The owner of this asset + Asset type + Whether to prioritize this asset download or not + + - + - Initiate a blocking logout request. This will return when the logout - handshake has completed or when Settings.LOGOUT_TIMEOUT - has expired and the network layer is manually shut down + Used to force asset data into the PendingUpload property, ie: for raw terrain uploads + An AssetUpload object containing the data to upload to the simulator - + - Initiate the logout process. Check if logout succeeded with the - OnLogoutReply event, and if this does not fire the - Shutdown() function needs to be manually called + Request an asset be uploaded to the simulator + The Object containing the asset data + If True, the asset once uploaded will be stored on the simulator + in which the client was connected in addition to being stored on the asset server + The of the transfer, can be used to correlate the upload with + events being fired - + - Close a connection to the given simulator + Request an asset be uploaded to the simulator - - + The of the asset being uploaded + A byte array containing the encoded asset data + If True, the asset once uploaded will be stored on the simulator + in which the client was connected in addition to being stored on the asset server + The of the transfer, can be used to correlate the upload with + events being fired - + - Shutdown will disconnect all the sims except for the current sim - first, and then kill the connection to CurrentSim. This should only - be called if the logout process times out on RequestLogout + Request an asset be uploaded to the simulator - Type of shutdown + + + Asset type to upload this data as + A byte array containing the encoded asset data + If True, the asset once uploaded will be stored on the simulator + in which the client was connected in addition to being stored on the asset server + The of the transfer, can be used to correlate the upload with + events being fired - + - Shutdown will disconnect all the sims except for the current sim - first, and then kill the connection to CurrentSim. This should only - be called if the logout process times out on RequestLogout + Initiate an asset upload - Type of shutdown - Shutdown message + The ID this asset will have if the + upload succeeds + Asset type to upload this data as + Raw asset data to upload + Whether to store this asset on the local + simulator or the grid-wide asset server + The tranaction id for the upload + The transaction ID of this transfer - + - Searches through the list of currently connected simulators to find - one attached to the given IPEndPoint + Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator - IPEndPoint of the Simulator to search for - A Simulator reference on success, otherwise null + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + A float indicating the requested priority for the transfer. Higher priority values tell the simulator + to prioritize the request before lower valued requests. An image already being transferred using the can have + its priority changed by resending the request with the new priority value + Number of quality layers to discard. + This controls the end marker of the data sent. Sending with value -1 combined with priority of 0 cancels an in-progress + transfer. + A bug exists in the Linden Simulator where a -1 will occasionally be sent with a non-zero priority + indicating an off-by-one error. + The packet number to begin the request at. A value of 0 begins the request + from the start of the asset texture + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + If true, the callback will be fired for each chunk of the downloaded image. + The callback asset parameter will contain all previously received chunks of the texture asset starting + from the beginning of the request + + Request an image and fire a callback when the request is complete + + Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); + private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) + { + if(state == TextureRequestState.Finished) + { + Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", + asset.AssetID, + asset.AssetData.Length); + } + } + + Request an image and use an inline anonymous method to handle the downloaded texture data + + Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, delegate(TextureRequestState state, AssetTexture asset) + { + if(state == TextureRequestState.Finished) + { + Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", + asset.AssetID, + asset.AssetData.Length); + } + } + ); + + Request a texture, decode the texture to a bitmap image and apply it to a imagebox + + Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); + private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) + { + if(state == TextureRequestState.Finished) + { + ManagedImage imgData; + Image bitmap; + if (state == TextureRequestState.Finished) + { + OpenJPEG.DecodeToImage(assetTexture.AssetData, out imgData, out bitmap); + picInsignia.Image = bitmap; + } + } + } + - + - Fire an event when an event queue connects for capabilities + Overload: Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator - Simulator the event queue is attached to + The of the texture asset to download + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data - + + + Overload: Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + + + + Overload: Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + If true, the callback will be fired for each chunk of the downloaded image. + The callback asset parameter will contain all previously received chunks of the texture asset starting + from the beginning of the request + + + + Cancel a texture request + + The texture assets + + + + Lets TexturePipeline class fire the progress event + + The texture ID currently being downloaded + the number of bytes transferred + the total number of bytes expected + + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - - The event subscribers, null of no subscribers + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Raises the LoginProgress Event - A LoginProgressEventArgs object containing - the data sent from the simulator + + Xfer data - - Thread sync lock object + + Upload data - - Seed CAPS URL returned from the login server + + Filename used on the simulator - - A list of packets obtained during the login process which - networkmanager will log but not process + + Filename used by the client - + + UUID of the image that is in progress + + + Number of bytes received so far + + + Image size in bytes + + - Generate sane default values for a login request + Avatar profile flags - Account first name - Account last name - Account password - Client application name - Client application version - A populated struct containing - sane defaults - + - Simplified login that takes the most common and required fields + Represents an avatar (other than your own) - Account first name - Account last name - Account password - Client application name - Client application version - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error - + - Simplified login that takes the most common fields along with a - starting location URI, and can accept an MD5 string instead of a - plaintext password + Default constructor - Account first name - Account last name - Account password or MD5 hash of the password - such as $1$1682a1e45e9f957dcdf0bb56eb43319c - Client application name - Starting location URI that can be built with - StartLocation() - Client application version - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error - + - Login that takes a struct of all the values that will be passed to - the login server + Positive and negative ratings - The values that will be passed to the login - server, all fields must be set even if they are String.Empty - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error - + + Positive ratings for Behavior + + + Negative ratings for Behavior + + + Positive ratings for Appearance + + + Negative ratings for Appearance + + + Positive ratings for Building + + + Negative ratings for Building + + + Positive ratings given by this avatar + + + Negative ratings given by this avatar + + - Build a start location URI for passing to the Login function + Avatar properties including about text, profile URL, image IDs and + publishing settings - Name of the simulator to start in - X coordinate to start at - Y coordinate to start at - Z coordinate to start at - String with a URI that can be used to login to a specified - location - + + First Life about text + + + First Life image ID + + - Handles response from XML-RPC login replies - + - Handle response from LLSD login replies - - - - + - Get current OS - Either "Win" or "Linux" - + - Get clients default Mac Address - A string containing the first found Mac Address - - Raised when the simulator sends us data containing - ... - - - Raised when the simulator sends us data containing - ... + + Profile image ID - - Raised when the simulator sends us data containing - ... + + Flags of the profile - - Raised when the simulator sends us data containing - ... + + Web URL for this profile - - Raised when the simulator sends us data containing - ... + + Should this profile be published on the web - - Raised when the simulator sends us data containing - ... + + Avatar Online Status - - Raised when the simulator sends us data containing - ... + + Is this a mature profile - - Raised when the simulator sends us data containing - ... + + + - - Unique identifier associated with our connections to - simulators + + + - - The simulator that the logged in avatar is currently - occupying + + + Avatar interests including spoken languages, skills, and "want to" + choices + - - Shows whether the network layer is logged in to the - grid or not + + Languages profile field - - Number of packets in the incoming queue + + + - - Number of packets in the outgoing queue + + + - - Raised when the simulator sends us data containing - ... + + + - - Called when a reply is received from the login server, the - login sequence will block until this event returns + + + - - Current state of logging in + + Groups that this avatar is a member of - - Upon login failure, contains a short string key for the - type of login error that occurred + + Positive and negative ratings - - The raw XML-RPC reply from the login server, exactly as it - was received (minus the HTTP header) + + Avatar properties including about text, profile URL, image IDs and + publishing settings - - During login this contains a descriptive version of - LoginStatusCode. After a successful login this will contain the - message of the day, and after a failed login a descriptive error - message will be returned + + Avatar interests including spoken languages, skills, and "want to" + choices - + + Movement control flags for avatars. Typically not set or used by + clients. To move your avatar, use Client.Self.Movement instead + + - Explains why a simulator or the grid disconnected from us + Contains the visual parameters describing the deformation of the avatar - - The client requested the logout or simulator disconnect + + First name - - The server notified us that it is disconnecting + + Last name - - Either a socket was closed or network traffic timed out + + Full name - - The last active simulator shut down + + Active group - + - Holds a simulator reference and a decoded packet, these structs are put in - the packet inbox for event handling + Holds group information for Avatars such as those you might find in a profile - - Reference to the simulator that this packet came from - - - Packet that needs to be processed - - - - Holds a simulator reference and a serialized packet, these structs are put in - the packet outbox for sending - + + true of Avatar accepts group notices - - Reference to the simulator this packet is destined for + + Groups Key - - Packet that needs to be sent + + Texture Key for groups insignia - - Sequence number of the wrapped packet + + Name of the group - - Number of times this packet has been resent + + Powers avatar has in the group - - Environment.TickCount when this packet was last sent over the wire + + Avatars Currently selected title - - - - - - - - - + + true of Avatar has chosen to list this in their profile - + - Reads in a byte array of an Animation Asset created by the SecondLife(tm) client. + Contains an animation currently being played by an agent - - - Rotation Keyframe count (used internally) - + + The ID of the animation asset - - - Position Keyframe count (used internally) - + + A number to indicate start order of currently playing animations + On Linden Grids this number is unique per region, with OpenSim it is per client - + - Animation Priority - + - The animation length in seconds. + Holds group information on an individual profile pick - + - Expression set in the client. Null if [None] is selected + Retrieve friend status notifications, and retrieve avatar names and + profiles - + - The time in seconds to start the animation + Represents other avatars + + - - - The time in seconds to end the animation - + + The event subscribers, null of no subscribers - - - Loop the animation - + + Thread sync lock object - - - Meta data. Ease in Seconds. - + + The event subscribers, null of no subscribers - - - Meta data. Ease out seconds. - + + Thread sync lock object - - - Meta Data for the Hand Pose - + + The event subscribers, null of no subscribers - - - Number of joints defined in the animation - + + Thread sync lock object - - - Contains an array of joints - + + The event subscribers, null of no subscribers - - - Searialize an animation asset into it's joints/keyframes/meta data - - + + Thread sync lock object - - - Variable length strings seem to be null terminated in the animation asset.. but.. - use with caution, home grown. - advances the index. - - The animation asset byte array - The offset to start reading - a string + + The event subscribers, null of no subscribers - - - Read in a Joint from an animation asset byte array - Variable length Joint fields, yay! - Advances the index - - animation asset byte array - Byte Offset of the start of the joint - The Joint data serialized into the binBVHJoint structure + + Thread sync lock object - - - Read Keyframes of a certain type - advance i - - Animation Byte array - Offset in the Byte Array. Will be advanced - Number of Keyframes - Scaling Min to pass to the Uint16ToFloat method - Scaling Max to pass to the Uint16ToFloat method - + + The event subscribers, null of no subscribers - - - A Joint and it's associated meta data and keyframes - + + Thread sync lock object - - - Name of the Joint. Matches the avatar_skeleton.xml in client distros - + + The event subscribers, null of no subscribers - - - Joint Animation Override? Was the same as the Priority in testing.. - + + Thread sync lock object - - - Array of Rotation Keyframes in order from earliest to latest - + + The event subscribers, null of no subscribers - - - Array of Position Keyframes in order from earliest to latest - This seems to only be for the Pelvis? - - - - - A Joint Keyframe. This is either a position or a rotation. - - - - - Either a Vector3 position or a Vector3 Euler rotation - - - - - Poses set in the animation metadata for the hands. - - - - - Manager class for our own avatar - - - - The event subscribers. null if no subcribers - - - Raises the ChatFromSimulator event - A ChatEventArgs object containing the - data returned from the data server - - + Thread sync lock object - - The event subscribers. null if no subcribers - - - Raises the ScriptDialog event - A SctriptDialogEventArgs object containing the - data returned from the data server + + The event subscribers, null of no subscribers - + Thread sync lock object - - The event subscribers. null if no subcribers - - - Raises the ScriptQuestion event - A ScriptQuestionEventArgs object containing the - data returned from the data server + + The event subscribers, null of no subscribers - + Thread sync lock object - - The event subscribers. null if no subcribers - - - Raises the LoadURL event - A LoadUrlEventArgs object containing the - data returned from the data server + + The event subscribers, null of no subscribers - + Thread sync lock object - - The event subscribers. null if no subcribers - - - Raises the MoneyBalance event - A BalanceEventArgs object containing the - data returned from the data server + + The event subscribers, null of no subscribers - + Thread sync lock object - - The event subscribers. null if no subcribers - - - Raises the MoneyBalanceReply event - A MoneyBalanceReplyEventArgs object containing the - data returned from the data server + + The event subscribers, null of no subscribers - + Thread sync lock object - - The event subscribers. null if no subcribers - - - Raises the IM event - A InstantMessageEventArgs object containing the - data returned from the data server + + The event subscribers, null of no subscribers - + Thread sync lock object - - The event subscribers. null if no subcribers + + Raised when the simulator sends us data containing + an agents animation playlist - - Raises the TeleportProgress event - A TeleportEventArgs object containing the - data returned from the data server + + Raised when the simulator sends us data containing + the appearance information for an agent - - Thread sync lock object + + Raised when the simulator sends us data containing + agent names/id values - - The event subscribers. null if no subcribers + + Raised when the simulator sends us data containing + the interests listed in an agents profile - - Raises the AgentDataReply event - A AgentDataReplyEventArgs object containing the - data returned from the data server + + Raised when the simulator sends us data containing + profile property information for an agent - - Thread sync lock object + + Raised when the simulator sends us data containing + the group membership an agent is a member of - - The event subscribers. null if no subcribers + + Raised when the simulator sends us data containing + name/id pair - - Raises the AnimationsChanged event - A AnimationsChangedEventArgs object containing the - data returned from the data server + + Raised when the simulator sends us data containing + the objects and effect when an agent is pointing at - - Thread sync lock object + + Raised when the simulator sends us data containing + the objects and effect when an agent is looking at - - The event subscribers. null if no subcribers + + Raised when the simulator sends us data containing + an agents viewer effect information - - Raises the MeanCollision event - A MeanCollisionEventArgs object containing the - data returned from the data server + + Raised when the simulator sends us data containing + the top picks from an agents profile - - Thread sync lock object + + Raised when the simulator sends us data containing + the Pick details - - The event subscribers. null if no subcribers + + Raised when the simulator sends us data containing + the classified ads an agent has placed - - Raises the RegionCrossed event - A RegionCrossedEventArgs object containing the - data returned from the data server + + Raised when the simulator sends us data containing + the details of a classified ad - - Thread sync lock object + + Raises the AvatarAnimation Event + An AvatarAnimationEventArgs object containing + the data sent from the simulator - - The event subscribers. null if no subcribers + + Raises the AvatarAppearance Event + A AvatarAppearanceEventArgs object containing + the data sent from the simulator - - Raises the GroupChatJoined event - A GroupChatJoinedEventArgs object containing the - data returned from the data server + + Raises the UUIDNameReply Event + A UUIDNameReplyEventArgs object containing + the data sent from the simulator - - Thread sync lock object + + Raises the AvatarInterestsReply Event + A AvatarInterestsReplyEventArgs object containing + the data sent from the simulator - - The event subscribers. null if no subcribers + + Raises the AvatarPropertiesReply Event + A AvatarPropertiesReplyEventArgs object containing + the data sent from the simulator - - Raises the GroupChatLeft event - A GroupChatLeftEventArgs object containing the - data returned from the data server + + Raises the AvatarGroupsReply Event + A AvatarGroupsReplyEventArgs object containing + the data sent from the simulator - - Thread sync lock object + + Raises the AvatarPickerReply Event + A AvatarPickerReplyEventArgs object containing + the data sent from the simulator - - The event subscribers. null if no subcribers + + Raises the ViewerEffectPointAt Event + A ViewerEffectPointAtEventArgs object containing + the data sent from the simulator - - Raises the AlertMessage event - A AlertMessageEventArgs object containing the - data returned from the data server + + Raises the ViewerEffectLookAt Event + A ViewerEffectLookAtEventArgs object containing + the data sent from the simulator - - Thread sync lock object + + Raises the ViewerEffect Event + A ViewerEffectEventArgs object containing + the data sent from the simulator - - The event subscribers. null if no subcribers + + Raises the AvatarPicksReply Event + A AvatarPicksReplyEventArgs object containing + the data sent from the simulator - - Raises the ScriptControlChange event - A ScriptControlEventArgs object containing the - data returned from the data server + + Raises the PickInfoReply Event + A PickInfoReplyEventArgs object containing + the data sent from the simulator - - Thread sync lock object + + Raises the AvatarClassifiedReply Event + A AvatarClassifiedReplyEventArgs object containing + the data sent from the simulator - - The event subscribers. null if no subcribers + + Raises the ClassifiedInfoReply Event + A ClassifiedInfoReplyEventArgs object containing + the data sent from the simulator - - Raises the CameraConstraint event - A CameraConstraintEventArgs object containing the - data returned from the data server + + Tracks the specified avatar on your map + Avatar ID to track - - Thread sync lock object + + + Request a single avatar name + + The avatar key to retrieve a name for - - The event subscribers. null if no subcribers - - - Raises the ScriptSensorReply event - A ScriptSensorReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Raises the AvatarSitResponse event - A AvatarSitResponseEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Raises the ChatSessionMemberAdded event - A ChatSessionMemberAddedEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Raises the ChatSessionMemberLeft event - A ChatSessionMemberLeftEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Reference to the GridClient instance - - - Used for movement and camera tracking - - - Currently playing animations for the agent. Can be used to - check the current movement status such as walking, hovering, aiming, - etc. by checking against system animations found in the Animations class - - - Dictionary containing current Group Chat sessions and members - - + - Constructor, setup callbacks for packets related to our avatar + Request a list of avatar names - A reference to the Class + The avatar keys to retrieve names for - + - Send a text message from the Agent to the Simulator + Start a request for Avatar Properties - A containing the message - The channel to send the message on, 0 is the public channel. Channels above 0 - can be used however only scripts listening on the specified channel will see the message - Denotes the type of message being sent, shout, whisper, etc. + + - + - Request any instant messages sent while the client was offline to be resent. + Search for an avatar (first name, last name) + The name to search for + An ID to associate with this query - + - Send an Instant Message to another Avatar + Start a request for Avatar Picks - The recipients - A containing the message to send + UUID of the avatar - + - Send an Instant Message to an existing group chat or conference chat + Start a request for Avatar Classifieds - The recipients - A containing the message to send - IM session ID (to differentiate between IM windows) + UUID of the avatar - + - Send an Instant Message + Start a request for details of a specific profile pick - The name this IM will show up as being from - Key of Avatar - Text message being sent - IM session ID (to differentiate between IM windows) - IDs of sessions for a conference + UUID of the avatar + UUID of the profile pick - + - Send an Instant Message + Start a request for details of a specific profile classified - The name this IM will show up as being from - Key of Avatar - Text message being sent - IM session ID (to differentiate between IM windows) - Type of instant message to send - Whether to IM offline avatars as well - Senders Position - RegionID Sender is In - Packed binary data that is specific to - the dialog type + UUID of the avatar + UUID of the profile classified - - - Send an Instant Message to a group - - of the group to send message to - Text Message being sent. + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Send an Instant Message to a group the agent is a member of - - The name this IM will show up as being from - of the group to send message to - Text message being sent + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Send a request to join a group chat session - - of Group to leave + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Exit a group chat session. This will stop further Group chat messages - from being sent until session is rejoined. - - of Group chat session to leave + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Reply to script dialog questions. - - Channel initial request came on - Index of button you're "clicking" - Label of button you're "clicking" - of Object that sent the dialog request - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - Accept invite for to a chatterbox session + Crossed region handler for message that comes across the EventQueue. Sent to an agent + when the agent crosses a sim border into a new region. - of session to accept invite to + The message key + the IMessage object containing the deserialized data sent from the simulator + The which originated the packet - - - Start a friends conference - - List of UUIDs to start a conference with - the temportary session ID returned in the callback> + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Start a particle stream between an agent and an object - - Key of the source agent - Key of the target object - - The type from the enum - A unique for this effect + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Start a particle stream between an agent and an object - - Key of the source agent - Key of the target object - A representing the beams offset from the source - A which sets the avatars lookat animation - of the Effect + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Create a particle beam between an avatar and an primitive - - The ID of source avatar - The ID of the target primitive - global offset - A object containing the combined red, green, blue and alpha - color values of particle beam - a float representing the duration the parcicle beam will last - A Unique ID for the beam - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Create a particle swirl around a target position using a packet - - global offset - A object containing the combined red, green, blue and alpha - color values of particle beam - a float representing the duration the parcicle beam will last - A Unique ID for the beam + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Sends a request to sit on the specified object - - of the object to sit on - Sit at offset + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Follows a call to to actually sit on the object - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Stands up from sitting on a prim or the ground - true of AgentUpdate was sent + + Provides data for the event + The event occurs when the simulator sends + the animation playlist for an agent + + The following code example uses the and + properties to display the animation playlist of an avatar on the window. + + // subscribe to the event + Client.Avatars.AvatarAnimation += Avatars_AvatarAnimation; + private void Avatars_AvatarAnimation(object sender, AvatarAnimationEventArgs e) + { + // create a dictionary of "known" animations from the Animations class using System.Reflection + Dictionary<UUID, string> systemAnimations = new Dictionary<UUID, string>(); + Type type = typeof(Animations); + System.Reflection.FieldInfo[] fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + foreach (System.Reflection.FieldInfo field in fields) + { + systemAnimations.Add((UUID)field.GetValue(type), field.Name); + } + // find out which animations being played are known animations and which are assets + foreach (Animation animation in e.Animations) + { + if (systemAnimations.ContainsKey(animation.AnimationID)) + { + Console.WriteLine("{0} is playing {1} ({2}) sequence {3}", e.AvatarID, + systemAnimations[animation.AnimationID], animation.AnimationSequence); + } + else + { + Console.WriteLine("{0} is playing {1} (Asset) sequence {2}", e.AvatarID, + animation.AnimationID, animation.AnimationSequence); + } + } + } + - + - Does a "ground sit" at the avatar's current position + Construct a new instance of the AvatarAnimationEventArgs class + The ID of the agent + The list of animations to start - - - Starts or stops flying - - True to start flying, false to stop flying + + Get the ID of the agent - + + Get the list of animations to start + + + Provides data for the event + The event occurs when the simulator sends + the appearance data for an avatar + + The following code example uses the and + properties to display the selected shape of an avatar on the window. + + // subscribe to the event + Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; + // handle the data when the event is raised + void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) + { + Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") + } + + + - Starts or stops crouching + Construct a new instance of the AvatarAppearanceEventArgs class - True to start crouching, false to stop crouching + The simulator request was from + The ID of the agent + true of the agent is a trial account + The default agent texture + The agents appearance layer textures + The for the agent - + + Get the Simulator this request is from of the agent + + + Get the ID of the agent + + + true if the agent is a trial account + + + Get the default agent texture + + + Get the agents appearance layer textures + + + Get the for the agent + + + Represents the interests from the profile of an agent + + + Get the ID of the agent + + + The properties of an agent + + + Get the ID of the agent + + + Get the ID of the agent + + + Get the ID of the agent + + + Get the ID of the avatar + + - Starts a jump (begin holding the jump key) + Reads in a byte array of an Animation Asset created by the SecondLife(tm) client. - + - Use the autopilot sim function to move the avatar to a new - position. Uses double precision to get precise movements + Searialize an animation asset into it's joints/keyframes/meta data - The z value is currently not handled properly by the simulator - Global X coordinate to move to - Global Y coordinate to move to - Z coordinate to move to + + - + - Use the autopilot sim function to move the avatar to a new position + Rotation Keyframe count (used internally) - The z value is currently not handled properly by the simulator - Integer value for the global X coordinate to move to - Integer value for the global Y coordinate to move to - Floating-point value for the Z coordinate to move to - + - Use the autopilot sim function to move the avatar to a new position + Position Keyframe count (used internally) - The z value is currently not handled properly by the simulator - Integer value for the local X coordinate to move to - Integer value for the local Y coordinate to move to - Floating-point value for the Z coordinate to move to - - - Macro to cancel autopilot sim function - Not certain if this is how it is really done - true if control flags were set and AgentUpdate was sent to the simulator - + - Grabs an object + Animation Priority - an unsigned integer of the objects ID within the simulator - - + - Overload: Grab a simulated object + The animation length in seconds. - an unsigned integer of the objects ID within the simulator - - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - + - Drag an object + Expression set in the client. Null if [None] is selected - of the object to drag - Drag target in region coordinates - + - Overload: Drag an object + The time in seconds to start the animation - of the object to drag - Drag target in region coordinates - - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - + - Release a grabbed object + The time in seconds to end the animation - The Objects Simulator Local ID - - - - + - Release a grabbed object + Loop the animation - The Objects Simulator Local ID - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - + - Touches an object + Meta data. Ease in Seconds. - an unsigned integer of the objects ID within the simulator - - + - Request the current L$ balance + Meta data. Ease out seconds. - + - Give Money to destination Avatar + Meta Data for the Hand Pose - UUID of the Target Avatar - Amount in L$ - + - Give Money to destination Avatar + Number of joints defined in the animation - UUID of the Target Avatar - Amount in L$ - Description that will show up in the - recipients transaction history - + - Give L$ to an object + Contains an array of joints - object to give money to - amount of L$ to give - name of object - + - Give L$ to a group + Variable length strings seem to be null terminated in the animation asset.. but.. + use with caution, home grown. + advances the index. - group to give money to - amount of L$ to give + The animation asset byte array + The offset to start reading + a string - + - Give L$ to a group + Read in a Joint from an animation asset byte array + Variable length Joint fields, yay! + Advances the index - group to give money to - amount of L$ to give - description of transaction + animation asset byte array + Byte Offset of the start of the joint + The Joint data serialized into the binBVHJoint structure - + - Pay texture/animation upload fee + Read Keyframes of a certain type + advance i + Animation Byte array + Offset in the Byte Array. Will be advanced + Number of Keyframes + Scaling Min to pass to the Uint16ToFloat method + Scaling Max to pass to the Uint16ToFloat method + + - + - Pay texture/animation upload fee + A Joint and it's associated meta data and keyframes - description of the transaction - + - Give Money to destination Object or Avatar + Name of the Joint. Matches the avatar_skeleton.xml in client distros - UUID of the Target Object/Avatar - Amount in L$ - Reason (Optional normally) - The type of transaction - Transaction flags, mostly for identifying group - transactions - + - Plays a gesture + Joint Animation Override? Was the same as the Priority in testing.. - Asset of the gesture - + - Mark gesture active + Array of Rotation Keyframes in order from earliest to latest - Inventory of the gesture - Asset of the gesture - + - Mark gesture inactive + Array of Position Keyframes in order from earliest to latest + This seems to only be for the Pelvis? - Inventory of the gesture - + - Send an AgentAnimation packet that toggles a single animation on + A Joint Keyframe. This is either a position or a rotation. - The of the animation to start playing - Whether to ensure delivery of this packet or not - + - Send an AgentAnimation packet that toggles a single animation off + Either a Vector3 position or a Vector3 Euler rotation - The of a - currently playing animation to stop playing - Whether to ensure delivery of this packet or not - + - Send an AgentAnimation packet that will toggle animations on or off + Poses set in the animation metadata for the hands. - A list of animation s, and whether to - turn that animation on or off - Whether to ensure delivery of this packet or not - + - Teleports agent to their stored home location + Wrapper around a byte array that allows bit to be packed and unpacked + one at a time or by a variable amount. Useful for very tightly packed + data like LayerData packets - true on successful teleport to home location - + - Teleport agent to a landmark + Default constructor, initialize the bit packer / bit unpacker + with a byte array and starting position - of the landmark to teleport agent to - true on success, false on failure + Byte array to pack bits in to or unpack from + Starting position in the byte array - + - Attempt to look up a simulator name and teleport to the discovered - destination - Region name to look up - Position to teleport to - True if the lookup and teleport were successful, otherwise - false - + - Attempt to look up a simulator name and teleport to the discovered - destination - Region name to look up - Position to teleport to - Target to look at - True if the lookup and teleport were successful, otherwise - false - + - Teleport agent to another region - handle of region to teleport agent to - position in destination sim to teleport to - true on success, false on failure - This call is blocking - + - Teleport agent to another region + Pack a floating point value in to the data - handle of region to teleport agent to - position in destination sim to teleport to - direction in destination sim agent will look at - true on success, false on failure - This call is blocking + Floating point value to pack - + - Request teleport to a another simulator + Pack part or all of an integer in to the data - handle of region to teleport agent to - position in destination sim to teleport to + Integer containing the data to pack + Number of bits of the integer to pack - + - Request teleport to a another simulator + Pack part or all of an unsigned integer in to the data - handle of region to teleport agent to - position in destination sim to teleport to - direction in destination sim agent will look at + Unsigned integer containing the data to pack + Number of bits of the integer to pack - + - Teleport agent to a landmark + Pack a single bit in to the data - of the landmark to teleport agent to + Bit to pack - + - Send a teleport lure to another avatar with default "Join me in ..." invitation message - target avatars to lure + + + + + + + + - + - Send a teleport lure to another avatar with custom invitation message - target avatars to lure - custom message to send with invitation + + - + - Respond to a teleport lure by either accepting it and initiating - the teleport, or denying it - of the avatar sending the lure - true to accept the lure, false to decline it + + - + - Update agent profile + Unpacking a floating point value from the data - struct containing updated - profile information + Unpacked floating point value - + - Update agents profile interests + Unpack a variable number of bits from the data in to integer format - selection of interests from struct + Number of bits to unpack + An integer containing the unpacked bits + This function is only useful up to 32 bits - + - Set the height and the width of the client window. This is used - by the server to build a virtual camera frustum for our avatar + Unpack a variable number of bits from the data in to unsigned + integer format - New height of the viewer window - New width of the viewer window + Number of bits to unpack + An unsigned integer containing the unpacked bits + This function is only useful up to 32 bits - + - Request the list of muted objects and avatars for this agent + Unpack a 16-bit signed integer + 16-bit signed integer - + - Sets home location to agents current position + Unpack a 16-bit unsigned integer - will fire an AlertMessage () with - success or failure message + 16-bit unsigned integer - + - Move an agent in to a simulator. This packet is the last packet - needed to complete the transition in to a new simulator + Unpack a 32-bit signed integer - Object + 32-bit signed integer - + - Reply to script permissions request + Unpack a 32-bit unsigned integer - Object - of the itemID requesting permissions - of the taskID requesting permissions - list of permissions to allow + 32-bit unsigned integer - + - Respond to a group invitation by either accepting or denying it + Capabilities is the name of the bi-directional HTTP REST protocol + used to communicate non real-time transactions such as teleporting or + group messaging - UUID of the group (sent in the AgentID field of the invite message) - IM Session ID from the group invitation message - Accept the group invitation or deny it - + - Requests script detection of objects and avatars + Default constructor - name of the object/avatar to search for - UUID of the object or avatar to search for - Type of search from ScriptSensorTypeFlags - range of scan (96 max?) - the arc in radians to search within - an user generated ID to correlate replies with - Simulator to perform search in + + + + - + - Create or update profile pick + Triggered when an event is received via the EventQueueGet + capability - UUID of the pick to update, or random UUID to create a new pick - Is this a top pick? (typically false) - UUID of the parcel (UUID.Zero for the current parcel) - Name of the pick - Global position of the pick landmark - UUID of the image displayed with the pick - Long description of the pick + Event name + Decoded event data + The simulator that generated the event - - - Delete profile pick - - UUID of the pick to delete + + Reference to the simulator this system is connected to - - - Create or update profile Classified - - UUID of the classified to update, or random UUID to create a new classified - Defines what catagory the classified is in - UUID of the image displayed with the classified - Price that the classified will cost to place for a week - Global position of the classified landmark - Name of the classified - Long description of the classified - if true, auto renew classified after expiration + + Capabilities URI this system was initialized with - - - Create or update profile Classified - - UUID of the classified to update, or random UUID to create a new classified - Defines what catagory the classified is in - UUID of the image displayed with the classified - Price that the classified will cost to place for a week - Name of the classified - Long description of the classified - if true, auto renew classified after expiration + + Whether the capabilities event queue is connected and + listening for incoming events - + - Delete a classified ad + Request the URI of a named capability - The classified ads ID + Name of the capability to request + The URI of the requested capability, or String.Empty if + the capability does not exist - + - Take an incoming ImprovedInstantMessage packet, auto-parse, and if - OnInstantMessage is defined call that with the appropriate arguments + Process any incoming events, check to see if we have a message created for the event, - The sender - The EventArgs object containing the packet data + + + + - + - Take an incoming Chat packet, auto-parse, and if OnChat is defined call - that with the appropriate arguments. + Attempts to convert an LLSD structure to a known Packet type - The sender - The EventArgs object containing the packet data + Event name, this must match an actual + packet name for a Packet to be successfully built + LLSD to convert to a Packet + A Packet on success, otherwise null - - - Used for parsing llDialogs - - The sender - The EventArgs object containing the packet data + + Origin position of this coordinate frame - + + X axis of this coordinate frame, or Forward/At in grid terms + + + Y axis of this coordinate frame, or Left in grid terms + + + Z axis of this coordinate frame, or Up in grid terms + + - Used for parsing llRequestPermissions dialogs - The sender - The EventArgs object containing the packet data + Looking direction, must be a normalized vector + Up direction, must be a normalized vector - + - Handles Script Control changes when Script with permissions releases or takes a control + Align the coordinate frame X and Y axis with a given rotation + around the Z axis in radians - The sender - The EventArgs object containing the packet data + Absolute rotation around the Z axis in + radians - + - Used for parsing llLoadURL Dialogs + Access to the data server which allows searching for land, events, people, etc - The sender - The EventArgs object containing the packet data - + - Update client's Position, LookAt and region handle from incoming packet + Constructs a new instance of the DirectoryManager class - The sender - The EventArgs object containing the packet data - This occurs when after an avatar moves into a new sim + An instance of GridClient - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Classified Ad categories - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Classified is listed in the Any category - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Classified is shopping related - + + Classified is + + - Process TeleportFailed message sent via EventQueue, informs agent its last teleport has failed and why. - The Message Key - An IMessage object Deserialized from the recieved message event - The simulator originating the event message - + - Process TeleportFinish from Event Queue and pass it onto our TeleportHandler - The message system key for this event - IMessage object containing decoded data from OSD - The simulator originating the event message - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + - + - Crossed region handler for message that comes across the EventQueue. Sent to an agent - when the agent crosses a sim border into a new region. - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - This packet is now being sent via the EventQueue + + + - + - Group Chat event handler - The capability Key - IMessage object containing decoded data from OSD - - + + Event Categories + + - Response from request to join a group chat - - IMessage object containing decoded data from OSD - - + - Someone joined or left group chat - - IMessage object containing decoded data from OSD - - + - Handle a group chat Invitation - Caps Key - IMessage object containing decoded data from OSD - Originating Simulator - + - Moderate a chat session - the of the session to moderate, for group chats this will be the groups UUID - the of the avatar to moderate - Either "voice" to moderate users voice, or "text" to moderate users text session - true to moderate (silence user), false to allow avatar to speak - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + - - Raised when a scripted object or agent within range sends a public message + + + - - Raised when a scripted object sends a dialog box containing possible - options an agent can respond to + + + - - Raised when an object requests a change in the permissions an agent has permitted + + + - - Raised when a script requests an agent open the specified URL + + + - - Raised when an agents currency balance is updated + + + Query Flags used in many of the DirectoryManager methods to specify which query to execute and how to return the results. + Flags can be combined using the | (pipe) character, not all flags are available in all queries + - - Raised when a transaction occurs involving currency such as a land purchase + + Query the People database - - Raised when an ImprovedInstantMessage packet is recieved from the simulator, this is used for everything from - private messaging to friendship offers. The Dialog field defines what type of message has arrived + + + - - Raised when an agent has requested a teleport to another location, or when responding to a lure. Raised multiple times - for each teleport indicating the progress of the request + + + - - Raised when a simulator sends agent specific information for our avatar. + + Query the Groups database - - Raised when our agents animation playlist changes + + Query the Events database - - Raised when an object or avatar forcefully collides with our agent + + Query the land holdings database for land owned by the currently connected agent - - Raised when our agent crosses a region border into another region + + + - - Raised when our agent succeeds or fails to join a group chat session + + Query the land holdings database for land which is owned by a Group - - Raised when our agent exits a group chat session + + Specifies the query should pre sort the results based upon traffic + when searching the Places database - - Raised when a simulator sends an urgent message usually indication the recent failure of - another action we have attempted to take such as an attempt to enter a parcel where we are denied access + + + - - Raised when a script attempts to take or release specified controls for our agent + + + - - Raised when the simulator detects our agent is trying to view something - beyond its limits + + + - - Raised when a script sensor reply is received from a simulator + + + - - Raised in response to a request + + Specifies the query should pre sort the results in an ascending order when searching the land sales database. + This flag is only used when searching the land sales database - - Raised when an avatar enters a group chat session we are participating in + + Specifies the query should pre sort the results using the SalePrice field when searching the land sales database. + This flag is only used when searching the land sales database - - Raised when an agent exits a group chat session we are participating in + + Specifies the query should pre sort the results by calculating the average price/sq.m (SalePrice / Area) when searching the land sales database. + This flag is only used when searching the land sales database - - Your (client) avatars - "client", "agent", and "avatar" all represent the same thing + + Specifies the query should pre sort the results using the ParcelSize field when searching the land sales database. + This flag is only used when searching the land sales database - - Temporary assigned to this session, used for - verifying our identity in packets + + Specifies the query should pre sort the results using the Name field when searching the land sales database. + This flag is only used when searching the land sales database - - Shared secret that is never sent over the wire + + When set, only parcels less than the specified Price will be included when searching the land sales database. + This flag is only used when searching the land sales database - - Your (client) avatar ID, local to the current region/sim + + When set, only parcels greater than the specified Size will be included when searching the land sales database. + This flag is only used when searching the land sales database - - Where the avatar started at login. Can be "last", "home" - or a login + + + - - The access level of this agent, usually M or PG + + + - - The CollisionPlane of Agent + + Include PG land in results. This flag is used when searching both the Groups, Events and Land sales databases - - An representing the velocity of our agent - - - An representing the acceleration of our agent - - - A which specifies the angular speed, and axis about which an Avatar is rotating. - - - Position avatar client will goto when login to 'home' or during - teleport request to 'home' region. - - - LookAt point saved/restored with HomePosition - - - Avatar First Name (i.e. Philip) - - - Avatar Last Name (i.e. Linden) - - - Avatar Full Name (i.e. Philip Linden) - - - Gets the health of the agent - - - Gets the current balance of the agent - - - Gets the local ID of the prim the agent is sitting on, - zero if the avatar is not currently sitting - - - Gets the of the agents active group. - - - Gets the Agents powers in the currently active group - - - Current status message for teleporting - - - Current position of the agent as a relative offset from - the simulator, or the parent object if we are sitting on something - - - Current rotation of the agent as a relative rotation from - the simulator, or the parent object if we are sitting on something + + Include Mature land in results. This flag is used when searching both the Groups, Events and Land sales databases - - Current position of the agent in the simulator + + Include Adult land in results. This flag is used when searching both the Groups, Events and Land sales databases - + - A representing the agents current rotation - - Returns the global grid position of the avatar - - - - Agent movement and camera control - - Agent movement is controlled by setting specific - After the control flags are set, An AgentUpdate is required to update the simulator of the specified flags - This is most easily accomplished by setting one or more of the AgentMovement properties - - Movement of an avatar is always based on a compass direction, for example AtPos will move the - agent from West to East or forward on the X Axis, AtNeg will of course move agent from - East to West or backward on the X Axis, LeftPos will be South to North or forward on the Y Axis - The Z axis is Up, finer grained control of movements can be done using the Nudge properties - - - - Agent camera controls - - - Currently only used for hiding your group title - - - Action state of the avatar, which can currently be - typing and editing - - - - - - + + + Land types to search dataserver for + - - + + Search Auction, Mainland and Estate - - + + Land which is currently up for auction - - + + Parcels which are on the mainland (Linden owned) continents - - + + Parcels which are on privately owned simulators - - + + + The content rating of the event + - - + + Event is PG - - + + Event is Mature - - Timer for sending AgentUpdate packets + + Event is Adult - - Default constructor + + + Classified Ad Options + + There appear to be two formats the flags are packed in. + This set of flags is for the newer style - + - Send an AgentUpdate with the camera set at the current agent - position and pointing towards the heading specified - Camera rotation in radians - Whether to send the AgentUpdate reliable - or not - + - Rotates the avatar body and camera toward a target position. - This will also anchor the camera position on the avatar - Region coordinates to turn toward - + - Send new AgentUpdate packet to update our current camera - position and rotation - + - Send new AgentUpdate packet to update our current camera - position and rotation - Whether to require server acknowledgement - of this packet - + - Send new AgentUpdate packet to update our current camera - position and rotation - Whether to require server acknowledgement - of this packet - Simulator to send the update to - + - Builds an AgentUpdate packet entirely from parameters. This - will not touch the state of Self.Movement or - Self.Movement.Camera in any way + Classified ad query options - - - - - - - - - - - - - Move agent positive along the X axis + + Include all ads in results - - Move agent negative along the X axis + + Include PG ads in results - - Move agent positive along the Y axis + + Include Mature ads in results - - Move agent negative along the Y axis + + Include Adult ads in results - - Move agent positive along the Z axis + + + The For Sale flag in PlacesReplyData + - - Move agent negative along the Z axis + + Parcel is not listed for sale - - + + Parcel is For Sale - - + + + A classified ad on the grid + - - + + UUID for this ad, useful for looking up detailed + information about it - - + + The title of this classified ad - - + + Flags that show certain options applied to the classified - - + + Creation date of the ad - - + + Expiration date of the ad - - Causes simulator to make agent fly + + Price that was paid for this ad - - Stop movement + + Print the struct data as a string + A string containing the field name, and field value - - Finish animation + + + A parcel retrieved from the dataserver such as results from the + "For-Sale" listings or "Places" Search + - - Stand up from a sit + + The unique dataserver parcel ID + This id is used to obtain additional information from the entry + by using the method - - Tells simulator to sit agent on ground + + A string containing the name of the parcel - - Place agent into mouselook mode + + The size of the parcel + This field is not returned for Places searches - - Nudge agent positive along the X axis + + The price of the parcel + This field is not returned for Places searches - - Nudge agent negative along the X axis + + If True, this parcel is flagged to be auctioned - - Nudge agent positive along the Y axis + + If true, this parcel is currently set for sale - - Nudge agent negative along the Y axis + + Parcel traffic - - Nudge agent positive along the Z axis + + Print the struct data as a string + A string containing the field name, and field value - - Nudge agent negative along the Z axis + + + An Avatar returned from the dataserver + - - - - - - - - Tell simulator to mark agent as away + + Online status of agent + This field appears to be obsolete and always returns false - - + + The agents first name - - + + The agents last name - - + + The agents - - + + Print the struct data as a string + A string containing the field name, and field value - + - Returns "always run" value, or changes it by sending a SetAlwaysRunPacket + Response to a "Groups" Search - - The current value of the agent control flags + + The Group ID - - Gets or sets the interval in milliseconds at which - AgentUpdate packets are sent to the current simulator. Setting - this to a non-zero value will also enable the packet sending if - it was previously off, and setting it to zero will disable + + The name of the group - - Gets or sets whether AgentUpdate packets are sent to - the current simulator + + The current number of members - - Reset movement controls every time we send an update + + Print the struct data as a string + A string containing the field name, and field value - + - Camera controls for the agent, mostly a thin wrapper around - CoordinateFrame. This class is only responsible for state - tracking and math, it does not send any packets + Parcel information returned from a request + + Represents one of the following: + A parcel of land on the grid that has its Show In Search flag set + A parcel of land owned by the agent making the request + A parcel of land owned by a group the agent making the request is a member of + + In a request for Group Land, the First record will contain an empty record + + Note: This is not the same as searching the land for sale data source - - - - - The camera is a local frame of reference inside of - the larger grid space. This is where the math happens + + The ID of the Agent of Group that owns the parcel - - - Default constructor - + + The name - - + + The description - - + + The Size of the parcel - - + + The billable Size of the parcel, for mainland + parcels this will match the ActualArea field. For Group owned land this will be 10 percent smaller + than the ActualArea. For Estate land this will always be 0 - - + + Indicates the ForSale status of the parcel - - - Used to specify movement actions for your agent - + + The Gridwide X position - - Empty flag + + The Gridwide Y position - - Move Forward (SL Keybinding: W/Up Arrow) + + The Z position of the parcel, or 0 if no landing point set - - Move Backward (SL Keybinding: S/Down Arrow) + + The name of the Region the parcel is located in - - Move Left (SL Keybinding: Shift-(A/Left Arrow)) + + The Asset ID of the parcels Snapshot texture - - Move Right (SL Keybinding: Shift-(D/Right Arrow)) + + The calculated visitor traffic - - Not Flying: Jump/Flying: Move Up (SL Keybinding: E) + + The billing product SKU + Known values are: + 023Mainland / Full Region024Estate / Full Region027Estate / Openspace029Estate / Homestead129Mainland / Homestead (Linden Owned) - - Not Flying: Croutch/Flying: Move Down (SL Keybinding: C) + + No longer used, will always be 0 - - Unused + + Get a SL URL for the parcel + A string, containing a standard SLURL - - Unused + + Print the struct data as a string + A string containing the field name, and field value - - Unused + + + An "Event" Listing summary + - - Unused + + The ID of the event creator - - ORed with AGENT_CONTROL_AT_* if the keyboard is being used + + The name of the event - - ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used + + The events ID - - ORed with AGENT_CONTROL_UP_* if the keyboard is being used + + A string containing the short date/time the event will begin - - Fly + + The event start time in Unixtime (seconds since epoch) - - + + The events maturity rating - - Finish our current animation + + Print the struct data as a string + A string containing the field name, and field value - - Stand up from the ground or a prim seat + + + The details of an "Event" + - - Sit on the ground at our current location + + The events ID - - Whether mouselook is currently enabled + + The ID of the event creator - - Legacy, used if a key was pressed for less than a certain amount of time + + The name of the event - - Legacy, used if a key was pressed for less than a certain amount of time + + The category - - Legacy, used if a key was pressed for less than a certain amount of time + + The events description - - Legacy, used if a key was pressed for less than a certain amount of time + + The short date/time the event will begin - - Legacy, used if a key was pressed for less than a certain amount of time + + The event start time in Unixtime (seconds since epoch) UTC adjusted - - Legacy, used if a key was pressed for less than a certain amount of time + + The length of the event in minutes - - + + 0 if no cover charge applies - - + + The cover charge amount in L$ if applicable - - Set when the avatar is idled or set to away. Note that the away animation is - activated separately from setting this flag + + The name of the region where the event is being held - - + + The gridwide location of the event - - + + The maturity rating - - + + Get a SL URL for the parcel where the event is hosted + A string, containing a standard SLURL - - + + Print the struct data as a string + A string containing the field name, and field value - - - Represents a single Voice Session to the Vivox service. - + + The event subscribers. null if no subcribers - - - Close this session. - + + Thread sync lock object - - - Look up an existing Participants in this session - - - + + The event subscribers. null if no subcribers - - Positional vector of the users position + + Thread sync lock object - - Velocity vector of the position + + The event subscribers. null if no subcribers - - At Orientation (X axis) of the position + + Thread sync lock object - - Up Orientation (Y axis) of the position + + The event subscribers. null if no subcribers - - Left Orientation (Z axis) of the position + + Thread sync lock object - - - The type of bump-mapping applied to a face - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raises the EventInfoReply event + An EventInfoReplyEventArgs object containing the + data returned from the data server - - + + Raises the DirEventsReply event + An DirEventsReplyEventArgs object containing the + data returned from the data server - - + + Raises the PlacesReply event + A PlacesReplyEventArgs object containing the + data returned from the data server - - - The level of shininess applied to a face - + + Raises the DirPlacesReply event + A DirPlacesReplyEventArgs object containing the + data returned from the data server - - + + Raises the DirClassifiedsReply event + A DirClassifiedsReplyEventArgs object containing the + data returned from the data server - - + + Raises the DirGroupsReply event + A DirGroupsReplyEventArgs object containing the + data returned from the data server - - + + Raises the DirPeopleReply event + A DirPeopleReplyEventArgs object containing the + data returned from the data server - - + + Raises the DirLandReply event + A DirLandReplyEventArgs object containing the + data returned from the data server - + - The texture mapping style used for a face + Query the data server for a list of classified ads containing the specified string. + Defaults to searching for classified placed in any category, and includes PG, Adult and Mature + results. + Responses are sent 16 per response packet, there is no way to know how many results a query reply will contain however assuming + the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received + The event is raised when a response is received from the simulator + A string containing a list of keywords to search for + A UUID to correlate the results when the event is raised - - - - - - - + - Flags in the TextureEntry block that describe which properties are - set + Query the data server for a list of classified ads which contain specified keywords (Overload) + The event is raised when a response is received from the simulator + A string containing a list of keywords to search for + The category to search + A set of flags which can be ORed to modify query options + such as classified maturity rating. + A UUID to correlate the results when the event is raised + + Search classified ads containing the key words "foo" and "bar" in the "Any" category that are either PG or Mature + + UUID searchID = StartClassifiedSearch("foo bar", ClassifiedCategories.Any, ClassifiedQueryFlags.PG | ClassifiedQueryFlags.Mature); + + + Responses are sent 16 at a time, there is no way to know how many results a query reply will contain however assuming + the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - Abstract base for rendering plugins + Starts search for places (Overloaded) + The event is raised when a response is received from the simulator + Search text + Each request is limited to 100 places + being returned. To get the first 100 result entries of a request use 0, + from 100-199 use 1, 200-299 use 2, etc. + A UUID to correlate the results when the event is raised - + - Generates a basic mesh structure from a primitive + Queries the dataserver for parcels of land which are flagged to be shown in search + The event is raised when a response is received from the simulator - Primitive to generate the mesh from - Level of detail to generate the mesh at - The generated mesh + A string containing a list of keywords to search for separated by a space character + A set of flags which can be ORed to modify query options + such as classified maturity rating. + The category to search + Each request is limited to 100 places + being returned. To get the first 100 result entries of a request use 0, + from 100-199 use 1, 200-299 use 2, etc. + A UUID to correlate the results when the event is raised + + Search places containing the key words "foo" and "bar" in the "Any" category that are either PG or Adult + + UUID searchID = StartDirPlacesSearch("foo bar", DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeAdult, ParcelCategory.Any, 0); + + + Additional information on the results can be obtained by using the ParcelManager.InfoRequest method + - + - Generates a a series of faces, each face containing a mesh and - metadata + Starts a search for land sales using the directory + The event is raised when a response is received from the simulator - Primitive to generate the mesh from - Level of detail to generate the mesh at - The generated mesh + What type of land to search for. Auction, + estate, mainland, "first land", etc + The OnDirLandReply event handler must be registered before + calling this function. There is no way to determine how many + results will be returned, or how many times the callback will be + fired other than you won't get more than 100 total parcels from + each query. - + - Apply texture coordinate modifications from a - to a list of vertices + Starts a search for land sales using the directory + The event is raised when a response is received from the simulator - Vertex list to modify texture coordinates for - Center-point of the face - Face texture parameters + What type of land to search for. Auction, + estate, mainland, "first land", etc + Maximum price to search for + Maximum area to search for + Each request is limited to 100 parcels + being returned. To get the first 100 parcels of a request use 0, + from 100-199 use 1, 200-299 use 2, etc. + The OnDirLandReply event handler must be registered before + calling this function. There is no way to determine how many + results will be returned, or how many times the callback will be + fired other than you won't get more than 100 total parcels from + each query. - + - Temporary code to produce a tar archive in tar v7 format + Send a request to the data server for land sales listings + Flags sent to specify query options + Available flags: + Specify the parcel rating with one or more of the following: + IncludePG IncludeMature IncludeAdult + Specify the field to pre sort the results with ONLY ONE of the following: + PerMeterSort NameSort AreaSort PricesSort + Specify the order the results are returned in, if not specified the results are pre sorted in a Descending Order + SortAsc + Specify additional filters to limit the results with one or both of the following: + LimitByPrice LimitByArea + Flags can be combined by separating them with the | (pipe) character + Additional details can be found in + What type of land to search for. Auction, + Estate or Mainland + Maximum price to search for when the + DirFindFlags.LimitByPrice flag is specified in findFlags + Maximum area to search for when the + DirFindFlags.LimitByArea flag is specified in findFlags + Each request is limited to 100 parcels + being returned. To get the first 100 parcels of a request use 0, + from 100-199 use 100, 200-299 use 200, etc. + + The event will be raised with the response from the simulator + There is no way to determine how many results will be returned, or how many times the callback will be + fired other than you won't get more than 100 total parcels from + each reply. + Any land set for sale to either anybody or specific to the connected agent will be included in the + results if the land is included in the query + + + + // request all mainland, any maturity rating that is larger than 512 sq.m + StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByArea | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, SearchTypeFlags.Mainland, 0, 512, 0); + + - + - Binary writer for the underlying stream + Search for Groups + The name or portion of the name of the group you wish to search for + Start from the match number + + - + - Write a directory entry to the tar archive. We can only handle one path level right now! + Search for Groups - + The name or portion of the name of the group you wish to search for + Start from the match number + Search flags + + - + - Write a file to the tar archive + Search the People directory for other avatars - - + The name or portion of the name of the avatar you wish to search for + + + + - + - Write a file to the tar archive + Search Places for parcels of land you personally own - - - + - Finish writing the raw tar archive data to a stream. The stream will be closed on completion. + Searches Places for land owned by the specified group + ID of the group you want to recieve land list for (You must be a member of the group) + Transaction (Query) ID which can be associated with results from your request. - + - Write a particular entry + Search the Places directory for parcels that are listed in search and contain the specified keywords - - - + A string containing the keywords to search for + Transaction (Query) ID which can be associated with results from your request. - + - Temporary code to do the bare minimum required to read a tar archive for our purposes + Search Places - All Options + One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc. + One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer + A string containing a list of keywords to search for separated by a space character + String Simulator Name to search in + LLUID of group you want to recieve results for + Transaction (Query) ID which can be associated with results from your request. + Transaction (Query) ID which can be associated with results from your request. - + - Binary reader for the underlying stream + Search All Events with specifid searchText in all categories, includes PG, Mature and Adult + A string containing a list of keywords to search for separated by a space character + Each request is limited to 100 entries + being returned. To get the first group of entries of a request use 0, + from 100-199 use 100, 200-299 use 200, etc. + UUID of query to correlate results in callback. - + - Used to trim off null chars + Search Events + A string containing a list of keywords to search for separated by a space character + One or more of the following flags: DateEvents, IncludePG, IncludeMature, IncludeAdult + from the Enum + Multiple flags can be combined by separating the flags with the | (pipe) character + "u" for in-progress and upcoming events, -or- number of days since/until event is scheduled + For example "0" = Today, "1" = tomorrow, "2" = following day, "-1" = yesterday, etc. + Each request is limited to 100 entries + being returned. To get the first group of entries of a request use 0, + from 100-199 use 100, 200-299 use 200, etc. + EventCategory event is listed under. + UUID of query to correlate results in callback. - - - Used to trim off space chars - + + Requests Event Details + ID of Event returned from the method - - - Generate a tar reader which reads from the given stream. - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Read the next entry in the tar file. - - - - the data for the entry. Returns null if there are no more entries + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Read the next 512 byte chunk of data as a tar header. - - A tar header struct. null if we have reached the end of the archive. + + Process an incoming event message + The Unique Capabilities Key + The event message containing the data + The simulator the message originated from - - - Read data following a header - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Convert octal bytes to a decimal representation - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Simulator (region) properties - + + Process an incoming event message + The Unique Capabilities Key + The event message containing the data + The simulator the message originated from - - No flags set + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Agents can take damage and be killed + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Landmarks can be created here + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Home position can be set in this sim + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Home position is reset when an agent teleports away + + Contains the Event data returned from the data server from an EventInfoRequest - - Sun does not move + + Construct a new instance of the EventInfoReplyEventArgs class + A single EventInfo object containing the details of an event - - No object, land, etc. taxes + + + A single EventInfo object containing the details of an event + - - Disable heightmap alterations (agents can still plant - foliage) + + Contains the "Event" detail data returned from the data server - - Land cannot be released, sold, or purchased + + Construct a new instance of the DirEventsReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list containing the "Events" returned by the search query - - All content is wiped nightly + + The ID returned by - - Unknown: Related to the availability of an overview world map tile.(Think mainland images when zoomed out.) + + A list of "Events" returned by the data server - - Unknown: Related to region debug flags. Possibly to skip processing of agent interaction with world. + + Contains the "Event" list data returned from the data server - - Region does not update agent prim interest lists. Internal debugging option. + + Construct a new instance of PlacesReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list containing the "Places" returned by the data server query - - No collision detection for non-agent objects + + The ID returned by - - No scripts are ran + + A list of "Places" returned by the data server - - All physics processing is turned off + + Contains the places data returned from the data server - - Region can be seen from other regions on world map. (Legacy world map option?) + + Construct a new instance of the DirPlacesReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list containing land data returned by the data server - - Region can be seen from mainland on world map. (Legacy world map option?) + + The ID returned by - - Agents not explicitly on the access list can visit the region. + + A list containing Places data returned by the data server - - Traffic calculations are not run across entire region, overrides parcel settings. + + Contains the classified data returned from the data server - - Flight is disabled (not currently enforced by the sim) + + Construct a new instance of the DirClassifiedsReplyEventArgs class + A list of classified ad data returned from the data server - - Allow direct (p2p) teleporting + + A list containing Classified Ads returned by the data server - - Estate owner has temporarily disabled scripting + + Contains the group data returned from the data server - - Restricts the usage of the LSL llPushObject function, applies to whole region. + + Construct a new instance of the DirGroupsReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list of groups data returned by the data server - - Deny agents with no payment info on file + + The ID returned by - - Deny agents with payment info on file + + A list containing Groups data returned by the data server - - Deny agents who have made a monetary transaction + + Contains the people data returned from the data server - - Parcels within the region may be joined or divided by anyone, not just estate owners/managers. + + Construct a new instance of the DirPeopleReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list of people data returned by the data server - - Abuse reports sent from within this region are sent to the estate owner defined email. + + The ID returned by - - Region is Voice Enabled + + A list containing People data returned by the data server - - Removes the ability from parcel owners to set their parcels to show in search. + + Contains the land sales data returned from the data server - - Deny agents who have not been age verified from entering the region. + + Construct a new instance of the DirLandReplyEventArgs class + A list of parcels for sale returned by the data server - + + A list containing land forsale data returned by the data server + + - Access level for a simulator + Represends individual HTTP Download request - - Minimum access level, no additional checks + + Default constructor - - Trial accounts allowed + + Constructor - - PG rating + + URI of the item to fetch - - Mature rating + + Timout specified in milliseconds - - Simulator is offline + + Download progress callback - - Simulator does not exist + + Download completed callback - - - - + + Accept the following content type - + - + Manages async HTTP downloads with a limit on maximum + concurrent downloads - - - Initialize the UDP packet handler in server mode - - Port to listening for incoming UDP packets on + + Default constructor - - - Initialize the UDP packet handler in client mode - - Remote UDP server to connect to + + Maximum number of parallel downloads from a single endpoint - - - - + + Client certificate - + + Cleanup method + + + Setup http download request + + + Check the queue for pending work + + + Enqueue a new HTPP download + + + Describes tasks returned in LandStatReply + + - + Estate level administration and utilities - + - + Constructor for EstateTools class + + - - A public reference to the client that this Simulator object - is attached to - - - A Unique Cache identifier for this simulator + + Used in the ReportType field of a LandStatRequest - - The capabilities for this simulator + + Used by EstateOwnerMessage packets - - + + Used by EstateOwnerMessage packets - - The current version of software this simulator is running + + + - - + + No flags set - - A 64x64 grid of parcel coloring values. The values stored - in this array are of the type + + Only return targets scripted objects - - + + Only return targets objects if on others land - - + + Returns target's scripted objects and objects on other parcels - - + + Ground texture settings for each corner of the region - - + + Used by GroundTextureHeightSettings - - + + The high and low texture thresholds for each corner of the sim - - + + Textures for each of the four terrain height levels - - + + Upper/lower texture boundaries for each corner of the sim - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - true if your agent has Estate Manager rights on this region + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - Statistics information for this simulator and the - connection to the simulator, calculated by the simulator itself - and the library + + Raised when the data server responds to a request. - - The regions Unique ID + + Raised when the data server responds to a request. - - The physical data center the simulator is located - Known values are: - - Dallas - Chandler - SF - - + + Raised when the data server responds to a request. - - The CPU Class of the simulator - Most full mainland/estate sims appear to be 5, - Homesteads and Openspace appear to be 501 + + Raised when the data server responds to a request. - - The number of regions sharing the same CPU as this one - "Full Sims" appear to be 1, Homesteads appear to be 4 + + Raised when the data server responds to a request. - - The billing product name - Known values are: - - Mainland / Full Region (Sku: 023) - Estate / Full Region (Sku: 024) - Estate / Openspace (Sku: 027) - Estate / Homestead (Sku: 029) - Mainland / Homestead (Sku: 129) (Linden Owned) - Mainland / Linden Homes (Sku: 131) - - + + Raised when the data server responds to a request. - - The billing product SKU - Known values are: - - 023 Mainland / Full Region - 024 Estate / Full Region - 027 Estate / Openspace - 029 Estate / Homestead - 129 Mainland / Homestead (Linden Owned) - 131 Linden Homes / Full Region - - + + Raised when the data server responds to a request. - - - A thread-safe dictionary containing avatars in a simulator - + + Raised when the data server responds to a request. - - - A thread-safe dictionary containing primitives in a simulator - + + Raises the TopCollidersReply event + A TopCollidersReplyEventArgs object containing the + data returned from the data server - - The current sequence number for packets sent to this - simulator. Must be Interlocked before modifying. Only - useful for applications manipulating sequence numbers + + Raises the TopScriptsReply event + A TopScriptsReplyEventArgs object containing the + data returned from the data server - - - Provides access to an internal thread-safe dictionary containing parcel - information found in this simulator - + + Raises the EstateUsersReply event + A EstateUsersReplyEventArgs object containing the + data returned from the data server - - - Checks simulator parcel map to make sure it has downloaded all data successfully - - true if map is full (contains no 0's) + + Raises the EstateGroupsReply event + A EstateGroupsReplyEventArgs object containing the + data returned from the data server - - Used internally to track sim disconnections + + Raises the EstateManagersReply event + A EstateManagersReplyEventArgs object containing the + data returned from the data server - - Event that is triggered when the simulator successfully - establishes a connection + + Raises the EstateBansReply event + A EstateBansReplyEventArgs object containing the + data returned from the data server - - Whether this sim is currently connected or not. Hooked up - to the property Connected + + Raises the EstateCovenantReply event + A EstateCovenantReplyEventArgs object containing the + data returned from the data server - - Coarse locations of avatars in this simulator + + Raises the EstateUpdateInfoReply event + A EstateUpdateInfoReplyEventArgs object containing the + data returned from the data server - - AvatarPositions key representing TrackAgent target + + + Requests estate information such as top scripts and colliders + + + + + + + + + - - Sequence numbers of packets we've received - (for duplicate checking) + + Requests estate settings, including estate manager and access/ban lists - - Packets we sent out that need ACKs from the simulator + + Requests the "Top Scripts" list for the current region - - Sequence number for pause/resume + + Requests the "Top Colliders" list for the current region - + - + Set several estate specific configuration variables - Reference to the GridClient object - IPEndPoint of the simulator - handle of the simulator + The Height of the waterlevel over the entire estate. Defaults to 20 + The maximum height change allowed above the baked terrain. Defaults to 4 + The minimum height change allowed below the baked terrain. Defaults to -4 + true to use + if True forces the sun position to the position in SunPosition + The current position of the sun on the estate, or when FixedSun is true the static position + the sun will remain. 6.0 = Sunrise, 30.0 = Sunset - + - Called when this Simulator object is being destroyed + Request return of objects owned by specified avatar + The Agents owning the primitives to return + specify the coverage and type of objects to be included in the return + true to perform return on entire estate - + - Attempt to connect to this simulator - Whether to move our agent in to this sim or not - True if the connection succeeded or connection status is - unknown, false if there was a failure + + + + - + - Disconnect from this simulator + Used for setting and retrieving various estate panel settings + EstateOwnerMessage Method field + List of parameters to include - + - Instructs the simulator to stop sending update (and possibly other) packets + Kick an avatar from an estate + Key of Agent to remove - + - Instructs the simulator to resume sending update packets (unpause) - + Ban an avatar from an estate + Key of Agent to remove + Ban user from this estate and all others owned by the estate owner - + + Unban an avatar from an estate + Key of Agent to remove + /// Unban user from this estate and all others owned by the estate owner + - Sends a packet + Send a message dialog to everyone in an entire estate - Packet to be sent + Message to send all users in the estate - + - + Send a message dialog to everyone in a simulator + Message to send all users in the simulator - + - Returns Simulator Name as a String + Send an avatar back to their home location - + Key of avatar to send home - + - + Begin the region restart process - - + - + Cancels a region restart - - - + + Estate panel "Region" tab settings + + + Estate panel "Debug" tab settings + + + Used for setting the region's terrain textures for its four height levels + + + + + + + + + + + Used for setting sim terrain texture heights + + + Requests the estate covenant + + - Sends out pending acknowledgements + Upload a terrain RAW file + A byte array containing the encoded terrain data + The name of the file being uploaded + The Id of the transfer request - + - Resend unacknowledged packets + Teleports all users home in current Estate - + - Provides access to an internal thread-safe multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. - + Remove estate manager + Key of Agent to Remove + removes manager to this estate and all others owned by the estate owner - - The IP address and port of the server + + + Add estate manager + Key of Agent to Add + Add agent as manager to this estate and all others owned by the estate owner - - Whether there is a working connection to the simulator or - not + + + Add's an agent to the estate Allowed list + Key of Agent to Add + Add agent as an allowed reisdent to All estates if true - - Coarse locations of avatars in this simulator + + + Removes an agent from the estate Allowed list + Key of Agent to Remove + Removes agent as an allowed reisdent from All estates if true - - AvatarPositions key representing TrackAgent target + + + Add's a group to the estate Allowed list + Key of Group to Add + Add Group as an allowed group to All estates if true - + - Simulator Statistics - + Removes a group from the estate Allowed list + Key of Group to Remove + Removes Group as an allowed Group from All estates if true - - Total number of packets sent by this simulator to this agent + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Total number of packets received by this simulator to this agent + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Total number of bytes sent by this simulator to this agent + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Total number of bytes received by this simulator to this agent + + Raised on LandStatReply when the report type is for "top colliders" - - Time in seconds agent has been connected to simulator + + Construct a new instance of the TopCollidersReplyEventArgs class + The number of returned items in LandStatReply + Dictionary of Object UUIDs to tasks returned in LandStatReply - - Total number of packets that have been resent + + + The number of returned items in LandStatReply + - - Total number of resent packets recieved + + + A Dictionary of Object UUIDs to tasks returned in LandStatReply + - - Total number of pings sent to this simulator by this agent + + Raised on LandStatReply when the report type is for "top Scripts" - - Total number of ping replies sent to this agent by this simulator + + Construct a new instance of the TopScriptsReplyEventArgs class + The number of returned items in LandStatReply + Dictionary of Object UUIDs to tasks returned in LandStatReply - + - Incoming bytes per second + The number of scripts returned in LandStatReply - It would be nice to have this claculated on the fly, but - this is far, far easier - + - Outgoing bytes per second + A Dictionary of Object UUIDs to tasks returned in LandStatReply - It would be nice to have this claculated on the fly, but - this is far, far easier - - Time last ping was sent - - - ID of last Ping sent + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateBansReplyEventArgs class + The estate's identifier on the grid + The number of returned items in LandStatReply + User UUIDs banned - - + + + The identifier of the estate + - - Current time dilation of this simulator + + + The number of returned itmes + - - Current Frames per second of simulator + + + List of UUIDs of Banned Users + - - Current Physics frames per second of simulator + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateUsersReplyEventArgs class + The estate's identifier on the grid + The number of users + Allowed users UUIDs - - + + + The identifier of the estate + - - + + + The number of returned items + - - + + + List of UUIDs of Allowed Users + - - + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateGroupsReplyEventArgs class + The estate's identifier on the grid + The number of Groups + Allowed Groups UUIDs - - + + + The identifier of the estate + - - + + + The number of returned items + - - Total number of objects Simulator is simulating + + + List of UUIDs of Allowed Groups + - - Total number of Active (Scripted) objects running + + Returned, along with other info, upon a successful .RequestInfo() - - Number of agents currently in this simulator + + Construct a new instance of the EstateManagersReplyEventArgs class + The estate's identifier on the grid + The number of Managers + Managers UUIDs - - Number of agents in neighbor simulators + + + The identifier of the estate + - - Number of Active scripts running in this simulator + + + The number of returned items + - - + + + List of UUIDs of the Estate's Managers + - - + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateCovenantReplyEventArgs class + The Covenant ID + The timestamp + The estate's name + The Estate Owner's ID (can be a GroupID) - - Number of downloads pending + + + The Covenant + - - Number of uploads pending + + + The timestamp + - - + + + The Estate name + - - + + + The Estate Owner's ID (can be a GroupID) + - - Number of local uploads pending + + Returned, along with other info, upon a successful .RequestInfo() - - Unacknowledged bytes in queue + + Construct a new instance of the EstateUpdateInfoReplyEventArgs class + The estate's name + The Estate Owners ID (can be a GroupID) + The estate's identifier on the grid + + - + - + The estate's name - - No report - - - Unknown report type + + + The Estate Owner's ID (can be a GroupID) + - - Bug report + + + The identifier of the estate on the grid + - - Complaint report + + + - - Customer service report + + + Registers, unregisters, and fires events generated by incoming packets + - + - Bitflag field for ObjectUpdateCompressed data blocks, describing - which options are present for each object + Default constructor + + - - Unknown + + + Object that is passed to worker threads in the ThreadPool for + firing packet callbacks + - - Whether the object has a TreeSpecies + + Callback to fire for this packet - - Whether the object has floating text ala llSetText + + Reference to the simulator that this packet came from - - Whether the object has an active particle system + + The packet that needs to be processed - - Whether the object has sound attached to it + + Reference to the GridClient object - - Whether the object is attached to a root object or not + + + Register an event handler + + Use PacketType.Default to fire this event on every + incoming packet + Packet type to register the handler for + Callback to be fired + True if this callback should be ran + asynchronously, false to run it synchronous - - Whether the object has texture animation settings + + + Unregister an event handler + + Packet type to unregister the handler for + Callback to be unregistered - - Whether the object has an angular velocity + + + Fire the events registered for this packet type + + Incoming packet type + Incoming packet + Simulator this packet was received from - - Whether the object has a name value pairs string + + + Registers, unregisters, and fires events generated by the Capabilities + event queue + - - Whether the object has a Media URL set + + + Default constructor + + Reference to the GridClient object - + - Specific Flags for MultipleObjectUpdate requests + Object that is passed to worker threads in the ThreadPool for + firing CAPS callbacks - - None + + Callback to fire for this packet - - Change position of prims + + Name of the CAPS event - - Change rotation of prims + + Strongly typed decoded data - - Change size of prims + + Reference to the simulator that generated this event - - Perform operation on link set + + Reference to the GridClient object - - Scale prims uniformly, same as selecing ctrl+shift in the - viewer. Used in conjunction with Scale + + + Register an new event handler for a capabilities event sent via the EventQueue + + Use String.Empty to fire this event on every CAPS event + Capability event name to register the + handler for + Callback to fire - + - Special values in PayPriceReply. If the price is not one of these - literal value of the price should be use + Unregister a previously registered capabilities handler + Capability event name unregister the + handler for + Callback to unregister - + - Indicates that this pay option should be hidden + Fire the events registered for this event type synchronously + Capability name + Decoded event body + Reference to the simulator that + generated this event - + - Indicates that this pay option should have the default value + Fire the events registered for this event type asynchronously + Capability name + Decoded event body + Reference to the simulator that + generated this event - + - Contains the variables sent in an object update packet for objects. - Used to track position and movement of prims and avatars - - + + The avatar has no rights - - + + The avatar can see the online status of the target avatar - - + + The avatar can see the location of the target avatar on the map - - + + The avatar can modify the ojects of the target avatar - - + + + This class holds information about an avatar in the friends list. There are two ways + to interface to this class. The first is through the set of boolean properties. This is the typical + way clients of this class will use it. The second interface is through two bitflag properties, + TheirFriendsRights and MyFriendsRights + - - + + + Used internally when building the initial list of friends at login time + + System ID of the avatar being prepesented + Rights the friend has to see you online and to modify your objects + Rights you have to see your friend online and to modify their objects - - + + + System ID of the avatar + - - + + + full name of the avatar + - - + + + True if the avatar is online + - - + + + True if the friend can see if I am online + - + - Handles all network traffic related to prims and avatar positions and - movement. + True if the friend can see me on the map - - The event subscribers, null of no subscribers + + + True if the freind can modify my objects + - - Raises the ObjectUpdate Event - A ObjectUpdateEventArgs object containing - the data sent from the simulator + + + True if I can see if my friend is online + - - Thread sync lock object + + + True if I can see if my friend is on the map + - - The event subscribers, null of no subscribers + + + True if I can modify my friend's objects + - - Raises the ObjectProperties Event - A ObjectPropertiesEventArgs object containing - the data sent from the simulator + + + My friend's rights represented as bitmapped flags + - - Thread sync lock object + + + My rights represented as bitmapped flags + - - The event subscribers, null of no subscribers + + + FriendInfo represented as a string + + A string reprentation of both my rights and my friends rights - - Raises the ObjectPropertiesUpdated Event - A ObjectPropertiesUpdatedEventArgs object containing - the data sent from the simulator + + + This class is used to add and remove avatars from your friends list and to manage their permission. + - - Thread sync lock object + + + Internal constructor + + A reference to the GridClient Object - - The event subscribers, null of no subscribers + + The event subscribers. null if no subcribers - - Raises the ObjectPropertiesFamily Event - A ObjectPropertiesFamilyEventArgs object containing - the data sent from the simulator + + Thread sync lock object - + + The event subscribers. null if no subcribers + + Thread sync lock object - - The event subscribers, null of no subscribers + + The event subscribers. null if no subcribers - - Raises the AvatarUpdate Event - A AvatarUpdateEventArgs object containing - the data sent from the simulator + + Thread sync lock object - + + The event subscribers. null if no subcribers + + Thread sync lock object - - The event subscribers, null of no subscribers + + The event subscribers. null if no subcribers + + + Thread sync lock object - - Raises the TerseObjectUpdate Event - A TerseObjectUpdateEventArgs object containing - the data sent from the simulator + + The event subscribers. null if no subcribers - + Thread sync lock object - - The event subscribers, null of no subscribers + + The event subscribers. null if no subcribers - - Raises the ObjectDataBlockUpdate Event - A ObjectDataBlockUpdateEventArgs object containing - the data sent from the simulator + + Thread sync lock object - + + The event subscribers. null if no subcribers + + Thread sync lock object - - The event subscribers, null of no subscribers + + + A dictionary of key/value pairs containing known friends of this avatar. + The Key is the of the friend, the value is a + object that contains detailed information including permissions you have and have given to the friend + - - Raises the KillObject Event - A KillObjectEventArgs object containing - the data sent from the simulator + + + A Dictionary of key/value pairs containing current pending frienship offers. + The key is the of the avatar making the request, + the value is the of the request which is used to accept + or decline the friendship offer + - - Thread sync lock object + + Raised when the simulator sends notification one of the members in our friends list comes online - - The event subscribers, null of no subscribers + + Raised when the simulator sends notification one of the members in our friends list goes offline - - Raises the AvatarSitChanged Event - A AvatarSitChangedEventArgs object containing - the data sent from the simulator + + Raised when the simulator sends notification one of the members in our friends list grants or revokes permissions - - Thread sync lock object + + Raised when the simulator sends us the names on our friends list - - The event subscribers, null of no subscribers + + Raised when the simulator sends notification another agent is offering us friendship - - Raises the PayPriceReply Event - A PayPriceReplyEventArgs object containing - the data sent from the simulator + + Raised when a request we sent to friend another agent is accepted or declined - - Thread sync lock object + + Raised when the simulator sends notification one of the members in our friends list has terminated + our friendship - - Reference to the GridClient object + + Raised when the simulator sends the location of a friend we have + requested map location info for - - Does periodic dead reckoning calculation to convert - velocity and acceleration to new positions for objects + + Raises the FriendOnline event + A FriendInfoEventArgs object containing the + data returned from the data server - + + Raises the FriendOffline event + A FriendInfoEventArgs object containing the + data returned from the data server + + + Raises the FriendRightsUpdate event + A FriendInfoEventArgs object containing the + data returned from the data server + + + Raises the FriendNames event + A FriendNamesEventArgs object containing the + data returned from the data server + + + Raises the FriendshipOffered event + A FriendshipOfferedEventArgs object containing the + data returned from the data server + + + Raises the FriendshipResponse event + A FriendshipResponseEventArgs object containing the + data returned from the data server + + + Raises the FriendshipTerminated event + A FriendshipTerminatedEventArgs object containing the + data returned from the data server + + + Raises the FriendFoundReply event + A FriendFoundReplyEventArgs object containing the + data returned from the data server + + - Construct a new instance of the ObjectManager class + Accept a friendship request - A reference to the instance + agentID of avatatar to form friendship with + imSessionID of the friendship request message - + - Request information for a single object from a - you are currently connected to + Decline a friendship request - The the object is located - The Local ID of the object + + of friend + imSessionID of the friendship request message - + - Request information for multiple objects contained in - the same simulator + Overload: Offer friendship to an avatar. - The the objects are located - An array containing the Local IDs of the objects - - - - Attempt to purchase an original object, a copy, or the contents of - an object - - The the object is located - The Local ID of the object - Whether the original, a copy, or the object - contents are on sale. This is used for verification, if the this - sale type is not valid for the object the purchase will fail - Price of the object. This is used for - verification, if it does not match the actual price the purchase - will fail - Group ID that will be associated with the new - purchase - Inventory folder UUID where the object or objects - purchased should be placed - - - BuyObject(Client.Network.CurrentSim, 500, SaleType.Copy, - 100, UUID.Zero, Client.Self.InventoryRootFolderUUID); - - + System ID of the avatar you are offering friendship to - + - Request prices that should be displayed in pay dialog. This will triggger the simulator - to send us back a PayPriceReply which can be handled by OnPayPriceReply event + Offer friendship to an avatar. - The the object is located - The ID of the object - The result is raised in the event + System ID of the avatar you are offering friendship to + A message to send with the request - + - Select a single object. This will cause the to send us - an which will raise the event + Terminate a friendship with an avatar - The the object is located - The Local ID of the object - + System ID of the avatar you are terminating the friendship with - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + - Select a single object. This will cause the to send us - an which will raise the event + Change the rights of a friend avatar. - The the object is located - The Local ID of the object - if true, a call to is - made immediately following the request - + the of the friend + the new rights to give the friend + This method will implicitly set the rights to those passed in the rights parameter. - + - Select multiple objects. This will cause the to send us - an which will raise the event - - The the objects are located - An array containing the Local IDs of the objects - Should objects be deselected immediately after selection - + Use to map a friends location on the grid. + + Friends UUID to find + + + - + - Select multiple objects. This will cause the to send us - an which will raise the event - - The the objects are located - An array containing the Local IDs of the objects - + Use to track a friends movement on the grid + + Friends Key - + - Update the properties of an object + Ask for a notification of friend's online status - The the object is located - The Local ID of the object - true to turn the objects physical property on - true to turn the objects temporary property on - true to turn the objects phantom property on - true to turn the objects cast shadows property on + Friend's UUID - + - Sets the sale properties of a single object + This handles the asynchronous response of a RequestAvatarNames call. - The the object is located - The Local ID of the object - One of the options from the enum - The price of the object + + + names cooresponding to the the list of IDs sent the the RequestAvatarNames call. - - - Sets the sale properties of multiple objects - - The the objects are located - An array containing the Local IDs of the objects - One of the options from the enum - The price of the object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Deselect a single object - - The the object is located - The Local ID of the object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Deselect multiple objects. - - The the objects are located - An array containing the Local IDs of the objects + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Perform a click action on an object - - The the object is located - The Local ID of the object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - Perform a click action (Grab) on a single object + Populate FriendList with data from the login reply - The the object is located - The Local ID of the object - The texture coordinates to touch - The surface coordinates to touch - The face of the position to touch - The region coordinates of the position to touch - The surface normal of the position to touch (A normal is a vector perpindicular to the surface) - The surface binormal of the position to touch (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space + true if login was successful + true if login request is requiring a redirect + A string containing the response to the login request + A string containing the reason for the request + A object containing the decoded + reply from the login server - - - Create (rez) a new prim object in a simulator - - A reference to the object to place the object in - Data describing the prim object to rez - Group ID that this prim will be set to, or UUID.Zero if you - do not want the object to be associated with a specific group - An approximation of the position at which to rez the prim - Scale vector to size this prim - Rotation quaternion to rotate this prim - Due to the way client prim rezzing is done on the server, - the requested position for an object is only close to where the prim - actually ends up. If you desire exact placement you'll need to - follow up by moving the object after it has been created. This - function will not set textures, light and flexible data, or other - extended primitive properties + + Contains information on a member of our friends list - + - Create (rez) a new prim object in a simulator + Construct a new instance of the FriendInfoEventArgs class - A reference to the object to place the object in - Data describing the prim object to rez - Group ID that this prim will be set to, or UUID.Zero if you - do not want the object to be associated with a specific group - An approximation of the position at which to rez the prim - Scale vector to size this prim - Rotation quaternion to rotate this prim - Specify the - Due to the way client prim rezzing is done on the server, - the requested position for an object is only close to where the prim - actually ends up. If you desire exact placement you'll need to - follow up by moving the object after it has been created. This - function will not set textures, light and flexible data, or other - extended primitive properties + The FriendInfo - - - Rez a Linden tree - - A reference to the object where the object resides - The size of the tree - The rotation of the tree - The position of the tree - The Type of tree - The of the group to set the tree to, - or UUID.Zero if no group is to be set - true to use the "new" Linden trees, false to use the old + + Get the FriendInfo - - - Rez grass and ground cover - - A reference to the object where the object resides - The size of the grass - The rotation of the grass - The position of the grass - The type of grass from the enum - The of the group to set the tree to, - or UUID.Zero if no group is to be set + + Contains Friend Names - + - Set the textures to apply to the faces of an object + Construct a new instance of the FriendNamesEventArgs class - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The texture data to apply + A dictionary where the Key is the ID of the Agent, + and the Value is a string containing their name - - - Set the textures to apply to the faces of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The texture data to apply - A media URL (not used) + + A dictionary where the Key is the ID of the Agent, + and the Value is a string containing their name - - - Set the Light data on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set + + Sent when another agent requests a friendship with our agent - + - Set the flexible data on an object + Construct a new instance of the FriendshipOfferedEventArgs class - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set + The ID of the agent requesting friendship + The name of the agent requesting friendship + The ID of the session, used in accepting or declining the + friendship offer - - - Set the sculptie texture and data on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set + + Get the ID of the agent requesting friendship - - - Unset additional primitive parameters on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The extra parameters to set + + Get the name of the agent requesting friendship - - - Link multiple prims into a linkset - - A reference to the object where the objects reside - An array which contains the IDs of the objects to link - The last object in the array will be the root object of the linkset TODO: Is this true? + + Get the ID of the session, used in accepting or declining the + friendship offer - - - Change the rotation of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new rotation of the object + + A response containing the results of our request to form a friendship with another agent - + - Set the name of an object + Construct a new instance of the FriendShipResponseEventArgs class - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A string containing the new name of the object + The ID of the agent we requested a friendship with + The name of the agent we requested a friendship with + true if the agent accepted our friendship offer - - - Set the name of multiple objects - - A reference to the object where the objects reside - An array which contains the IDs of the objects to change the name of - An array which contains the new names of the objects + + Get the ID of the agent we requested a friendship with - - - Set the description of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A string containing the new description of the object + + Get the name of the agent we requested a friendship with - + + true if the agent accepted our friendship offer + + + Contains data sent when a friend terminates a friendship with us + + - Set the descriptions of multiple objects + Construct a new instance of the FrindshipTerminatedEventArgs class - A reference to the object where the objects reside - An array which contains the IDs of the objects to change the description of - An array which contains the new descriptions of the objects + The ID of the friend who terminated the friendship with us + The name of the friend who terminated the friendship with us - + + Get the ID of the agent that terminated the friendship with us + + + Get the name of the agent that terminated the friendship with us + + - Attach an object to this avatar + Data sent in response to a request which contains the information to allow us to map the friends location - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The point on the avatar the object will be attached - The rotation of the attached object - + - Drop an attached object from this avatar + Construct a new instance of the FriendFoundReplyEventArgs class - A reference to the - object where the objects reside. This will always be the simulator the avatar is currently in - - The object's ID which is local to the simulator the object is in + The ID of the agent we have requested location information for + The region handle where our friend is located + The simulator local position our friend is located - + + Get the ID of the agent we have received location information for + + + Get the region handle where our mapped friend is located + + + Get the simulator local position where our friend is located + + - Detach an object from yourself + Main class to expose grid functionality to clients. All of the + classes needed for sending and receiving data are accessible through + this class. - A reference to the - object where the objects reside - - This will always be the simulator the avatar is currently in - - An array which contains the IDs of the objects to detach + + + // Example minimum code required to instantiate class and + // connect to a simulator. + using System; + using System.Collections.Generic; + using System.Text; + using OpenMetaverse; + namespace FirstBot + { + class Bot + { + public static GridClient Client; + static void Main(string[] args) + { + Client = new GridClient(); // instantiates the GridClient class + // to the global Client object + // Login to Simulator + Client.Network.Login("FirstName", "LastName", "Password", "FirstBot", "1.0"); + // Wait for a Keypress + Console.ReadLine(); + // Logout of simulator + Client.Network.Logout(); + } + } + } + + - + - Change the position of an object, Will change position of entire linkset + Default constructor - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new position of the object - + + Networking subsystem + + + Settings class including constant values and changeable + parameters for everything + + + Parcel (subdivided simulator lots) subsystem + + + Our own avatars subsystem + + + Other avatars subsystem + + + Estate subsystem + + + Friends list subsystem + + + Grid (aka simulator group) subsystem + + + Object subsystem + + + Group subsystem + + + Asset subsystem + + + Appearance subsystem + + + Inventory subsystem + + + Directory searches including classifieds, people, land + sales, etc + + + Handles land, wind, and cloud heightmaps + + + Handles sound-related networking + + + Throttling total bandwidth usage, or allocating bandwidth + for specific data stream types + + - Change the position of an object + Return the full name of this instance - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new position of the object - if true, will change position of (this) child prim only, not entire linkset + Client avatars full name - + - Change the Scale (size) of an object + Map layer request type - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new scale of the object - If true, will change scale of this prim only, not entire linkset - True to resize prims uniformly - + + Objects and terrain are shown + + + Only the terrain is shown, no objects + + + Overlay showing land for sale and for auction + + - Change the Rotation of an object that is either a child or a whole linkset + Type of grid item, such as telehub, event, populator location, etc. - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new scale of the object - If true, will change rotation of this prim only, not entire linkset - + + Telehub + + + PG rated event + + + Mature rated event + + + Popular location + + + Locations of avatar groups in a region + + + Land for sale + + + Classified ad + + + Adult rated event + + + Adult land for sale + + - Send a Multiple Object Update packet to change the size, scale or rotation of a primitive + Information about a region on the grid map - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new rotation, size, or position of the target object - The flags from the Enum - + + Sim X position on World Map + + + Sim Y position on World Map + + + Sim Name (NOTE: In lowercase!) + + - Deed an object (prim) to a group, Object must be shared with group which - can be accomplished with SetPermissions() - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The of the group to deed the object to - + + Appears to always be zero (None) + + + Sim's defined Water Height + + - Deed multiple objects (prims) to a group, Objects must be shared with group which - can be accomplished with SetPermissions() - A reference to the object where the object resides - An array which contains the IDs of the objects to deed - The of the group to deed the object to - + + UUID of the World Map image + + + Unique identifier for this region, a combination of the X + and Y position + + - Set the permissions on multiple objects - A reference to the object where the objects reside - An array which contains the IDs of the objects to set the permissions on - The new Who mask to set - The new Permissions mark to set - TODO: What does this do? + + - + - Request additional properties for an object - A reference to the object where the object resides - + + - + - Request additional properties for an object - A reference to the object where the object resides - Absolute UUID of the object - Whether to require server acknowledgement of this request + + + + - + - Set the ownership of a list of objects to the specified group + Visual chunk of the grid map - A reference to the object where the objects reside - An array which contains the IDs of the objects to set the group id on - The Groups ID - + - Update current URL of the previously set prim media + Base class for Map Items - UUID of the prim - Set current URL to this - Prim face number - Simulator in which prim is located - + + The Global X position of the item + + + The Global Y position of the item + + + Get the Local X position of the item + + + Get the Local Y position of the item + + + Get the Handle of the region + + - Set object media + Represents an agent or group of agents location - UUID of the prim - Array the length of prims number of faces. Null on face indexes where there is - no media, on faces which contain the media - Simulatior in which prim is located - + - Retrieve information about object media + Represents a Telehub location - UUID of the primitive - Simulator where prim is located - Call this callback when done - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - + - A terse object update, used when a transformation matrix or - velocity/acceleration for an object changes but nothing else - (scale/position/rotation/acceleration/velocity) + Represents a non-adult parcel of land for sale - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - + - Setup construction data for a basic primitive shape + Represents an Adult parcel of land for sale - Primitive shape to construct - Construction data that can be plugged into a - + - + Represents a PG Event - - - - - + - + Represents a Mature event - - - + - Set the Shape data of an object + Represents an Adult event - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - Data describing the prim shape - + - Set the Material data of an object + Manages grid-wide tasks such as the world map - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new material of the object - + - + Constructor - - - - + Instance of GridClient object to associate with this GridManager instance - - - - - - - - + + The event subscribers. null if no subcribers - - Raised when the simulator sends us data containing - A , Foliage or Attachment - - + + Thread sync lock object - - Raised when the simulator sends us data containing - additional information - - + + The event subscribers. null if no subcribers - - Raised when the simulator sends us data containing - Primitive.ObjectProperties for an object we are currently tracking + + Thread sync lock object - - Raised when the simulator sends us data containing - additional and details - + + The event subscribers. null if no subcribers - - Raised when the simulator sends us data containing - updated information for an + + Thread sync lock object - - Raised when the simulator sends us data containing - and movement changes + + The event subscribers. null if no subcribers - - Raised when the simulator sends us data containing - updates to an Objects DataBlock + + Thread sync lock object - - Raised when the simulator informs us an - or is no longer within view + + The event subscribers. null if no subcribers - - Raised when the simulator sends us data containing - updated sit information for our + + Thread sync lock object - - Raised when the simulator sends us data containing - purchase price information for a + + A dictionary of all the regions, indexed by region name - - - Callback for getting object media data via CAP - - Indicates if the operation was succesfull - Object media version string - Array indexed on prim face of media entry data + + A dictionary of all the regions, indexed by region handle - - Provides data for the event - The event occurs when the simulator sends - an containing a Primitive, Foliage or Attachment data - Note 1: The event will not be raised when the object is an Avatar - Note 2: It is possible for the to be - raised twice for the same object if for example the primitive moved to a new simulator, then returned to the current simulator or - if an Avatar crosses the border into a new simulator and returns to the current simulator - - - The following code example uses the , , and - properties to display new Primitives and Attachments on the window. - - // Subscribe to the event that gives us prim and foliage information - Client.Objects.ObjectUpdate += Objects_ObjectUpdate; - - - private void Objects_ObjectUpdate(object sender, PrimEventArgs e) - { - Console.WriteLine("Primitive {0} {1} in {2} is an attachment {3}", e.Prim.ID, e.Prim.LocalID, e.Simulator.Name, e.IsAttachment); - } - - - - - + + Raised when the simulator sends a + containing the location of agents in the simulator - - - Construct a new instance of the PrimEventArgs class - - The simulator the object originated from - The Primitive - The simulator time dilation - The prim was not in the dictionary before this update - true if the primitive represents an attachment to an agent + + Raised when the simulator sends a Region Data in response to + a Map request - - Get the simulator the originated from + + Raised when the simulator sends GridLayer object containing + a map tile coordinates and texture information - - Get the details + + Raised when the simulator sends GridItems object containing + details on events, land sales at a specific location - - true if the did not exist in the dictionary before this update (always true if object tracking has been disabled) + + Raised in response to a Region lookup - - true if the is attached to an + + Unknown - - Get the simulator Time Dilation + + Current direction of the sun - - Provides data for the event - The event occurs when the simulator sends - an containing Avatar data - Note 1: The event will not be raised when the object is an Avatar - Note 2: It is possible for the to be - raised twice for the same avatar if for example the avatar moved to a new simulator, then returned to the current simulator - - - The following code example uses the property to make a request for the top picks - using the method in the class to display the names - of our own agents picks listings on the window. - - // subscribe to the AvatarUpdate event to get our information - Client.Objects.AvatarUpdate += Objects_AvatarUpdate; - Client.Avatars.AvatarPicksReply += Avatars_AvatarPicksReply; - - private void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e) - { - // we only want our own data - if (e.Avatar.LocalID == Client.Self.LocalID) - { - // Unsubscribe from the avatar update event to prevent a loop - // where we continually request the picks every time we get an update for ourselves - Client.Objects.AvatarUpdate -= Objects_AvatarUpdate; - // make the top picks request through AvatarManager - Client.Avatars.RequestAvatarPicks(e.Avatar.ID); - } - } - - private void Avatars_AvatarPicksReply(object sender, AvatarPicksReplyEventArgs e) - { - // we'll unsubscribe from the AvatarPicksReply event since we now have the data - // we were looking for - Client.Avatars.AvatarPicksReply -= Avatars_AvatarPicksReply; - // loop through the dictionary and extract the names of the top picks from our profile - foreach (var pickName in e.Picks.Values) - { - Console.WriteLine(pickName); - } - } - - - - + + Current angular velocity of the sun - - - Construct a new instance of the AvatarUpdateEventArgs class - - The simulator the packet originated from - The data - The simulator time dilation - The avatar was not in the dictionary before this update + + Current world time - - Get the simulator the object originated from + + Raises the CoarseLocationUpdate event + A CoarseLocationUpdateEventArgs object containing the + data sent by simulator - - Get the data + + Raises the GridRegion event + A GridRegionEventArgs object containing the + data sent by simulator - - Get the simulator time dilation + + Raises the GridLayer event + A GridLayerEventArgs object containing the + data sent by simulator - - true if the did not exist in the dictionary before this update (always true if avatar tracking has been disabled) + + Raises the GridItems event + A GridItemEventArgs object containing the + data sent by simulator - - Provides additional primitive data for the event - The event occurs when the simulator sends - an containing additional details for a Primitive, Foliage data or Attachment data - The event is also raised when a request is - made. - - - The following code example uses the , and - - properties to display new attachments and send a request for additional properties containing the name of the - attachment then display it on the window. - - // Subscribe to the event that provides additional primitive details - Client.Objects.ObjectProperties += Objects_ObjectProperties; - - // handle the properties data that arrives - private void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e) - { - Console.WriteLine("Primitive Properties: {0} Name is {1}", e.Properties.ObjectID, e.Properties.Name); - } - - + + Raises the RegionHandleReply event + A RegionHandleReplyEventArgs object containing the + data sent by simulator - + - Construct a new instance of the ObjectPropertiesEventArgs class - The simulator the object is located - The primitive Properties + + - - Get the simulator the object is located + + + Request a map layer + + The name of the region + The type of layer - - Get the primitive properties + + + + + + + + + + + + + + + - - Provides additional primitive data for the event - The event occurs when the simulator sends - an containing additional details for a Primitive or Foliage data that is currently - being tracked in the dictionary - The event is also raised when a request is - made and is enabled - + + + + + + + + + + + + + - + - Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class - - The simulator the object is located - The Primitive - The primitive Properties + + + + + + + - - Get the simulator the object is located + + + Request data for all mainland (Linden managed) simulators + - - Get the primitive details + + + Request the region handle for the specified region UUID + + UUID of the region to look up - - Get the primitive properties + + + Get grid region information using the region name, this function + will block until it can find the region or gives up + + Name of sim you're looking for + Layer that you are requesting + Will contain a GridRegion for the sim you're + looking for if successful, otherwise an empty structure + True if the GridRegion was successfully fetched, otherwise + false - - Provides additional primitive data, permissions and sale info for the event - The event occurs when the simulator sends - an containing additional details for a Primitive, Foliage data or Attachment. This includes - Permissions, Sale info, and other basic details on an object - The event is also raised when a request is - made, the viewer equivalent is hovering the mouse cursor over an object - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Get the simulator the object is located + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Provides primitive data containing updated location, velocity, rotation, textures for the event - The event occurs when the simulator sends updated location, velocity, rotation, etc - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Get the simulator the object is located + + + Avatar group management + - - Get the primitive details + + Key of Group Member - - + + Total land contribution - - + + Online status information - + + Abilities that the Group Member has + + + Current group title + + + Is a group owner + + - + Role manager for a group - - Get the simulator the object is located + + Key of the group - - Get the primitive details + + Key of Role - - + + Name of Role - - + + Group Title associated with Role - - + + Description of Role - - + + Abilities Associated with Role - - Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the - event + + Returns the role's title + The role's title - - Get the simulator the object is located + + + Class to represent Group Title + - - The LocalID of the object + + Key of the group - + + ID of the role title belongs to + + + Group Title + + + Whether title is Active + + + Returns group title + + - Provides updates sit position data + Represents a group on the grid - - Get the simulator the object is located + + Key of Group - - + + Key of Group Insignia - - + + Key of Group Founder - - + + Key of Group Role for Owners - + + Name of Group + + + Text of Group Charter + + + Title of "everyone" role + + + Is the group open for enrolement to everyone + + + Will group show up in search + + - - - Get the simulator the object is located + + + - - + + + - - + + Is the group Mature - - + + Cost of group membership - + - Indicates if the operation was successful - + - Media version string - + + The total number of current members this group has + + + The number of roles this group has configured + + + Show this group in agent's profile + + + Returns the name of the group + A string containing the name of the group + + - Array of media entries indexed by face number + A group Vote - + + Key of Avatar who created Vote + + + Text of the Vote proposal + + + Total number of votes + + - Singleton logging class for the entire library + A group proposal - - log4net logging engine + + The Text of the proposal + + + The minimum number of members that must vote before proposal passes or failes + + + The required ration of yes/no votes required for vote to pass + The three options are Simple Majority, 2/3 Majority, and Unanimous + TODO: this should be an enum + + The duration in days votes are accepted - + - Default constructor - + - Send a log message to the logging engine - The log message - The severity of the log entry - + - Send a log message to the logging engine - The log message - The severity of the log entry - Instance of the client - + - Send a log message to the logging engine - The log message - The severity of the log entry - Exception that was raised - + - Send a log message to the logging engine - The log message - The severity of the log entry - Instance of the client - Exception that was raised - + - If the library is compiled with DEBUG defined, an event will be - fired if an OnLogMessage handler is registered and the - message will be sent to the logging engine - The message to log at the DEBUG level to the - current logging engine - + - If the library is compiled with DEBUG defined and - GridClient.Settings.DEBUG is true, an event will be - fired if an OnLogMessage handler is registered and the - message will be sent to the logging engine - The message to log at the DEBUG level to the - current logging engine - Instance of the client - - Triggered whenever a message is logged. If this is left - null, log messages will go to the console - - + - Callback used for client apps to receive log messages from - the library - Data being logged - The severity of the log entry from - + - - + - - - + - De-serialization constructor for the InventoryNode Class - + - Serialization handler for the InventoryNode Class - + - De-serialization handler for the InventoryNode Class - + - - - - - - - - - - - - - - - + - For inventory folder nodes specifies weather the folder needs to be - refreshed from the server - + - Exception class to identify inventory exceptions - + - Responsible for maintaining inventory structure. Inventory constructs nodes - and manages node children as is necessary to maintain a coherant hirarchy. - Other classes should not manipulate or create InventoryNodes explicitly. When - A node's parent changes (when a folder is moved, for example) simply pass - Inventory the updated InventoryFolder and it will make the appropriate changes - to its internal representation. - - The event subscribers, null of no subscribers - - - Raises the InventoryObjectUpdated Event - A InventoryObjectUpdatedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - The event subscribers, null of no subscribers - - - Raises the InventoryObjectRemoved Event - A InventoryObjectRemovedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object + + + - - The event subscribers, null of no subscribers + + + - - Raises the InventoryObjectAdded Event - A InventoryObjectAddedEventArgs object containing - the data sent from the simulator + + + - - Thread sync lock object + + + Struct representing a group notice + - + - Returns the contents of the specified folder - A folder's UUID - The contents of the folder corresponding to folder - When folder does not exist in the inventory - + - Updates the state of the InventoryNode and inventory data structure that - is responsible for the InventoryObject. If the item was previously not added to inventory, - it adds the item, and updates structure accordingly. If it was, it updates the - InventoryNode, changing the parent node if item.parentUUID does - not match node.Parent.Data.UUID. - - You can not set the inventory root folder using this method - The InventoryObject to store - + - Removes the InventoryObject and all related node data from Inventory. - The InventoryObject to remove. - + - Used to find out if Inventory contains the InventoryObject - specified by uuid. - The UUID to check. - true if inventory contains uuid, false otherwise - + - Saves the current inventory structure to a cache file - Name of the cache file to save to + + - + - Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful. + Struct representing a group notice list entry - Name of the cache file to load - The number of inventory items sucessfully reconstructed into the inventory node tree - - Raised when the simulator sends us data containing - ... + + Notice ID - - Raised when the simulator sends us data containing - ... + + Creation timestamp of notice - - Raised when the simulator sends us data containing - ... + + Agent name who created notice - + + Notice subject + + + Is there an attachment? + + + Attachment Type + + - The root folder of this avatars inventory + Struct representing a member of a group chat session and their settings - + + The of the Avatar + + + True if user has voice chat enabled + + + True of Avatar has moderator abilities + + + True if a moderator has muted this avatars chat + + + True if a moderator has muted this avatars voice + + - The default shared library folder + Role update flags - + - The root node of the avatars inventory - + - The root node of the default shared library - + - By using the bracket operator on this class, the program can get the - InventoryObject designated by the specified uuid. If the value for the corresponding - UUID is null, the call is equivelant to a call to RemoveNodeFor(this[uuid]). - If the value is non-null, it is equivelant to a call to UpdateNodeFor(value), - the uuid parameter is ignored. - The UUID of the InventoryObject to get or set, ignored if set to non-null value. - The InventoryObject corresponding to uuid. - - - Describes tasks returned in LandStatReply - + - Estate level administration and utilities - - Textures for each of the four terrain height levels + + + - - Upper/lower texture boundaries for each corner of the sim + + + - + - Constructor for EstateTools class - - - The event subscribers. null if no subcribers + + Can send invitations to groups default role - - Raises the TopCollidersReply event - A TopCollidersReplyEventArgs object containing the - data returned from the data server + + Can eject members from group - - Thread sync lock object + + Can toggle 'Open Enrollment' and change 'Signup fee' - - The event subscribers. null if no subcribers + + Member is visible in the public member list - - Raises the TopScriptsReply event - A TopScriptsReplyEventArgs object containing the - data returned from the data server + + Can create new roles - - Thread sync lock object + + Can delete existing roles - - The event subscribers. null if no subcribers + + Can change Role names, titles and descriptions - - Raises the EstateUsersReply event - A EstateUsersReplyEventArgs object containing the - data returned from the data server + + Can assign other members to assigners role - - Thread sync lock object + + Can assign other members to any role - - The event subscribers. null if no subcribers + + Can remove members from roles - - Raises the EstateGroupsReply event - A EstateGroupsReplyEventArgs object containing the - data returned from the data server + + Can assign and remove abilities in roles - - Thread sync lock object + + Can change group Charter, Insignia, 'Publish on the web' and which + members are publicly visible in group member listings - - The event subscribers. null if no subcribers + + Can buy land or deed land to group - - Raises the EstateManagersReply event - A EstateManagersReplyEventArgs object containing the - data returned from the data server + + Can abandon group owned land to Governor Linden on mainland, or Estate owner for + private estates - - Thread sync lock object + + Can set land for-sale information on group owned parcels - - The event subscribers. null if no subcribers + + Can subdivide and join parcels - - Raises the EstateBansReply event - A EstateBansReplyEventArgs object containing the - data returned from the data server + + Can join group chat sessions - - Thread sync lock object + + Can use voice chat in Group Chat sessions - - The event subscribers. null if no subcribers + + Can moderate group chat sessions - - Raises the EstateCovenantReply event - A EstateCovenantReplyEventArgs object containing the - data returned from the data server + + Can toggle "Show in Find Places" and set search category - - Thread sync lock object + + Can change parcel name, description, and 'Publish on web' settings - - The event subscribers. null if no subcribers + + Can set the landing point and teleport routing on group land - - Raises the EstateUpdateInfoReply event - A EstateUpdateInfoReplyEventArgs object containing the - data returned from the data server + + Can change music and media settings - - Thread sync lock object + + Can toggle 'Edit Terrain' option in Land settings - - - Requests estate information such as top scripts and colliders - - - - - + + Can toggle various About Land > Options settings - - Requests estate settings, including estate manager and access/ban lists + + Can always terraform land, even if parcel settings have it turned off - - Requests the "Top Scripts" list for the current region + + Can always fly while over group owned land - - Requests the "Top Colliders" list for the current region + + Can always rez objects on group owned land - - - Set several estate specific configuration variables - - The Height of the waterlevel over the entire estate. Defaults to 20 - The maximum height change allowed above the baked terrain. Defaults to 4 - The minimum height change allowed below the baked terrain. Defaults to -4 - true to use - if True forces the sun position to the position in SunPosition - The current position of the sun on the estate, or when FixedSun is true the static position - the sun will remain. 6.0 = Sunrise, 30.0 = Sunset + + Can always create landmarks for group owned parcels - - - Request return of objects owned by specified avatar - - The Agents owning the primitives to return - specify the coverage and type of objects to be included in the return - true to perform return on entire estate + + Can set home location on any group owned parcel - - - - + + Can modify public access settings for group owned parcels - - - Used for setting and retrieving various estate panel settings - - EstateOwnerMessage Method field - List of parameters to include + + Can manager parcel ban lists on group owned land - - - Kick an avatar from an estate - - Key of Agent to remove + + Can manage pass list sales information - - - Ban an avatar from an estate - Key of Agent to remove - Ban user from this estate and all others owned by the estate owner + + Can eject and freeze other avatars on group owned land - - Unban an avatar from an estate - Key of Agent to remove - /// Unban user from this estate and all others owned by the estate owner + + Can return objects set to group - - - Send a message dialog to everyone in an entire estate - - Message to send all users in the estate + + Can return non-group owned/set objects - - - Send a message dialog to everyone in a simulator - - Message to send all users in the simulator + + Can return group owned objects - - - Send an avatar back to their home location - - Key of avatar to send home + + Can landscape using Linden plants - - - Begin the region restart process - + + Can deed objects to group - - - Cancels a region restart - + + Can move group owned objects - - Estate panel "Region" tab settings + + Can set group owned objects for-sale - - Estate panel "Debug" tab settings + + Pay group liabilities and receive group dividends - - Used for setting the region's terrain textures for its four height levels - - - - + + Can send group notices - - Used for setting sim terrain texture heights + + Can receive group notices - - Requests the estate covenant + + Can create group proposals - + + Can vote on group proposals + + - Upload a terrain RAW file + Handles all network traffic related to reading and writing group + information - A byte array containing the encoded terrain data - The name of the file being uploaded - The Id of the transfer request - + - Teleports all users home in current Estate + Construct a new instance of the GroupManager class + A reference to the current instance - - - Remove estate manager - Key of Agent to Remove - removes manager to this estate and all others owned by the estate owner + + The event subscribers. null if no subcribers - - - Add estate manager - Key of Agent to Add - Add agent as manager to this estate and all others owned by the estate owner + + Thread sync lock object - - - Add's an agent to the estate Allowed list - Key of Agent to Add - Add agent as an allowed reisdent to All estates if true + + The event subscribers. null if no subcribers - - - Removes an agent from the estate Allowed list - Key of Agent to Remove - Removes agent as an allowed reisdent from All estates if true + + Thread sync lock object - - - - Add's a group to the estate Allowed list - Key of Group to Add - Add Group as an allowed group to All estates if true + + The event subscribers. null if no subcribers - - - - Removes a group from the estate Allowed list - Key of Group to Remove - Removes Group as an allowed Group from All estates if true + + Thread sync lock object - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The event subscribers. null if no subcribers - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Thread sync lock object - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The event subscribers. null if no subcribers - - Raised when the data server responds to a request. + + Thread sync lock object - - Raised when the data server responds to a request. + + The event subscribers. null if no subcribers - - Raised when the data server responds to a request. + + Thread sync lock object - - Raised when the data server responds to a request. + + The event subscribers. null if no subcribers - - Raised when the data server responds to a request. + + Thread sync lock object - - Raised when the data server responds to a request. + + The event subscribers. null if no subcribers - - Raised when the data server responds to a request. + + Thread sync lock object - - Raised when the data server responds to a request. + + The event subscribers. null if no subcribers - - Used in the ReportType field of a LandStatRequest + + Thread sync lock object - - Used by EstateOwnerMessage packets + + The event subscribers. null if no subcribers - - Used by EstateOwnerMessage packets + + Thread sync lock object - - - - + + The event subscribers. null if no subcribers - - No flags set + + Thread sync lock object - - Only return targets scripted objects + + The event subscribers. null if no subcribers - - Only return targets objects if on others land + + Thread sync lock object - - Returns target's scripted objects and objects on other parcels + + The event subscribers. null if no subcribers - - Ground texture settings for each corner of the region + + Thread sync lock object - - Used by GroundTextureHeightSettings + + The event subscribers. null if no subcribers - - The high and low texture thresholds for each corner of the sim + + Thread sync lock object - - Raised on LandStatReply when the report type is for "top colliders" + + The event subscribers. null if no subcribers - - Construct a new instance of the TopCollidersReplyEventArgs class - The number of returned items in LandStatReply - Dictionary of Object UUIDs to tasks returned in LandStatReply + + Thread sync lock object - - - The number of returned items in LandStatReply - + + A reference to the current instance - - - A Dictionary of Object UUIDs to tasks returned in LandStatReply - + + Currently-active group members requests - - Raised on LandStatReply when the report type is for "top Scripts" + + Currently-active group roles requests - - Construct a new instance of the TopScriptsReplyEventArgs class - The number of returned items in LandStatReply - Dictionary of Object UUIDs to tasks returned in LandStatReply + + Currently-active group role-member requests - - - The number of scripts returned in LandStatReply - + + Dictionary keeping group members while request is in progress - - - A Dictionary of Object UUIDs to tasks returned in LandStatReply - + + Dictionary keeping mebmer/role mapping while request is in progress - - Returned, along with other info, upon a successful .RequestInfo() + + Dictionary keeping GroupRole information while request is in progress - - Construct a new instance of the EstateBansReplyEventArgs class - The estate's identifier on the grid - The number of returned items in LandStatReply - User UUIDs banned + + Caches group name lookups - - - The identifier of the estate - + + Raised when the simulator sends us data containing + our current group membership - - - The number of returned itmes - + + Raised when the simulator responds to a RequestGroupName + or RequestGroupNames request - - - List of UUIDs of Banned Users - + + Raised when the simulator responds to a request - - Returned, along with other info, upon a successful .RequestInfo() + + Raised when the simulator responds to a request - - Construct a new instance of the EstateUsersReplyEventArgs class - The estate's identifier on the grid - The number of users - Allowed users UUIDs + + Raised when the simulator responds to a request - - - The identifier of the estate - + + Raised when the simulator responds to a request - - - The number of returned items - + + Raised when the simulator responds to a request - - - List of UUIDs of Allowed Users - + + Raised when a response to a RequestGroupAccountSummary is returned + by the simulator - - Returned, along with other info, upon a successful .RequestInfo() + + Raised when a request to create a group is successful - - Construct a new instance of the EstateGroupsReplyEventArgs class - The estate's identifier on the grid - The number of Groups - Allowed Groups UUIDs + + Raised when a request to join a group either + fails or succeeds - - - The identifier of the estate - + + Raised when a request to leave a group either + fails or succeeds - - - The number of returned items - + + Raised when A group is removed from the group server - - - List of UUIDs of Allowed Groups - + + Raised when a request to eject a member from a group either + fails or succeeds - - Returned, along with other info, upon a successful .RequestInfo() + + Raised when the simulator sends us group notices + - - Construct a new instance of the EstateManagersReplyEventArgs class - The estate's identifier on the grid - The number of Managers - Managers UUIDs + + Raised when another agent invites our avatar to join a group - - - The identifier of the estate - + + Raises the CurrentGroups event + A CurrentGroupsEventArgs object containing the + data sent from the simulator - - - The number of returned items - + + Raises the GroupNamesReply event + A GroupNamesEventArgs object containing the + data response from the simulator - - - List of UUIDs of the Estate's Managers - + + Raises the GroupProfile event + An GroupProfileEventArgs object containing the + data returned from the simulator - - Returned, along with other info, upon a successful .RequestInfo() + + Raises the GroupMembers event + A GroupMembersEventArgs object containing the + data returned from the simulator - - Construct a new instance of the EstateCovenantReplyEventArgs class - The Covenant ID - The timestamp - The estate's name - The Estate Owner's ID (can be a GroupID) + + Raises the GroupRolesDataReply event + A GroupRolesDataReplyEventArgs object containing the + data returned from the simulator - - - The Covenant - + + Raises the GroupRoleMembersReply event + A GroupRolesRoleMembersReplyEventArgs object containing the + data returned from the simulator - - - The timestamp - + + Raises the GroupTitlesReply event + A GroupTitlesReplyEventArgs object containing the + data returned from the simulator - - - The Estate name - + + Raises the GroupAccountSummary event + A GroupAccountSummaryReplyEventArgs object containing the + data returned from the simulator - - - The Estate Owner's ID (can be a GroupID) - + + Raises the GroupCreated event + An GroupCreatedEventArgs object containing the + data returned from the simulator - - Returned, along with other info, upon a successful .RequestInfo() + + Raises the GroupJoined event + A GroupOperationEventArgs object containing the + result of the operation returned from the simulator - - Construct a new instance of the EstateUpdateInfoReplyEventArgs class - The estate's name - The Estate Owners ID (can be a GroupID) - The estate's identifier on the grid - + + Raises the GroupLeft event + A GroupOperationEventArgs object containing the + result of the operation returned from the simulator - - - The estate's name - + + Raises the GroupDropped event + An GroupDroppedEventArgs object containing the + the group your agent left - - - The Estate Owner's ID (can be a GroupID) - + + Raises the GroupMemberEjected event + An GroupMemberEjectedEventArgs object containing the + data returned from the simulator - - - The identifier of the estate on the grid - + + Raises the GroupNoticesListReply event + An GroupNoticesListReplyEventArgs object containing the + data returned from the simulator - - + + Raises the GroupInvitation event + An GroupInvitationEventArgs object containing the + data returned from the simulator - + - Image width + Request a current list of groups the avatar is a member of. + CAPS Event Queue must be running for this to work since the results + come across CAPS. - + - Image height + Lookup name of group based on groupID + groupID of group to lookup name for. - + - Image channel flags + Request lookup of multiple group names + List of group IDs to request. - - - Red channel data - + + Lookup group profile data such as name, enrollment, founder, logo, etc + Subscribe to OnGroupProfile event to receive the results. + group ID (UUID) - - - Green channel data - + + Request a list of group members. + Subscribe to OnGroupMembers event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache - - - Blue channel data - + + Request group roles + Subscribe to OnGroupRoles event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache - - - Alpha channel data - + + Request members (members,role) role mapping for a group. + Subscribe to OnGroupRolesMembers event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache - - - Bump channel data - + + Request a groups Titles + Subscribe to OnGroupTitles event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache - - - Create a new blank image - - width - height - channel flags + + Begin to get the group account summary + Subscribe to the OnGroupAccountSummary event to receive the results. + group ID (UUID) + How long of an interval + Which interval (0 for current, 1 for last) - - - - - + + Invites a user to a group + The group to invite to + A list of roles to invite a person to + Key of person to invite - - - Convert the channels in the image. Channels are created or destroyed as required. - - new channel flags + + Set a group as the current active group + group ID (UUID) - - - Resize or stretch the image using nearest neighbor (ugly) resampling - - new width - new height + + Change the role that determines your active title + Group ID to use + Role ID to change to - - - Create a byte array containing 32-bit RGBA data with a bottom-left - origin, suitable for feeding directly into OpenGL - - A byte array containing raw texture data + + Set this avatar's tier contribution + Group ID to change tier in + amount of tier to donate - + - Represents an AssetScriptBinary object containing the - LSO compiled bytecode of an LSL script + Save wheather agent wants to accept group notices and list this group in their profile + Group + Accept notices from this group + List this group in the profile - - Initializes a new instance of an AssetScriptBinary object - - - Initializes a new instance of an AssetScriptBinary object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - - TODO: Encodes a scripts contents into a LSO Bytecode file - + + Request to join a group + Subscribe to OnGroupJoined event for confirmation. + group ID (UUID) to join. - + - TODO: Decode LSO Bytecode into a string + Request to create a new group. If the group is successfully + created, L$100 will automatically be deducted - true + Subscribe to OnGroupCreated event to receive confirmation. + Group struct containing the new group info - - Override the base classes AssetType + + Update a group's profile and other information + Groups ID (UUID) to update. + Group struct to update. - - - - + + Eject a user from a group + Group ID to eject the user from + Avatar's key to eject - - - An instance of DelegateWrapper which calls InvokeWrappedDelegate, - which in turn calls the DynamicInvoke method of the wrapped - delegate - + + Update role information + Modified role to be updated - - - Callback used to call EndInvoke on the asynchronously - invoked DelegateWrapper - + + Create a new group role + Group ID to update + Role to create - - - Executes the specified delegate with the specified arguments - asynchronously on a thread pool thread - - - + + Delete a group role + Group ID to update + Role to delete - - - Invokes the wrapped delegate synchronously - - - + + Remove an avatar from a role + Group ID to update + Role ID to be removed from + Avatar's Key to remove - - - Calls EndInvoke on the wrapper and Close on the resulting WaitHandle - to prevent resource leaks - - + + Assign an avatar to a role + Group ID to update + Role ID to assign to + Avatar's ID to assign to role - - - Delegate to wrap another delegate and its arguments - - - + + Request the group notices list + Group ID to fetch notices for - - - Checks the instance back into the object pool - + + Request a group notice by key + ID of group notice - - - Returns an instance of the class that has been checked out of the Object Pool. - + + Send out a group notice + Group ID to update + + GroupNotice structure containing notice data - - - Creates a new instance of the ObjectPoolBase class. Initialize MUST be called - after using this constructor. - + + Start a group proposal (vote) + The Group ID to send proposal to + + GroupProposal structure containing the proposal - - - Creates a new instance of the ObjectPool Base class. - - The object pool is composed of segments, which - are allocated whenever the size of the pool is exceeded. The number of items - in a segment should be large enough that allocating a new segmeng is a rare - thing. For example, on a server that will have 10k people logged in at once, - the receive buffer object pool should have segment sizes of at least 1000 - byte arrays per segment. - - The minimun number of segments that may exist. - Perform a full GC.Collect whenever a segment is allocated, and then again after allocation to compact the heap. - The frequency which segments are checked to see if they're eligible for cleanup. + + Request to leave a group + Subscribe to OnGroupLeft event to receive confirmation + The group to leave - - - Forces the segment cleanup algorithm to be run. This method is intended - primarly for use from the Unit Test libraries. - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Responsible for allocate 1 instance of an object that will be stored in a segment. - - An instance of whatever objec the pool is pooling. + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Checks in an instance of T owned by the object pool. This method is only intended to be called - by the WrappedObject class. - - The segment from which the instance is checked out. - The instance of T to check back into the segment. + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Checks an instance of T from the pool. If the pool is not sufficient to - allow the checkout, a new segment is created. - - A WrappedObject around the instance of T. To check - the instance back into the segment, be sureto dispose the WrappedObject - when finished. + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - The total number of segments created. Intended to be used by the Unit Tests. - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - The number of items that are in a segment. Items in a segment - are all allocated at the same time, and are hopefully close to - each other in the managed heap. - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - The minimum number of segments. When segments are reclaimed, - this number of segments will always be left alone. These - segments are allocated at startup. - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - The age a segment must be before it's eligible for cleanup. - This is used to prevent thrash, and typical values are in - the 5 minute range. - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - The frequence which the cleanup thread runs. This is typically - expected to be in the 5 minute range. - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Size of the byte array used to store raw packet data + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Raw packet data buffer + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Length of the data to transmit + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - EndPoint of the remote host + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Create an allocated UDP packet buffer for receiving a packet - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Create an allocated UDP packet buffer for sending a packet - - EndPoint of the remote host + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Create an allocated UDP packet buffer for sending a packet - - EndPoint of the remote host - Size of the buffer to allocate for packet data + + Contains the current groups your agent is a member of - - - Object pool for packet buffers. This is used to allocate memory for all - incoming and outgoing packets, and zerocoding buffers for those packets - + + Construct a new instance of the CurrentGroupsEventArgs class + The current groups your agent is a member of - - - Initialize the object pool in client mode - - Server to connect to - - + + Get the current groups your agent is a member of - - - Initialize the object pool in server mode - - - + + A Dictionary of group names, where the Key is the groups ID and the value is the groups name - - - Returns a packet buffer with EndPoint set if the buffer is in - client mode, or with EndPoint set to null in server mode - - Initialized UDPPacketBuffer object + + Construct a new instance of the GroupNamesEventArgs class + The Group names dictionary - - - Default constructor - + + Get the Group Names dictionary - - - Check a packet buffer out of the pool - - A packet buffer object + + Represents the members of a group - + - Static pre-defined animations available to all agents + Construct a new instance of the GroupMembersReplyEventArgs class + The ID of the request + The ID of the group + The membership list of the group - - Agent with afraid expression on face - - - Agent aiming a bazooka (right handed) + + Get the ID as returned by the request to correlate + this result set and the request - - Agent aiming a bow (left handed) + + Get the ID of the group - - Agent aiming a hand gun (right handed) + + Get the dictionary of members - - Agent aiming a rifle (right handed) + + Represents the roles associated with a group - - Agent with angry expression on face + + Construct a new instance of the GroupRolesDataReplyEventArgs class + The ID as returned by the request to correlate + this result set and the request + The ID of the group + The dictionary containing the roles - - Agent hunched over (away) + + Get the ID as returned by the request to correlate + this result set and the request - - Agent doing a backflip + + Get the ID of the group - - Agent laughing while holding belly + + Get the dictionary containing the roles - - Agent blowing a kiss + + Represents the Role to Member mappings for a group - - Agent with bored expression on face - - - Agent bowing to audience + + Construct a new instance of the GroupRolesMembersReplyEventArgs class + The ID as returned by the request to correlate + this result set and the request + The ID of the group + The member to roles map - - Agent brushing himself/herself off + + Get the ID as returned by the request to correlate + this result set and the request - - Agent in busy mode + + Get the ID of the group - - Agent clapping hands + + Get the member to roles map - - Agent doing a curtsey bow + + Represents the titles for a group - - Agent crouching + + Construct a new instance of the GroupTitlesReplyEventArgs class + The ID as returned by the request to correlate + this result set and the request + The ID of the group + The titles - - Agent crouching while walking + + Get the ID as returned by the request to correlate + this result set and the request - - Agent crying + + Get the ID of the group - - Agent unanimated with arms out (e.g. setting appearance) + + Get the titles - - Agent re-animated after set appearance finished + + Represents the summary data for a group - - Agent dancing + + Construct a new instance of the GroupAccountSummaryReplyEventArgs class + The ID of the group + The summary data - - Agent dancing + + Get the ID of the group - - Agent dancing + + Get the summary data - - Agent dancing + + A response to a group create request - - Agent dancing + + Construct a new instance of the GroupCreatedReplyEventArgs class + The ID of the group + the success or faulure of the request + A string containing additional information - - Agent dancing + + Get the ID of the group - - Agent dancing + + true of the group was created successfully - - Agent dancing + + A string containing the message - - Agent on ground unanimated + + Represents a response to a request - - Agent boozing it up + + Construct a new instance of the GroupOperationEventArgs class + The ID of the group + true of the request was successful - - Agent with embarassed expression on face + + Get the ID of the group - - Agent with afraid expression on face + + true of the request was successful - - Agent with angry expression on face + + Represents your agent leaving a group - - Agent with bored expression on face + + Construct a new instance of the GroupDroppedEventArgs class + The ID of the group - - Agent crying + + Get the ID of the group - - Agent showing disdain (dislike) for something + + Represents a list of active group notices - - Agent with embarassed expression on face + + Construct a new instance of the GroupNoticesListReplyEventArgs class + The ID of the group + The list containing active notices - - Agent with frowning expression on face + + Get the ID of the group - - Agent with kissy face + + Get the notices list - - Agent expressing laughgter + + Represents the profile of a group - - Agent with open mouth + + Construct a new instance of the GroupProfileEventArgs class + The group profile - - Agent with repulsed expression on face + + Get the group profile - - Agent expressing sadness + + + Provides notification of a group invitation request sent by another Avatar + + The invitation is raised when another avatar makes an offer for our avatar + to join a group. - - Agent shrugging shoulders + + The ID of the Avatar sending the group invitation - - Agent with a smile + + The name of the Avatar sending the group invitation - - Agent expressing surprise + + A message containing the request information which includes + the name of the group, the groups charter and the fee to join details - - Agent sticking tongue out + + The Simulator - - Agent with big toothy smile + + Set to true to accept invitation, false to decline - - Agent winking + + + Static helper functions and global variables + - - Agent expressing worry + + + Passed to Logger.Log() to identify the severity of a log entry + - - Agent falling down + + No logging information will be output - - Agent walking (feminine version) + + Non-noisy useful information, may be helpful in + debugging a problem - - Agent wagging finger (disapproval) + + A non-critical error occurred. A warning will not + prevent the rest of the library from operating as usual, + although it may be indicative of an underlying issue - - I'm not sure I want to know + + A critical error has occurred. Generally this will + be followed by the network layer shutting down, although the + stability of the library after an error is uncertain - - Agent in superman position + + Used for internal testing, this logging level can + generate very noisy (long and/or repetitive) messages. Don't + pass this to the Log() function, use DebugLog() instead. + - - Agent in superman position + + This header flag signals that ACKs are appended to the packet - - Agent greeting another + + This header flag signals that this packet has been sent before - - Agent holding bazooka (right handed) + + This header flags signals that an ACK is expected for this packet - - Agent holding a bow (left handed) + + This header flag signals that the message is compressed using zerocoding - - Agent holding a handgun (right handed) + + + + + + + - - Agent holding a rifle (right handed) + + + + + + + + + - - Agent throwing an object (right handed) + + + + + + + - - Agent in static hover + + + + + + + + + - - Agent hovering downward + + + Given an X/Y location in absolute (grid-relative) terms, a region + handle is returned along with the local X/Y location in that region + + The absolute X location, a number such as + 255360.35 + The absolute Y location, a number such as + 255360.35 + The sim-local X position of the global X + position, a value from 0.0 to 256.0 + The sim-local Y position of the global Y + position, a value from 0.0 to 256.0 + A 64-bit region handle that can be used to teleport to - - Agent hovering upward + + + Converts a floating point number to a terse string format used for + transmitting numbers in wearable asset files + + Floating point number to convert to a string + A terse string representation of the input number - - Agent being impatient + + + Convert a variable length field (byte array) to a string, with a + field name prepended to each line of the output + + If the byte array has unprintable characters in it, a + hex dump will be written instead + The StringBuilder object to write to + The byte array to convert to a string + A field name to prepend to each line of output - - Agent jumping + + + Decode a zerocoded byte array, used to decompress packets marked + with the zerocoded flag + + Any time a zero is encountered, the next byte is a count + of how many zeroes to expand. One zero is encoded with 0x00 0x01, + two zeroes is 0x00 0x02, three zeroes is 0x00 0x03, etc. The + first four bytes are copied directly to the output buffer. + + The byte array to decode + The length of the byte array to decode. This + would be the length of the packet up to (but not including) any + appended ACKs + The output byte array to decode to + The length of the output buffer - - Agent jumping with fervor + + + Encode a byte array with zerocoding. Used to compress packets marked + with the zerocoded flag. Any zeroes in the array are compressed down + to a single zero byte followed by a count of how many zeroes to expand + out. A single zero becomes 0x00 0x01, two zeroes becomes 0x00 0x02, + three zeroes becomes 0x00 0x03, etc. The first four bytes are copied + directly to the output buffer. + + The byte array to encode + The length of the byte array to encode + The output byte array to encode to + The length of the output buffer - - Agent point to lips then rear end + + + Calculates the CRC (cyclic redundancy check) needed to upload inventory. + + Creation date + Sale type + Inventory type + Type + Asset ID + Group ID + Sale price + Owner ID + Creator ID + Item ID + Folder ID + Everyone mask (permissions) + Flags + Next owner mask (permissions) + Group mask (permissions) + Owner mask (permissions) + The calculated CRC - - Agent landing from jump, finished flight, etc + + + Attempts to load a file embedded in the assembly + + The filename of the resource to load + A Stream for the requested file, or null if the resource + was not successfully loaded - - Agent laughing + + + Attempts to load a file either embedded in the assembly or found in + a given search path + + The filename of the resource to load + An optional path that will be searched if + the asset is not found embedded in the assembly + A Stream for the requested file, or null if the resource + was not successfully loaded - - Agent landing from jump, finished flight, etc + + + Converts a list of primitives to an object that can be serialized + with the LLSD system + + Primitives to convert to a serializable object + An object that can be serialized with LLSD - - Agent sitting on a motorcycle + + + Deserializes OSD in to a list of primitives + + Structure holding the serialized primitive list, + must be of the SDMap type + A list of deserialized primitives - - + + + Converts a struct or class object containing fields only into a key value separated string + + The struct object + A string containing the struct fields as the keys, and the field value as the value separated + + + // Add the following code to any struct or class containing only fields to override the ToString() + // method to display the values of the passed object + /// Print the struct data as a string + ///A string containing the field name, and field value + public override string ToString() + { + return Helpers.StructToString(this); + } + + - - Agent moving head side to side + + + The InternalDictionary class is used through the library for storing key/value pairs. + It is intended to be a replacement for the generic Dictionary class and should + be used in its place. It contains several methods for allowing access to the data from + outside the library that are read only and thread safe. + + Key + Value + + + + Initializes a new instance of the Class + with the specified key/value, has the default initial capacity. + + + + // initialize a new InternalDictionary named testDict with a string as the key and an int as the value. + public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(); + + + + + + Initializes a new instance of the Class + with the specified key/value, has its initial valies copied from the specified + + + + to copy initial values from + + + // initialize a new InternalDictionary named testAvName with a UUID as the key and an string as the value. + // populates with copied values from example KeyNameCache Dictionary. + // create source dictionary + Dictionary<UUID, string> KeyNameCache = new Dictionary<UUID, string>(); + KeyNameCache.Add("8300f94a-7970-7810-cf2c-fc9aa6cdda24", "Jack Avatar"); + KeyNameCache.Add("27ba1e40-13f7-0708-3e98-5819d780bd62", "Jill Avatar"); + // Initialize new dictionary. + public InternalDictionary<UUID, string> testAvName = new InternalDictionary<UUID, string>(KeyNameCache); + + + + + + Initializes a new instance of the Class + with the specified key/value, With its initial capacity specified. + + Initial size of dictionary + + + // initialize a new InternalDictionary named testDict with a string as the key and an int as the value, + // initially allocated room for 10 entries. + public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(10); + + + + + Internal dictionary that this class wraps around. Do not + modify or enumerate the contents of this dictionary without locking + on this member + + + + Indexer for the dictionary + + The key + The value + + + + Gets the number of Key/Value pairs contained in the + + + + Try to get entry from with specified key + + Key to use for lookup + Value returned + + if specified key exists, if not found + + + // find your avatar using the Simulator.ObjectsAvatars InternalDictionary: + Avatar av; + if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) + Console.WriteLine("Found Avatar {0}", av.Name); + + + + + + + Finds the specified match. + + The match. + Matched value + + + // use a delegate to find a prim in the ObjectsPrimitives InternalDictionary + // with the ID 95683496 + uint findID = 95683496; + Primitive findPrim = sim.ObjectsPrimitives.Find( + delegate(Primitive prim) { return prim.ID == findID; }); + + + + + Find All items in an + return matching items. + a containing found items. + + Find All prims within 20 meters and store them in a List + + int radius = 20; + List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( + delegate(Primitive prim) { + Vector3 pos = prim.Position; + return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); + } + ); + + + + Find All items in an + return matching keys. + a containing found keys. + + Find All keys which also exist in another dictionary + + List<UUID> matches = myDict.FindAll( + delegate(UUID id) { + return myOtherDict.ContainsKey(id); + } + ); + + + + Perform an on each entry in an + + to perform + + + // Iterates over the ObjectsPrimitives InternalDictionary and prints out some information. + Client.Network.CurrentSim.ObjectsPrimitives.ForEach( + delegate(Primitive prim) + { + if (prim.Text != null) + { + Console.WriteLine("NAME={0} ID = {1} TEXT = '{2}'", + prim.PropertiesFamily.Name, prim.ID, prim.Text); + } + }); + + + + + Perform an on each key of an + + to perform + + + + Perform an on each KeyValuePair of an + + to perform + + + Check if Key exists in Dictionary + Key to check for + + if found, otherwise + + + Check if Value exists in Dictionary + Value to check for + + if found, otherwise + + + + Adds the specified key to the dictionary, dictionary locking is not performed, + + The key + The value + + + + Removes the specified key, dictionary locking is not performed + + The key. + + if successful, otherwise + + + + Exception class to identify inventory exceptions + + + + + Responsible for maintaining inventory structure. Inventory constructs nodes + and manages node children as is necessary to maintain a coherant hirarchy. + Other classes should not manipulate or create InventoryNodes explicitly. When + A node's parent changes (when a folder is moved, for example) simply pass + Inventory the updated InventoryFolder and it will make the appropriate changes + to its internal representation. + + + + The event subscribers, null of no subscribers + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Thread sync lock object + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + Raised when the simulator sends us data containing + ... + + + + By using the bracket operator on this class, the program can get the + InventoryObject designated by the specified uuid. If the value for the corresponding + UUID is null, the call is equivelant to a call to RemoveNodeFor(this[uuid]). + If the value is non-null, it is equivelant to a call to UpdateNodeFor(value), + the uuid parameter is ignored. + + The UUID of the InventoryObject to get or set, ignored if set to non-null value. + The InventoryObject corresponding to uuid. + + + + The root folder of this avatars inventory + + + + + The default shared library folder + + + + + The root node of the avatars inventory + + + + + The root node of the default shared library + + + + Raises the InventoryObjectUpdated Event + A InventoryObjectUpdatedEventArgs object containing + the data sent from the simulator + + + Raises the InventoryObjectRemoved Event + A InventoryObjectRemovedEventArgs object containing + the data sent from the simulator + + + Raises the InventoryObjectAdded Event + A InventoryObjectAddedEventArgs object containing + the data sent from the simulator + + + + Returns the contents of the specified folder + + A folder's UUID + The contents of the folder corresponding to folder + When folder does not exist in the inventory - - Agent moving head side to side with unhappy expression + + + Updates the state of the InventoryNode and inventory data structure that + is responsible for the InventoryObject. If the item was previously not added to inventory, + it adds the item, and updates structure accordingly. If it was, it updates the + InventoryNode, changing the parent node if item.parentUUID does + not match node.Parent.Data.UUID. + You can not set the inventory root folder using this method + + The InventoryObject to store - - Agent taunting another + + + Removes the InventoryObject and all related node data from Inventory. + + The InventoryObject to remove. - - + + + Used to find out if Inventory contains the InventoryObject + specified by uuid. + + The UUID to check. + true if inventory contains uuid, false otherwise - - Agent giving peace sign + + + Saves the current inventory structure to a cache file + + Name of the cache file to save to - - Agent pointing at self + + + Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful. + + Name of the cache file to load + The number of inventory items sucessfully reconstructed into the inventory node tree - - Agent pointing at another + + Sort by name - - Agent preparing for jump (bending knees) + + Sort by date - - Agent punching with left hand + + Sort folders by name, regardless of whether items are + sorted by name or date - - Agent punching with right hand + + Place system folders at the top - - Agent acting repulsed + + + Possible destinations for DeRezObject request + - - Agent trying to be Chuck Norris + + + - - Rocks, Paper, Scissors 1, 2, 3 + + Copy from in-world to agent inventory - - Agent with hand flat over other hand + + Derez to TaskInventory - - Agent with fist over other hand + + + - - Agent with two fingers spread over other hand + + Take Object - - Agent running + + + - - Agent appearing sad + + Delete Object - - Agent saluting + + Put an avatar attachment into agent inventory - - Agent shooting bow (left handed) + + + - - Agent cupping mouth as if shouting + + Return an object back to the owner's inventory - - Agent shrugging shoulders + + Return a deeded object back to the last owner's inventory - - Agent in sit position + + + Upper half of the Flags field for inventory items + - - Agent in sit position (feminine) + + Indicates that the NextOwner permission will be set to the + most restrictive set of permissions found in the object set + (including linkset items and object inventory items) on next rez - - Agent in sit position (generic) + + Indicates that the object sale information has been + changed - - Agent sitting on ground + + If set, and a slam bit is set, indicates BaseMask will be overwritten on Rez - - Agent sitting on ground + + If set, and a slam bit is set, indicates OwnerMask will be overwritten on Rez - - + + If set, and a slam bit is set, indicates GroupMask will be overwritten on Rez - - Agent sleeping on side + + If set, and a slam bit is set, indicates EveryoneMask will be overwritten on Rez - - Agent smoking + + If set, and a slam bit is set, indicates NextOwnerMask will be overwritten on Rez - - Agent inhaling smoke + + Indicates whether this object is composed of multiple + items or not - - + + Indicates that the asset is only referenced by this + inventory item. If this item is deleted or updated to reference a + new assetID, the asset can be deleted - - Agent taking a picture + + + Base Class for Inventory Items + - - Agent standing + + + Constructor, takes an itemID as a parameter + + The of the item - - Agent standing up + + + + + - - Agent standing + + + of item/folder - - Agent standing + + + of parent folder - - Agent standing + + Name of item/folder - - Agent standing + + Item/Folder Owners - - Agent stretching + + + + + - - Agent in stride (fast walk) + + + Generates a number corresponding to the value of the object to support the use of a hash table, + suitable for use in hashing algorithms and data structures such as a hash table + + A Hashcode of all the combined InventoryBase fields - - Agent surfing + + + Determine whether the specified object is equal to the current object + + InventoryBase object to compare against + true if objects are the same - - Agent acting surprised + + + Determine whether the specified object is equal to the current object + + InventoryBase object to compare against + true if objects are the same - - Agent striking with a sword + + + An Item in Inventory + - - Agent talking (lips moving) + + + Construct a new InventoryItem object + + The of the item - - Agent throwing a tantrum + + + Construct a new InventoryItem object of a specific Type + + The type of item from + + of the item - - Agent throwing an object (right handed) + + + + + - - Agent trying on a shirt + + The of this item - - Agent turning to the left + + The combined of this item - - Agent turning to the right + + The type of item from - - Agent typing + + The type of item from the enum - - Agent walking + + The of the creator of this item + + + A Description of this item - - Agent whispering + + The s this item is set to or owned by - - Agent whispering with fingers in mouth + + If true, item is owned by a group - - Agent winking + + The price this item can be purchased for - - Agent winking + + The type of sale from the enum - - Agent worried + + Combined flags from - - Agent nodding yes + + Time and date this inventory item was created, stored as + UTC (Coordinated Universal Time) - - Agent nodding yes with happy face + + Used to update the AssetID in requests sent to the server - - Agent floating with legs and arms crossed + + The of the previous owner of the item - + - A dictionary containing all pre-defined animations + Indicates inventory item is a link - A dictionary containing the pre-defined animations, - where the key is the animations ID, and the value is a string - containing a name to identify the purpose of the animation + True if inventory item is a link to another inventory item - + - Represents an that represents an avatars body ie: Hair, Etc. + + - - Initializes a new instance of an AssetBodyPart object - - - Initializes a new instance of an AssetBodyPart object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - Initializes a new instance of an AssetBodyPart object with parameters - A string representing the values of the Bodypart - - - Override the base classes AssetType - - + - Archives assets + Generates a number corresponding to the value of the object to support the use of a hash table. + Suitable for use in hashing algorithms and data structures such as a hash table + A Hashcode of all the combined InventoryItem fields - + - Archive assets + Compares an object + The object to compare + true if comparison object matches - + - Archive the assets given to this archiver to the given archive. + Determine whether the specified object is equal to the current object - + The object to compare against + true if objects are the same - + - Write an assets metadata file to the given archive + Determine whether the specified object is equal to the current object - + The object to compare against + true if objects are the same - + - Write asset data files to the given archive + InventoryTexture Class representing a graphical image - + - + - + Construct an InventoryTexture object + A which becomes the + objects AssetUUID - - OK - - - Transfer completed - - - - - - - - - Unknown error occurred - - - Equivalent to a 404 error - - - Client does not have permission for that resource - - - Unknown status - - + - + Construct an InventoryTexture object from a serialization stream - - - - - Unknown - - - Virtually all asset transfers use this channel + + + InventorySound Class representing a playable sound + - + - + Construct an InventorySound object + A which becomes the + objects AssetUUID - - + + + Construct an InventorySound object from a serialization stream + - - Asset from the asset server + + + InventoryCallingCard Class, contains information on another avatar + - - Inventory item + + + Construct an InventoryCallingCard object + + A which becomes the + objects AssetUUID - - Estate asset, such as an estate covenant + + + Construct an InventoryCallingCard object from a serialization stream + - + - + InventoryLandmark Class, contains details on a specific location - - + + + Construct an InventoryLandmark object + + A which becomes the + objects AssetUUID - - + + + Construct an InventoryLandmark object from a serialization stream + - - + + + Landmarks use the InventoryItemFlags struct and will have a flag of 1 set if they have been visited + - + - + InventoryObject Class contains details on a primitive or coalesced set of primitives - - + + + Construct an InventoryObject object + + A which becomes the + objects AssetUUID - - + + + Construct an InventoryObject object from a serialization stream + - + - Image file format + Gets or sets the upper byte of the Flags value - + - + Gets or sets the object attachment point, the lower byte of the Flags value - - Number of milliseconds passed since the last transfer - packet was received + + + InventoryNotecard Class, contains details on an encoded text document + - + - + Construct an InventoryNotecard object + A which becomes the + objects AssetUUID - + - + Construct an InventoryNotecard object from a serialization stream - + - + InventoryCategory Class + TODO: Is this even used for anything? - + - + Construct an InventoryCategory object + A which becomes the + objects AssetUUID - + - + Construct an InventoryCategory object from a serialization stream - + - + InventoryLSL Class, represents a Linden Scripting Language object - - - - - + - + Construct an InventoryLSL object + A which becomes the + objects AssetUUID - - Number of milliseconds to wait for a transfer header packet if out of order data was received + + + Construct an InventoryLSL object from a serialization stream + - - The event subscribers. null if no subcribers + + + InventorySnapshot Class, an image taken with the viewer + - - Raises the XferReceived event - A XferReceivedEventArgs object containing the - data returned from the simulator + + + Construct an InventorySnapshot object + + A which becomes the + objects AssetUUID - - Thread sync lock object + + + Construct an InventorySnapshot object from a serialization stream + - - The event subscribers. null if no subcribers + + + InventoryAttachment Class, contains details on an attachable object + - - Raises the AssetUploaded event - A AssetUploadedEventArgs object containing the - data returned from the simulator + + + Construct an InventoryAttachment object + + A which becomes the + objects AssetUUID - - Thread sync lock object + + + Construct an InventoryAttachment object from a serialization stream + - - The event subscribers. null if no subcribers + + + Get the last AttachmentPoint this object was attached to + - - Raises the UploadProgress event - A UploadProgressEventArgs object containing the - data returned from the simulator + + + InventoryWearable Class, details on a clothing item or body part + - - Thread sync lock object + + + Construct an InventoryWearable object + + A which becomes the + objects AssetUUID - - The event subscribers. null if no subcribers + + + Construct an InventoryWearable object from a serialization stream + - - Raises the InitiateDownload event - A InitiateDownloadEventArgs object containing the - data returned from the simulator + + + The , Skin, Shape, Skirt, Etc + - - Thread sync lock object + + + InventoryAnimation Class, A bvh encoded object which animates an avatar + - - The event subscribers. null if no subcribers + + + Construct an InventoryAnimation object + + A which becomes the + objects AssetUUID - - Raises the ImageReceiveProgress event - A ImageReceiveProgressEventArgs object containing the - data returned from the simulator + + + Construct an InventoryAnimation object from a serialization stream + - - Thread sync lock object + + + InventoryGesture Class, details on a series of animations, sounds, and actions + - - Texture download cache + + + Construct an InventoryGesture object + + A which becomes the + objects AssetUUID - + - Default constructor + Construct an InventoryGesture object from a serialization stream - A reference to the GridClient object - + - Request an asset download + A folder contains s and has certain attributes specific + to itself - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - The callback to fire when the simulator responds with the asset data - + - Request an asset download + Constructor - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - The callback to fire when the simulator responds with the asset data + UUID of the folder - + - Request an asset download + Construct an InventoryFolder object from a serialization stream - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - UUID of the transaction - The callback to fire when the simulator responds with the asset data - + + The Preferred for a folder. + + + The Version of this folder + + + Number of child items this folder contains. + + - Request an asset download through the almost deprecated Xfer system - Filename of the asset to request - Whether or not to delete the asset - off the server after it is retrieved - Use large transfer packets or not - UUID of the file to request, if filename is - left empty - Asset type of vFileID, or - AssetType.Unknown if filename is not empty - Sets the FilePath in the request to Cache - (4) if true, otherwise Unknown (0) is used - + + - + - + Get Serilization data for this InventoryFolder object - Use UUID.Zero if you do not have the - asset ID but have all the necessary permissions - The item ID of this asset in the inventory - Use UUID.Zero if you are not requesting an - asset from an object inventory - The owner of this asset - Asset type - Whether to prioritize this asset download or not - - + - Used to force asset data into the PendingUpload property, ie: for raw terrain uploads - An AssetUpload object containing the data to upload to the simulator + + - + - Request an asset be uploaded to the simulator - The Object containing the asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired + + + + - + - Request an asset be uploaded to the simulator - The of the asset being uploaded - A byte array containing the encoded asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired + + + + - + - Request an asset be uploaded to the simulator - - Asset type to upload this data as - A byte array containing the encoded asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired + + + + - + - Initiate an asset upload + Tools for dealing with agents inventory - The ID this asset will have if the - upload succeeds - Asset type to upload this data as - Raw asset data to upload - Whether to store this asset on the local - simulator or the grid-wide asset server - The tranaction id for the upload - The transaction ID of this transfer - - - Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - A float indicating the requested priority for the transfer. Higher priority values tell the simulator - to prioritize the request before lower valued requests. An image already being transferred using the can have - its priority changed by resending the request with the new priority value - Number of quality layers to discard. - This controls the end marker of the data sent. Sending with value -1 combined with priority of 0 cancels an in-progress - transfer. - A bug exists in the Linden Simulator where a -1 will occasionally be sent with a non-zero priority - indicating an off-by-one error. - The packet number to begin the request at. A value of 0 begins the request - from the start of the asset texture - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request - - Request an image and fire a callback when the request is complete - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); - - private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", - asset.AssetID, - asset.AssetData.Length); - } - } - - Request an image and use an inline anonymous method to handle the downloaded texture data - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, delegate(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", - asset.AssetID, - asset.AssetData.Length); - } - } - ); - - Request a texture, decode the texture to a bitmap image and apply it to a imagebox - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); - - private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - ManagedImage imgData; - Image bitmap; - - if (state == TextureRequestState.Finished) - { - OpenJPEG.DecodeToImage(assetTexture.AssetData, out imgData, out bitmap); - picInsignia.Image = bitmap; - } - } - } - - + + + Default constructor + + Reference to the GridClient object - + - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator + Callback for inventory item creation finishing - The of the texture asset to download - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data + Whether the request to create an inventory + item succeeded or not + Inventory item being created. If success is + false this will be null - + - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator + Callback for an inventory item being create from an uploaded asset - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data + true if inventory item creation was successful + + + + + + - + - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request + + - + - Cancel a texture request + Reply received when uploading an inventory asset - The texture assets + Has upload been successful + Error message if upload failed + Inventory asset UUID + New asset UUID - + - Lets TexturePipeline class fire the progress event + Delegate that is invoked when script upload is completed - The texture ID currently being downloaded - the number of bytes transferred - the total number of bytes expected + Has upload succeded (note, there still might be compile errors) + Upload status message + Is compilation successful + If compilation failed, list of error messages, null on compilation success + Script inventory UUID + Script's new asset UUID - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Used for converting shadow_id to asset_id - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The event subscribers, null of no subscribers - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Thread sync lock object - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The event subscribers, null of no subscribers - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Thread sync lock object - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The event subscribers, null of no subscribers - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Thread sync lock object - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The event subscribers, null of no subscribers - - Raised when the simulator responds sends + + Thread sync lock object - - Raised during upload completes + + The event subscribers, null of no subscribers - - Raised during upload with progres update + + Thread sync lock object - - Fired when the simulator sends an InitiateDownloadPacket, used to download terrain .raw files + + The event subscribers, null of no subscribers - - Fired when a texture is in the process of being downloaded by the TexturePipeline class + + Thread sync lock object - - - Callback used for various asset download requests - - Transfer information - Downloaded asset, null on fail + + The event subscribers, null of no subscribers - - - Callback used upon competition of baked texture upload - - Asset UUID of the newly uploaded baked texture + + Thread sync lock object - - Xfer data + + The event subscribers, null of no subscribers - - Upload data + + Thread sync lock object - - Filename used on the simulator + + Partial mapping of AssetTypes to folder names - - Filename used by the client + + Raised when the simulator sends us data containing + ... - - UUID of the image that is in progress + + Raised when the simulator sends us data containing + ... - - Number of bytes received so far + + Raised when the simulator sends us data containing + an inventory object sent by another avatar or primitive - - Image size in bytes + + Raised when the simulator sends us data containing + ... - - - - + + Raised when the simulator sends us data containing + ... - - The event subscribers, null of no subscribers + + Raised when the simulator sends us data containing + ... - - Raises the AttachedSound Event - A AttachedSoundEventArgs object containing - the data sent from the simulator + + Raised when the simulator sends us data containing + ... - - Thread sync lock object + + Raised when the simulator sends us data containing + ... - - The event subscribers, null of no subscribers + + + Get this agents Inventory data + - - Raises the AttachedSoundGainChange Event - A AttachedSoundGainChangeEventArgs object containing - the data sent from the simulator + + Raises the ItemReceived Event + A ItemReceivedEventArgs object containing + the data sent from the simulator - - Thread sync lock object + + Raises the FolderUpdated Event + A FolderUpdatedEventArgs object containing + the data sent from the simulator - - The event subscribers, null of no subscribers + + Raises the InventoryObjectOffered Event + A InventoryObjectOfferedEventArgs object containing + the data sent from the simulator - - Raises the SoundTrigger Event - A SoundTriggerEventArgs object containing - the data sent from the simulator + + Raises the TaskItemReceived Event + A TaskItemReceivedEventArgs object containing + the data sent from the simulator - - Thread sync lock object + + Raises the FindObjectByPath Event + A FindObjectByPathEventArgs object containing + the data sent from the simulator - - The event subscribers, null of no subscribers + + Raises the TaskInventoryReply Event + A TaskInventoryReplyEventArgs object containing + the data sent from the simulator - - Raises the PreloadSound Event - A PreloadSoundEventArgs object containing - the data sent from the simulator + + Raises the SaveAssetToInventory Event + A SaveAssetToInventoryEventArgs object containing + the data sent from the simulator - - Thread sync lock object + + Raises the ScriptRunningReply Event + A ScriptRunningReplyEventArgs object containing + the data sent from the simulator - + - Construct a new instance of the SoundManager class, used for playing and receiving - sound assets + Fetch an inventory item from the dataserver - A reference to the current GridClient instance + The items + The item Owners + a integer representing the number of milliseconds to wait for results + An object on success, or null if no item was found + Items will also be sent to the event - + - Plays a sound in the current region at full volume from avatar position + Request A single inventory item - UUID of the sound to be played + The items + The item Owners + - + - Plays a sound in the current region at full volume + Request inventory items - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. + Inventory items to request + Owners of the inventory items + - + - Plays a sound in the current region + Get contents of a folder - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 + The of the folder to search + The of the folders owner + true to retrieve folders + true to retrieve items + sort order to return results in + a integer representing the number of milliseconds to wait for results + A list of inventory items matching search criteria within folder + + InventoryFolder.DescendentCount will only be accurate if both folders and items are + requested - + - Plays a sound in the specified sim + Request the contents of an inventory folder - UUID of the sound to be played. - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 + The folder to search + The folder owners + true to return s contained in folder + true to return s containd in folder + the sort order to return items in + - + - Play a sound asset + Returns the UUID of the folder (category) that defaults to + containing 'type'. The folder is not necessarily only for that + type - UUID of the sound to be played. - handle id for the sim to be played in. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + This will return the root folder if one does not exist + + + The UUID of the desired folder if found, the UUID of the RootFolder + if not found, or UUID.Zero on failure - - Raised when the simulator sends us data containing - sound + + + Find an object in inventory using a specific path to search + + The folder to begin the search in + The object owners + A string path to search + milliseconds to wait for a reply + Found items or if + timeout occurs or item is not found - - Raised when the simulator sends us data containing - ... + + + Find inventory items by path + + The folder to begin the search in + The object owners + A string path to search, folders/objects separated by a '/' + Results are sent to the event - - Raised when the simulator sends us data containing - ... + + + Search inventory Store object for an item or folder + + The folder to begin the search in + An array which creates a path to search + Number of levels below baseFolder to conduct searches + if True, will stop searching after first match is found + A list of inventory items found - - Raised when the simulator sends us data containing - ... + + + Move an inventory item or folder to a new location + + The item or folder to move + The to move item or folder to - - Provides data for the event - The event occurs when the simulator sends - the sound data which emits from an agents attachment - - The following code example shows the process to subscribe to the event - and a stub to handle the data passed from the simulator - - // Subscribe to the AttachedSound event - Client.Sound.AttachedSound += Sound_AttachedSound; - - // process the data raised in the event here - private void Sound_AttachedSound(object sender, AttachedSoundEventArgs e) - { - // ... Process AttachedSoundEventArgs here ... - } - - + + + Move an inventory item or folder to a new location and change its name + + The item or folder to move + The to move item or folder to + The name to change the item or folder to - + - Construct a new instance of the SoundTriggerEventArgs class + Move and rename a folder - The sound asset id - The ID of the owner - The ID of the object - The volume level - The + The source folders + The destination folders + The name to change the folder to - - Get the sound asset id + + + Update folder properties + + + of the folder to update + Sets folder's parent to + Folder name + Folder type - - Get the ID of the owner + + + Move a folder + + The source folders + The destination folders - - Get the ID of the Object + + + Move multiple folders, the keys in the Dictionary parameter, + to a new parents, the value of that folder's key. + + A Dictionary containing the + of the source as the key, and the + of the destination as the value - - Get the volume level + + + Move an inventory item to a new folder + + The of the source item to move + The of the destination folder - - Get the + + + Move and rename an inventory item + + The of the source item to move + The of the destination folder + The name to change the folder to - - Provides data for the event - The event occurs when an attached sound - changes its volume level + + + Move multiple inventory items to new locations + + A Dictionary containing the + of the source item as the key, and the + of the destination folder as the value - + - Construct a new instance of the AttachedSoundGainChangedEventArgs class + Remove descendants of a folder - The ID of the Object - The new volume level + The of the folder - - Get the ID of the Object + + + Remove a single item from inventory + + The of the inventory item to remove - - Get the volume level + + + Remove a folder from inventory + + The of the folder to remove - - Provides data for the event - The event occurs when the simulator forwards - a request made by yourself or another agent to play either an asset sound or a built in sound - - Requests to play sounds where the is not one of the built-in - will require sending a request to download the sound asset before it can be played - - - The following code example uses the , - and - properties to display some information on a sound request on the window. - - // subscribe to the event - Client.Sound.SoundTrigger += Sound_SoundTrigger; - - // play the pre-defined BELL_TING sound - Client.Sound.SendSoundTrigger(Sounds.BELL_TING); - - // handle the response data - private void Sound_SoundTrigger(object sender, SoundTriggerEventArgs e) - { - Console.WriteLine("{0} played the sound {1} at volume {2}", - e.OwnerID, e.SoundID, e.Gain); - } - - - - + - Construct a new instance of the SoundTriggerEventArgs class + Remove multiple items or folders from inventory - The sound asset id - The ID of the owner - The ID of the object - The ID of the objects parent - The volume level - The regionhandle - The source position + A List containing the s of items to remove + A List containing the s of the folders to remove - - Get the sound asset id + + + Empty the Lost and Found folder + - - Get the ID of the owner + + + Empty the Trash folder + - - Get the ID of the Object + + + + + + + + + + + + Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. + + + + + + - - Get the ID of the objects parent + + + + + + + + + + + + Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. + + + + + + + + - - Get the volume level + + + Creates a new inventory folder + + ID of the folder to put this folder in + Name of the folder to create + The UUID of the newly created folder - - Get the regionhandle + + + Creates a new inventory folder + + ID of the folder to put this folder in + Name of the folder to create + Sets this folder as the default folder + for new assets of the specified type. Use AssetType.Unknown + to create a normal folder, otherwise it will likely create a + duplicate of an existing folder type + The UUID of the newly created folder + If you specify a preferred type of AsseType.Folder + it will create a new root folder which may likely cause all sorts + of strange problems - - Get the source position + + + Create an inventory item and upload asset data + + Asset data + Inventory item name + Inventory item description + Asset type + Inventory type + Put newly created inventory in this folder + Delegate that will receive feedback on success or failure - - Provides data for the event - The event occurs when the simulator sends - the appearance data for an avatar - - The following code example uses the and - properties to display the selected shape of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; - - // handle the data when the event is raised - void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) - { - Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") - } - - + + + Create an inventory item and upload asset data + + Asset data + Inventory item name + Inventory item description + Asset type + Inventory type + Put newly created inventory in this folder + Permission of the newly created item + (EveryoneMask, GroupMask, and NextOwnerMask of Permissions struct are supported) + Delegate that will receive feedback on success or failure - + - Construct a new instance of the PreloadSoundEventArgs class + Creates inventory link to another inventory item or folder - The sound asset id - The ID of the owner - The ID of the object + Put newly created link in folder with this UUID + Inventory item or folder + Method to call upon creation of the link - - Get the sound asset id + + + Creates inventory link to another inventory item + + Put newly created link in folder with this UUID + Original inventory item + Method to call upon creation of the link - - Get the ID of the owner + + + Creates inventory link to another inventory folder + + Put newly created link in folder with this UUID + Original inventory folder + Method to call upon creation of the link - - Get the ID of the Object + + + Creates inventory link to another inventory item or folder + + Put newly created link in folder with this UUID + Original item's UUID + Name + Description + Asset Type + Inventory Type + Transaction UUID + Method to call upon creation of the link - + - Class for controlling various system settings. - Some values are readonly because they affect things that - happen when the GridClient object is initialized, so changing them at - runtime won't do any good. Non-readonly values may affect things that - happen at login or dynamically + + + + + + + + - - Main grid login server + + + + + + + + + + + + + - - Beta grid login server + + + + + + + + + + + + + - + + + Request a copy of an asset embedded within a notecard + + Usually UUID.Zero for copying an asset from a notecard + UUID of the notecard to request an asset from + Target folder for asset to go to in your inventory + UUID of the embedded asset + callback to run when item is copied to inventory + + - InventoryManager requests inventory information on login, - GridClient initializes an Inventory store for main inventory. + + - + - InventoryManager requests library information on login, - GridClient initializes an Inventory store for the library. + + - - Number of milliseconds between sending pings to each sim - - - Number of milliseconds between sending camera updates - - - Number of milliseconds between updating the current - positions of moving, non-accelerating and non-colliding objects + + + + + + + - - Millisecond interval between ticks, where all ACKs are - sent out and the age of unACKed packets is checked + + + + + + + + + - - The initial size of the packet inbox, where packets are - stored before processing + + + Save changes to notecard embedded in object contents + + Encoded notecard asset data + Notecard UUID + Object's UUID + Called upon finish of the upload with status information - - Maximum size of packet that we want to send over the wire + + + Upload new gesture asset for an inventory gesture item + + Encoded gesture asset + Gesture inventory UUID + Callback whick will be called when upload is complete - - The maximum value of a packet sequence number before it - rolls over back to one + + + Update an existing script in an agents Inventory + + A byte[] array containing the encoded scripts contents + the itemID of the script + if true, sets the script content to run on the mono interpreter + + - - The maximum size of the sequence number archive, used to - check for resent and/or duplicate packets + + + Update an existing script in an task Inventory + + A byte[] array containing the encoded scripts contents + the itemID of the script + UUID of the prim containting the script + if true, sets the script content to run on the mono interpreter + if true, sets the script to running + + - - The relative directory where external resources are kept + + + Rez an object from inventory + + Simulator to place object in + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details - - Login server to connect to + + + Rez an object from inventory + + Simulator to place object in + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details + UUID of group to own the object - - IP Address the client will bind to + + + Rez an object from inventory + + Simulator to place object in + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details + UUID of group to own the object + User defined queryID to correlate replies + If set to true, the CreateSelected flag + will be set on the rezzed object - - Use XML-RPC Login or LLSD Login, default is XML-RPC Login + + + DeRez an object from the simulator to the agents Objects folder in the agents Inventory + + The simulator Local ID of the object + If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed - - Number of milliseconds before an asset transfer will time - out + + + DeRez an object from the simulator and return to inventory + + The simulator Local ID of the object + The type of destination from the enum + The destination inventory folders -or- + if DeRezzing object to a tasks Inventory, the Tasks + The transaction ID for this request which + can be used to correlate this request with other packets + If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed - - Number of milliseconds before a teleport attempt will time - out + + + Rez an item from inventory to its previous simulator location + + + + + + + + + - - Number of milliseconds before NetworkManager.Logout() will - time out + + + Give an inventory item to another avatar + + The of the item to give + The name of the item + The type of the item from the enum + The of the recipient + true to generate a beameffect during transfer - - Number of milliseconds before a CAPS call will time out - Setting this too low will cause web requests time out and - possibly retry repeatedly + + + Give an inventory Folder with contents to another avatar + + The of the Folder to give + The name of the folder + The type of the item from the enum + The of the recipient + true to generate a beameffect during transfer - - Number of milliseconds for xml-rpc to timeout + + + Copy or move an from agent inventory to a task (primitive) inventory + + The target object + The item to copy or move from inventory + + + For items with copy permissions a copy of the item is placed in the tasks inventory, + for no-copy items the object is moved to the tasks inventory - - Milliseconds before a packet is assumed lost and resent + + + Retrieve a listing of the items contained in a task (Primitive) + + The tasks + The tasks simulator local ID + milliseconds to wait for reply from simulator + A list containing the inventory items inside the task or null + if a timeout occurs + This request blocks until the response from the simulator arrives + or timeoutMS is exceeded - - Milliseconds without receiving a packet before the - connection to a simulator is assumed lost + + + Request the contents of a tasks (primitives) inventory from the + current simulator + + The LocalID of the object + - - Milliseconds to wait for a simulator info request through - the grid interface + + + Request the contents of a tasks (primitives) inventory + + The simulator Local ID of the object + A reference to the simulator object that contains the object + - - Maximum number of queued ACKs to be sent before SendAcks() - is forced + + + Move an item from a tasks (Primitive) inventory to the specified folder in the avatars inventory + + LocalID of the object in the simulator + UUID of the task item to move + The ID of the destination folder in this agents inventory + Simulator Object + Raises the event - - Network stats queue length (seconds) + + + Remove an item from an objects (Prim) Inventory + + LocalID of the object in the simulator + UUID of the task item to remove + Simulator Object + You can confirm the removal by comparing the tasks inventory serial before and after the + request with the request combined with + the event - - Enable to process packets synchronously, where all of the - callbacks for each packet must return before the next packet is - processed - This is an experimental feature and is not completely - reliable yet. Ideally it would reduce context switches and thread - overhead, but several calls currently block for a long time and - would need to be rewritten as asynchronous code before this is - feasible + + + Copy an InventoryScript item from the Agents Inventory into a primitives task inventory + + An unsigned integer representing a primitive being simulated + An which represents a script object from the agents inventory + true to set the scripts running state to enabled + A Unique Transaction ID + + The following example shows the basic steps necessary to copy a script from the agents inventory into a tasks inventory + and assumes the script exists in the agents inventory. + + uint primID = 95899503; // Fake prim ID + UUID scriptID = UUID.Parse("92a7fe8a-e949-dd39-a8d8-1681d8673232"); // Fake Script UUID in Inventory + Client.Inventory.FolderContents(Client.Inventory.FindFolderForType(AssetType.LSLText), Client.Self.AgentID, + false, true, InventorySortOrder.ByName, 10000); + Client.Inventory.RezScript(primID, (InventoryItem)Client.Inventory.Store[scriptID]); + - - Enable/disable storing terrain heightmaps in the - TerrainManager + + + Request the running status of a script contained in a task (primitive) inventory + + The ID of the primitive containing the script + The ID of the script + The event can be used to obtain the results of the + request + - - Enable/disable sending periodic camera updates + + + Send a request to set the running state of a script contained in a task (primitive) inventory + + The ID of the primitive containing the script + The ID of the script + true to set the script running, false to stop a running script + To verify the change you can use the method combined + with the event - - Enable/disable automatically setting agent appearance at - login and after sim crossing + + + Create a CRC from an InventoryItem + + The source InventoryItem + A uint representing the source InventoryItem as a CRC - - Enable/disable automatically setting the bandwidth throttle - after connecting to each simulator - The default throttle uses the equivalent of the maximum - bandwidth setting in the official client. If you do not set a - throttle your connection will by default be throttled well below - the minimum values and you may experience connection problems + + + Reverses a cheesy XORing with a fixed UUID to convert a shadow_id to an asset_id + + Obfuscated shadow_id value + Deobfuscated asset_id value - - Enable/disable the sending of pings to monitor lag and - packet loss + + + Does a cheesy XORing with a fixed UUID to convert an asset_id to a shadow_id + + asset_id value to obfuscate + Obfuscated shadow_id value - - Should we connect to multiple sims? This will allow - viewing in to neighboring simulators and sim crossings - (Experimental) + + + Wrapper for creating a new object + + The type of item from the enum + The of the newly created object + An object with the type and id passed - - If true, all object update packets will be decoded in to - native objects. If false, only updates for our own agent will be - decoded. Registering an event handler will force objects for that - type to always be decoded. If this is disabled the object tracking - will have missing or partial prim and avatar information + + + Parse the results of a RequestTaskInventory() response + + A string which contains the data from the task reply + A List containing the items contained within the tasks inventory - - If true, when a cached object check is received from the - server the full object info will automatically be requested + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Whether to establish connections to HTTP capabilities - servers for simulators + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Whether to decode sim stats + + + UpdateCreateInventoryItem packets are received when a new inventory item + is created. This may occur when an object that's rezzed in world is + taken into inventory, when an item is created using the CreateInventoryItem + packet, or when an object is purchased + + The sender + The EventArgs object containing the packet data - - The capabilities servers are currently designed to - periodically return a 502 error which signals for the client to - re-establish a connection. Set this to true to log those 502 errors + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - If true, any reference received for a folder or item - the library is not aware of will automatically be fetched + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - If true, and SEND_AGENT_UPDATES is true, - AgentUpdate packets will continuously be sent out to give the bot - smoother movement and autopiloting + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - If true, currently visible avatars will be stored - in dictionaries inside Simulator.ObjectAvatars. - If false, a new Avatar or Primitive object will be created - each time an object update packet is received + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - If true, currently visible avatars will be stored - in dictionaries inside Simulator.ObjectPrimitives. - If false, a new Avatar or Primitive object will be created - each time an object update packet is received + + Set to true to accept offer, false to decline it - - If true, position and velocity will periodically be - interpolated (extrapolated, technically) for objects and - avatars that are being tracked by the library. This is - necessary to increase the accuracy of speed and position - estimates for simulated objects + + The folder to accept the inventory into, if null default folder for will be used - + - If true, utilization statistics will be tracked. There is a minor penalty - in CPU time for enabling this option. + Callback when an inventory object is accepted and received from a + task inventory. This is the callback in which you actually get + the ItemID, as in ObjectOfferedCallback it is null when received + from a task. - - If true, parcel details will be stored in the - Simulator.Parcels dictionary as they are received - - + - If true, an incoming parcel properties reply will automatically send - a request for the parcel access list - + - if true, an incoming parcel properties reply will automatically send - a request for the traffic count. + + - + - If true, images, and other assets downloaded from the server - will be cached in a local directory + De-serialization constructor for the InventoryNode Class - - Path to store cached texture data - - - Maximum size cached files are allowed to take on disk (bytes) - - - Default color used for viewer particle effects + + + De-serialization handler for the InventoryNode Class + - - Maximum number of times to resend a failed packet + + + - - Throttle outgoing packet rate + + + - - UUID of a texture used by some viewers to indentify type of client used + + + - - The maximum number of concurrent texture downloads allowed - Increasing this number will not necessarily increase texture retrieval times due to - simulator throttles + + + - + - The Refresh timer inteval is used to set the delay between checks for stalled texture downloads + For inventory folder nodes specifies weather the folder needs to be + refreshed from the server - This is a static variable which applies to all instances - + - Textures taking longer than this value will be flagged as timed out and removed from the pipeline + Serialization handler for the InventoryNode Class - + - Get or set the minimum log level to output to the console by default - - If the library is not compiled with DEBUG defined and this level is set to DEBUG - You will get no output on the console. This behavior can be overriden by creating - a logger configuration file for log4net + + - - Attach avatar names to log messages + + + Singleton logging class for the entire library + - - Log packet retransmission info + + + Default constructor + - - Constructor - Reference to a GridClient object + + + Callback used for client apps to receive log messages from + the library + + Data being logged + The severity of the log entry from - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + log4net logging engine - - Cost of uploading an asset - Read-only since this value is dynamically fetched at login + + Triggered whenever a message is logged. If this is left + null, log messages will go to the console - + - Represents a string of characters encoded with specific formatting properties + Send a log message to the logging engine + The log message + The severity of the log entry - - A text string containing main text of the notecard - - - List of s embedded on the notecard + + + Send a log message to the logging engine + + The log message + The severity of the log entry + Instance of the client - - Construct an Asset of type Notecard + + + Send a log message to the logging engine + + The log message + The severity of the log entry + Exception that was raised - + - Construct an Asset object of type Notecard + Send a log message to the logging engine - A unique specific to this asset - A byte array containing the raw asset data + The log message + The severity of the log entry + Instance of the client + Exception that was raised - + - Construct an Asset object of type Notecard + If the library is compiled with DEBUG defined, an event will be + fired if an OnLogMessage handler is registered and the + message will be sent to the logging engine - A text string containing the main body text of the notecard + The message to log at the DEBUG level to the + current logging engine - + - Encode the raw contents of a string with the specific Linden Text properties + If the library is compiled with DEBUG defined and + GridClient.Settings.DEBUG is true, an event will be + fired if an OnLogMessage handler is registered and the + message will be sent to the logging engine + The message to log at the DEBUG level to the + current logging engine + Instance of the client - + - Decode the raw asset data including the Linden Text properties - true if the AssetData was successfully decoded - - Override the base classes AssetType - - + - Capabilities is the name of the bi-directional HTTP REST protocol - used to communicate non real-time transactions such as teleporting or - group messaging - - Reference to the simulator this system is connected to - - + - Default constructor - - - + - Request the URI of a named capability - Name of the capability to request - The URI of the requested capability, or String.Empty if - the capability does not exist - + - Process any incoming events, check to see if we have a message created for the event, - - - - - Capabilities URI this system was initialized with - - - Whether the capabilities event queue is connected and - listening for incoming events - + - Triggered when an event is received via the EventQueueGet - capability - Event name - Decoded event data - The simulator that generated the event - + - Level of Detail mesh - + - Return a decoded capabilities message as a strongly typed object - A string containing the name of the capabilities message key - An to decode - A strongly typed object containing the decoded information from the capabilities message, or null - if no existing Message object exists for the specified event - + - + Login Request Parameters - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + Default constuctor, initializes sane default values - - - - - - - - - - - - - + - + Instantiates new LoginParams object and fills in the values - - + Instance of GridClient to read settings from + Login first name + Login last name + Password + Login channnel (application name) + Client version, should be application name + version number - + - + Instantiates new LoginParams object and fills in the values + Instance of GridClient to read settings from + Login first name + Login last name + Password + Login channnel (application name) + Client version, should be application name + version number + URI of the login server - - + + The URL of the Login Server - - + + The number of milliseconds to wait before a login is considered + failed due to timeout - - + + The request method + login_to_simulator is currently the only supported method - - + + The Agents First name - - - - - - + + The Agents Last name - - - - + + A md5 hashed password + plaintext password will be automatically hashed - - + + The agents starting location once logged in + Either "last", "home", or a string encoded URI + containing the simulator name and x/y/z coordinates e.g: uri:hooper&128&152&17 - - + + A string containing the client software channel information + Second Life Release - - + + The client software version information + The official viewer uses: Second Life Release n.n.n.n + where n is replaced with the current version of the viewer - - + + A string containing the platform information the agent is running on - - + + A string hash of the network cards Mac Address - - + + Unknown or deprecated - - - - + + A string hash of the first disk drives ID used to identify this clients uniqueness - - + + A string containing the viewers Software, this is not directly sent to the login server but + instead is used to generate the Version string - - + + A string representing the software creator. This is not directly sent to the login server but + is used by the library to generate the Version information - - + + If true, this agent agrees to the Terms of Service of the grid its connecting to - - + + Unknown - - + + An array of string sent to the login server to enable various options - - - - - - + + A randomly generated ID to distinguish between login attempts. This value is only used + internally in the library and is never sent over the wire - + - + The decoded data returned from the login server after a successful login - - - - - - - - + + true, false, indeterminate - - - - - - - + + Login message of the day - + + M or PG, also agent_region_access and agent_access_max + + - + Parse LLSD Login Reply Data + An + contaning the login response data + XML-RPC logins do not require this as XML-RPC.NET + automatically populates the struct properly using attributes - + - + Login Routines - - - - - + NetworkManager is responsible for managing the network layer of + OpenMetaverse. It tracks all the server connections, serializes + outgoing traffic and deserializes incoming traffic, and provides + instances of delegates for network-related events. - - - + - + Default constructor - + Reference to the GridClient object - + - + Explains why a simulator or the grid disconnected from us - - + + The client requested the logout or simulator disconnect - - + + The server notified us that it is disconnecting - - + + Either a socket was closed or network traffic timed out - - + + The last active simulator shut down - - + + + Holds a simulator reference and a decoded packet, these structs are put in + the packet inbox for event handling + - - + + Reference to the simulator that this packet came from - - + + Packet that needs to be processed - + - Login Request Parameters + Holds a simulator reference and a serialized packet, these structs are put in + the packet outbox for sending - - The URL of the Login Server + + Reference to the simulator this packet is destined for - - The number of milliseconds to wait before a login is considered - failed due to timeout + + Packet that needs to be sent - - The request method - login_to_simulator is currently the only supported method + + Sequence number of the wrapped packet + + + Number of times this packet has been resent - - The Agents First name + + Environment.TickCount when this packet was last sent over the wire - - The Agents Last name + + + + + + + + + + + + + - - A md5 hashed password - plaintext password will be automatically hashed + + The event subscribers, null of no subscribers - - The agents starting location once logged in - Either "last", "home", or a string encoded URI - containing the simulator name and x/y/z coordinates e.g: uri:hooper&128&152&17 + + Thread sync lock object - - A string containing the client software channel information - Second Life Release + + Seed CAPS URL returned from the login server - - The client software version information - The official viewer uses: Second Life Release n.n.n.n - where n is replaced with the current version of the viewer + + A list of packets obtained during the login process which + networkmanager will log but not process - - A string containing the platform information the agent is running on + + The event subscribers, null of no subscribers - - A string hash of the network cards Mac Address + + Thread sync lock object - - Unknown or deprecated + + The event subscribers, null of no subscribers - - A string hash of the first disk drives ID used to identify this clients uniqueness + + Thread sync lock object - - A string containing the viewers Software, this is not directly sent to the login server but - instead is used to generate the Version string + + The event subscribers, null of no subscribers - - A string representing the software creator. This is not directly sent to the login server but - is used by the library to generate the Version information + + Thread sync lock object - - If true, this agent agrees to the Terms of Service of the grid its connecting to + + The event subscribers, null of no subscribers - - Unknown + + Thread sync lock object - - An array of string sent to the login server to enable various options + + The event subscribers, null of no subscribers - - A randomly generated ID to distinguish between login attempts. This value is only used - internally in the library and is never sent over the wire + + Thread sync lock object - - - The decoded data returned from the login server after a successful login - + + The event subscribers, null of no subscribers - - true, false, indeterminate + + Thread sync lock object - - Login message of the day + + The event subscribers, null of no subscribers - - M or PG, also agent_region_access and agent_access_max + + Thread sync lock object - - - Parse LLSD Login Reply Data - - An - contaning the login response data - XML-RPC logins do not require this as XML-RPC.NET - automatically populates the struct properly using attributes + + The event subscribers, null of no subscribers - - Sort by name + + Thread sync lock object - - Sort by date + + All of the simulators we are currently connected to - - Sort folders by name, regardless of whether items are - sorted by name or date + + Handlers for incoming capability events - - Place system folders at the top + + Handlers for incoming packets - - - Possible destinations for DeRezObject request - + + Incoming packets that are awaiting handling - - + + Outgoing packets that are awaiting handling - - Copy from in-world to agent inventory + + Raised when the simulator sends us data containing + ... - - Derez to TaskInventory + + Called when a reply is received from the login server, the + login sequence will block until this event returns - - + + Raised when the simulator sends us data containing + ... - - Take Object + + Raised when the simulator sends us data containing + ... - - + + Raised when the simulator sends us data containing + ... - - Delete Object + + Raised when the simulator sends us data containing + ... - - Put an avatar attachment into agent inventory + + Raised when the simulator sends us data containing + ... - - + + Raised when the simulator sends us data containing + ... - - Return an object back to the owner's inventory + + Raised when the simulator sends us data containing + ... - - Return a deeded object back to the last owner's inventory + + Raised when the simulator sends us data containing + ... - - - Upper half of the Flags field for inventory items - + + Current state of logging in - - Indicates that the NextOwner permission will be set to the - most restrictive set of permissions found in the object set - (including linkset items and object inventory items) on next rez + + Upon login failure, contains a short string key for the + type of login error that occurred - - Indicates that the object sale information has been - changed + + The raw XML-RPC reply from the login server, exactly as it + was received (minus the HTTP header) - - If set, and a slam bit is set, indicates BaseMask will be overwritten on Rez + + During login this contains a descriptive version of + LoginStatusCode. After a successful login this will contain the + message of the day, and after a failed login a descriptive error + message will be returned - - If set, and a slam bit is set, indicates OwnerMask will be overwritten on Rez + + Unique identifier associated with our connections to + simulators - - If set, and a slam bit is set, indicates GroupMask will be overwritten on Rez + + The simulator that the logged in avatar is currently + occupying - - If set, and a slam bit is set, indicates EveryoneMask will be overwritten on Rez + + Shows whether the network layer is logged in to the + grid or not - - If set, and a slam bit is set, indicates NextOwnerMask will be overwritten on Rez + + Number of packets in the incoming queue - - Indicates whether this object is composed of multiple - items or not + + Number of packets in the outgoing queue - - Indicates that the asset is only referenced by this - inventory item. If this item is deleted or updated to reference a - new assetID, the asset can be deleted + + Raises the LoginProgress Event + A LoginProgressEventArgs object containing + the data sent from the simulator - + - Base Class for Inventory Items + Generate sane default values for a login request + Account first name + Account last name + Account password + Client application name + Client application version + A populated struct containing + sane defaults - - of item/folder - - - of parent folder - - - Name of item/folder - - - Item/Folder Owners + + + Simplified login that takes the most common and required fields + + Account first name + Account last name + Account password + Client application name + Client application version + Whether the login was successful or not. On failure the + LoginErrorKey string will contain the error code and LoginMessage + will contain a description of the error - + - Constructor, takes an itemID as a parameter + Simplified login that takes the most common fields along with a + starting location URI, and can accept an MD5 string instead of a + plaintext password - The of the item + Account first name + Account last name + Account password or MD5 hash of the password + such as $1$1682a1e45e9f957dcdf0bb56eb43319c + Client application name + Starting location URI that can be built with + StartLocation() + Client application version + Whether the login was successful or not. On failure the + LoginErrorKey string will contain the error code and LoginMessage + will contain a description of the error - + - + Login that takes a struct of all the values that will be passed to + the login server - + The values that will be passed to the login + server, all fields must be set even if they are String.Empty + Whether the login was successful or not. On failure the + LoginErrorKey string will contain the error code and LoginMessage + will contain a description of the error - + - + Build a start location URI for passing to the Login function - + Name of the simulator to start in + X coordinate to start at + Y coordinate to start at + Z coordinate to start at + String with a URI that can be used to login to a specified + location - + - Generates a number corresponding to the value of the object to support the use of a hash table, - suitable for use in hashing algorithms and data structures such as a hash table + Handles response from XML-RPC login replies - A Hashcode of all the combined InventoryBase fields - + - Determine whether the specified object is equal to the current object + Handle response from LLSD login replies - InventoryBase object to compare against - true if objects are the same + + + + + + - + - Determine whether the specified object is equal to the current object + Get current OS - InventoryBase object to compare against - true if objects are the same + Either "Win" or "Linux" - + - An Item in Inventory + Get clients default Mac Address + A string containing the first found Mac Address - - The of this item + + Raises the PacketSent Event + A PacketSentEventArgs object containing + the data sent from the simulator - - The combined of this item + + Raises the LoggedOut Event + A LoggedOutEventArgs object containing + the data sent from the simulator - - The type of item from + + Raises the SimConnecting Event + A SimConnectingEventArgs object containing + the data sent from the simulator - - The type of item from the enum + + Raises the SimConnected Event + A SimConnectedEventArgs object containing + the data sent from the simulator - - The of the creator of this item + + Raises the SimDisconnected Event + A SimDisconnectedEventArgs object containing + the data sent from the simulator - - A Description of this item + + Raises the Disconnected Event + A DisconnectedEventArgs object containing + the data sent from the simulator - - The s this item is set to or owned by + + Raises the SimChanged Event + A SimChangedEventArgs object containing + the data sent from the simulator - - If true, item is owned by a group + + Raises the EventQueueRunning Event + A EventQueueRunningEventArgs object containing + the data sent from the simulator - - The price this item can be purchased for + + + Register an event handler for a packet. This is a low level event + interface and should only be used if you are doing something not + supported in the library + + Packet type to trigger events for + Callback to fire when a packet of this type + is received - - The type of sale from the enum + + + Register an event handler for a packet. This is a low level event + interface and should only be used if you are doing something not + supported in the library + + Packet type to trigger events for + Callback to fire when a packet of this type + is received + True if the callback should be ran + asynchronously. Only set this to false (synchronous for callbacks + that will always complete quickly) + If any callback for a packet type is marked as + asynchronous, all callbacks for that packet type will be fired + asynchronously - - Combined flags from + + + Unregister an event handler for a packet. This is a low level event + interface and should only be used if you are doing something not + supported in the library + + Packet type this callback is registered with + Callback to stop firing events for - - Time and date this inventory item was created, stored as - UTC (Coordinated Universal Time) + + + Register a CAPS event handler. This is a low level event interface + and should only be used if you are doing something not supported in + the library + + Name of the CAPS event to register a handler for + Callback to fire when a CAPS event is received - - Used to update the AssetID in requests sent to the server + + + Unregister a CAPS event handler. This is a low level event interface + and should only be used if you are doing something not supported in + the library + + Name of the CAPS event this callback is + registered with + Callback to stop firing events for - - The of the previous owner of the item + + + Send a packet to the simulator the avatar is currently occupying + + Packet to send - + - Construct a new InventoryItem object + Send a packet to a specified simulator - The of the item + Packet to send + Simulator to send the packet to - + - Construct a new InventoryItem object of a specific Type + Connect to a simulator - The type of item from - of the item + IP address to connect to + Port to connect to + Handle for this simulator, to identify its + location in the grid + Whether to set CurrentSim to this new + connection, use this if the avatar is moving in to this simulator + URL of the capabilities server to use for + this sim connection + A Simulator object on success, otherwise null - + - Indicates inventory item is a link + Connect to a simulator - True if inventory item is a link to another inventory item + IP address and port to connect to + Handle for this simulator, to identify its + location in the grid + Whether to set CurrentSim to this new + connection, use this if the avatar is moving in to this simulator + URL of the capabilities server to use for + this sim connection + A Simulator object on success, otherwise null - + - + Initiate a blocking logout request. This will return when the logout + handshake has completed or when Settings.LOGOUT_TIMEOUT + has expired and the network layer is manually shut down - - + - + Initiate the logout process. Check if logout succeeded with the + OnLogoutReply event, and if this does not fire the + Shutdown() function needs to be manually called - - + - Generates a number corresponding to the value of the object to support the use of a hash table. - Suitable for use in hashing algorithms and data structures such as a hash table + Close a connection to the given simulator - A Hashcode of all the combined InventoryItem fields + + + + - + - Compares an object + Shutdown will disconnect all the sims except for the current sim + first, and then kill the connection to CurrentSim. This should only + be called if the logout process times out on RequestLogout + Type of shutdown + + + + Shutdown will disconnect all the sims except for the current sim + first, and then kill the connection to CurrentSim. This should only + be called if the logout process times out on RequestLogout + Type of shutdown + Shutdown message + + + + Searches through the list of currently connected simulators to find + one attached to the given IPEndPoint - The object to compare - true if comparison object matches + IPEndPoint of the Simulator to search for + A Simulator reference on success, otherwise null + + + + Fire an event when an event queue connects for capabilities + + Simulator the event queue is attached to + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - Determine whether the specified object is equal to the current object + A Name Value pair with additional settings, used in the protocol + primarily to transmit avatar names and active group in object packets - The object to compare against - true if objects are the same - + - Determine whether the specified object is equal to the current object + Constructor that takes all the fields as parameters - The object to compare against - true if objects are the same + + + + + + + + + + - + - InventoryTexture Class representing a graphical image + Constructor that takes a single line from a NameValue field - + + - - - Construct an InventoryTexture object - - A which becomes the - objects AssetUUID + + Type of the value - - - Construct an InventoryTexture object from a serialization stream - + + Unknown - - - InventorySound Class representing a playable sound - + + String value - + - Construct an InventorySound object - A which becomes the - objects AssetUUID - + - Construct an InventorySound object from a serialization stream - + - InventoryCallingCard Class, contains information on another avatar - + - Construct an InventoryCallingCard object - A which becomes the - objects AssetUUID - - - Construct an InventoryCallingCard object from a serialization stream - + + Deprecated - - - InventoryLandmark Class, contains details on a specific location - + + String value, but designated as an asset - + - Construct an InventoryLandmark object - A which becomes the - objects AssetUUID - + - Construct an InventoryLandmark object from a serialization stream - + - Landmarks use the InventoryItemFlags struct and will have a flag of 1 set if they have been visited - + - InventoryObject Class contains details on a primitive or coalesced set of primitives - + - Construct an InventoryObject object - A which becomes the - objects AssetUUID - + - Construct an InventoryObject object from a serialization stream - + - Gets or sets the upper byte of the Flags value - + - Gets or sets the object attachment point, the lower byte of the Flags value - + - InventoryNotecard Class, contains details on an encoded text document - + - Construct an InventoryNotecard object - A which becomes the - objects AssetUUID - + - Construct an InventoryNotecard object from a serialization stream - + - InventoryCategory Class - TODO: Is this even used for anything? - + - Construct an InventoryCategory object - A which becomes the - objects AssetUUID - + - Construct an InventoryCategory object from a serialization stream - + - InventoryLSL Class, represents a Linden Scripting Language object - + - Construct an InventoryLSL object - A which becomes the - objects AssetUUID - + - Construct an InventoryLSL object from a serialization stream - + - InventorySnapshot Class, an image taken with the viewer - - - Construct an InventorySnapshot object - - A which becomes the - objects AssetUUID + + No report - - - Construct an InventorySnapshot object from a serialization stream - + + Unknown report type - - - InventoryAttachment Class, contains details on an attachable object - + + Bug report - - - Construct an InventoryAttachment object - - A which becomes the - objects AssetUUID + + Complaint report - - - Construct an InventoryAttachment object from a serialization stream - + + Customer service report - + - Get the last AttachmentPoint this object was attached to + Bitflag field for ObjectUpdateCompressed data blocks, describing + which options are present for each object - - - InventoryWearable Class, details on a clothing item or body part - + + Unknown - - - Construct an InventoryWearable object - - A which becomes the - objects AssetUUID + + Whether the object has a TreeSpecies - + + Whether the object has floating text ala llSetText + + + Whether the object has an active particle system + + + Whether the object has sound attached to it + + + Whether the object is attached to a root object or not + + + Whether the object has texture animation settings + + + Whether the object has an angular velocity + + + Whether the object has a name value pairs string + + + Whether the object has a Media URL set + + - Construct an InventoryWearable object from a serialization stream + Specific Flags for MultipleObjectUpdate requests - + + None + + + Change position of prims + + + Change rotation of prims + + + Change size of prims + + + Perform operation on link set + + + Scale prims uniformly, same as selecing ctrl+shift in the + viewer. Used in conjunction with Scale + + - The , Skin, Shape, Skirt, Etc + Special values in PayPriceReply. If the price is not one of these + literal value of the price should be use - + - InventoryAnimation Class, A bvh encoded object which animates an avatar + Indicates that this pay option should be hidden - + - Construct an InventoryAnimation object + Indicates that this pay option should have the default value - A which becomes the - objects AssetUUID - + - Construct an InventoryAnimation object from a serialization stream + Contains the variables sent in an object update packet for objects. + Used to track position and movement of prims and avatars - + - InventoryGesture Class, details on a series of animations, sounds, and actions - + - Construct an InventoryGesture object - A which becomes the - objects AssetUUID - + - Construct an InventoryGesture object from a serialization stream - + - A folder contains s and has certain attributes specific - to itself - - The Preferred for a folder. - - - The Version of this folder - - - Number of child items this folder contains. - - + - Constructor - UUID of the folder - + - - - + - Get Serilization data for this InventoryFolder object - + - Construct an InventoryFolder object from a serialization stream - + - - - + - - - - + - + Handles all network traffic related to prims and avatar positions and + movement. - - - + - + Construct a new instance of the ObjectManager class - - + A reference to the instance - + - Tools for dealing with agents inventory + Callback for getting object media data via CAP + Indicates if the operation was succesfull + Object media version string + Array indexed on prim face of media entry data - - Used for converting shadow_id to asset_id - - + The event subscribers, null of no subscribers - - Raises the ItemReceived Event - A ItemReceivedEventArgs object containing - the data sent from the simulator - - + Thread sync lock object - + The event subscribers, null of no subscribers - - Raises the FolderUpdated Event - A FolderUpdatedEventArgs object containing - the data sent from the simulator - - + Thread sync lock object - + The event subscribers, null of no subscribers - - Raises the InventoryObjectOffered Event - A InventoryObjectOfferedEventArgs object containing - the data sent from the simulator - - + Thread sync lock object - + The event subscribers, null of no subscribers - - Raises the TaskItemReceived Event - A TaskItemReceivedEventArgs object containing - the data sent from the simulator - - + Thread sync lock object - + The event subscribers, null of no subscribers - - Raises the FindObjectByPath Event - A FindObjectByPathEventArgs object containing - the data sent from the simulator - - + Thread sync lock object - + The event subscribers, null of no subscribers - - Raises the TaskInventoryReply Event - A TaskInventoryReplyEventArgs object containing - the data sent from the simulator - - + Thread sync lock object - + The event subscribers, null of no subscribers - - Raises the SaveAssetToInventory Event - A SaveAssetToInventoryEventArgs object containing - the data sent from the simulator - - + Thread sync lock object - + The event subscribers, null of no subscribers - - Raises the ScriptRunningReply Event - A ScriptRunningReplyEventArgs object containing - the data sent from the simulator - - + Thread sync lock object - - Partial mapping of AssetTypes to folder names - - - - Default constructor - - Reference to the GridClient object - - - - Fetch an inventory item from the dataserver - - The items - The item Owners - a integer representing the number of milliseconds to wait for results - An object on success, or null if no item was found - Items will also be sent to the event - - - - Request A single inventory item - - The items - The item Owners - - - - - Request inventory items - - Inventory items to request - Owners of the inventory items - - - - - Get contents of a folder - - The of the folder to search - The of the folders owner - true to retrieve folders - true to retrieve items - sort order to return results in - a integer representing the number of milliseconds to wait for results - A list of inventory items matching search criteria within folder - - InventoryFolder.DescendentCount will only be accurate if both folders and items are - requested - - - - Request the contents of an inventory folder - - The folder to search - The folder owners - true to return s contained in folder - true to return s containd in folder - the sort order to return items in - + + The event subscribers, null of no subscribers - - - Returns the UUID of the folder (category) that defaults to - containing 'type'. The folder is not necessarily only for that - type - - This will return the root folder if one does not exist - - The UUID of the desired folder if found, the UUID of the RootFolder - if not found, or UUID.Zero on failure + + Thread sync lock object - - - Find an object in inventory using a specific path to search - - The folder to begin the search in - The object owners - A string path to search - milliseconds to wait for a reply - Found items or if - timeout occurs or item is not found + + The event subscribers, null of no subscribers - - - Find inventory items by path - - The folder to begin the search in - The object owners - A string path to search, folders/objects separated by a '/' - Results are sent to the event + + Thread sync lock object - - - Search inventory Store object for an item or folder - - The folder to begin the search in - An array which creates a path to search - Number of levels below baseFolder to conduct searches - if True, will stop searching after first match is found - A list of inventory items found + + Reference to the GridClient object - - - Move an inventory item or folder to a new location - - The item or folder to move - The to move item or folder to + + Does periodic dead reckoning calculation to convert + velocity and acceleration to new positions for objects - - - Move an inventory item or folder to a new location and change its name - - The item or folder to move - The to move item or folder to - The name to change the item or folder to + + Raised when the simulator sends us data containing + A , Foliage or Attachment + + - - - Move and rename a folder - - The source folders - The destination folders - The name to change the folder to + + Raised when the simulator sends us data containing + additional information + + - - - Update folder properties - - of the folder to update - Sets folder's parent to - Folder name - Folder type + + Raised when the simulator sends us data containing + Primitive.ObjectProperties for an object we are currently tracking - - - Move a folder - - The source folders - The destination folders + + Raised when the simulator sends us data containing + additional and details + - - - Move multiple folders, the keys in the Dictionary parameter, - to a new parents, the value of that folder's key. - - A Dictionary containing the - of the source as the key, and the - of the destination as the value + + Raised when the simulator sends us data containing + updated information for an - - - Move an inventory item to a new folder - - The of the source item to move - The of the destination folder + + Raised when the simulator sends us data containing + and movement changes - - - Move and rename an inventory item - - The of the source item to move - The of the destination folder - The name to change the folder to + + Raised when the simulator sends us data containing + updates to an Objects DataBlock - - - Move multiple inventory items to new locations - - A Dictionary containing the - of the source item as the key, and the - of the destination folder as the value + + Raised when the simulator informs us an + or is no longer within view - - - Remove descendants of a folder - - The of the folder + + Raised when the simulator sends us data containing + updated sit information for our - - - Remove a single item from inventory - - The of the inventory item to remove + + Raised when the simulator sends us data containing + purchase price information for a - - - Remove a folder from inventory - - The of the folder to remove + + Raises the ObjectProperties Event + A ObjectPropertiesEventArgs object containing + the data sent from the simulator - - - Remove multiple items or folders from inventory - - A List containing the s of items to remove - A List containing the s of the folders to remove + + Raises the ObjectPropertiesUpdated Event + A ObjectPropertiesUpdatedEventArgs object containing + the data sent from the simulator - - - Empty the Lost and Found folder - + + Raises the ObjectPropertiesFamily Event + A ObjectPropertiesFamilyEventArgs object containing + the data sent from the simulator - - - Empty the Trash folder - + + Raises the AvatarUpdate Event + A AvatarUpdateEventArgs object containing + the data sent from the simulator - - - - - - - - - Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. - - - + + Raises the ObjectDataBlockUpdate Event + A ObjectDataBlockUpdateEventArgs object containing + the data sent from the simulator - - - - - - - - - Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. - - - - + + Raises the KillObject Event + A KillObjectEventArgs object containing + the data sent from the simulator - - - Creates a new inventory folder - - ID of the folder to put this folder in - Name of the folder to create - The UUID of the newly created folder + + Raises the AvatarSitChanged Event + A AvatarSitChangedEventArgs object containing + the data sent from the simulator - - - Creates a new inventory folder - - ID of the folder to put this folder in - Name of the folder to create - Sets this folder as the default folder - for new assets of the specified type. Use AssetType.Unknown - to create a normal folder, otherwise it will likely create a - duplicate of an existing folder type - The UUID of the newly created folder - If you specify a preferred type of AsseType.Folder - it will create a new root folder which may likely cause all sorts - of strange problems + + Raises the PayPriceReply Event + A PayPriceReplyEventArgs object containing + the data sent from the simulator - + - Create an inventory item and upload asset data + Request information for a single object from a + you are currently connected to - Asset data - Inventory item name - Inventory item description - Asset type - Inventory type - Put newly created inventory in this folder - Delegate that will receive feedback on success or failure + The the object is located + The Local ID of the object - + - Create an inventory item and upload asset data + Request information for multiple objects contained in + the same simulator - Asset data - Inventory item name - Inventory item description - Asset type - Inventory type - Put newly created inventory in this folder - Permission of the newly created item - (EveryoneMask, GroupMask, and NextOwnerMask of Permissions struct are supported) - Delegate that will receive feedback on success or failure + The the objects are located + An array containing the Local IDs of the objects - + - Creates inventory link to another inventory item or folder + Attempt to purchase an original object, a copy, or the contents of + an object - Put newly created link in folder with this UUID - Inventory item or folder - Method to call upon creation of the link + The the object is located + The Local ID of the object + Whether the original, a copy, or the object + contents are on sale. This is used for verification, if the this + sale type is not valid for the object the purchase will fail + Price of the object. This is used for + verification, if it does not match the actual price the purchase + will fail + Group ID that will be associated with the new + purchase + Inventory folder UUID where the object or objects + purchased should be placed + + + BuyObject(Client.Network.CurrentSim, 500, SaleType.Copy, + 100, UUID.Zero, Client.Self.InventoryRootFolderUUID); + + - + - Creates inventory link to another inventory item + Request prices that should be displayed in pay dialog. This will triggger the simulator + to send us back a PayPriceReply which can be handled by OnPayPriceReply event - Put newly created link in folder with this UUID - Original inventory item - Method to call upon creation of the link + The the object is located + The ID of the object + The result is raised in the event - + - Creates inventory link to another inventory folder + Select a single object. This will cause the to send us + an which will raise the event - Put newly created link in folder with this UUID - Original inventory folder - Method to call upon creation of the link + The the object is located + The Local ID of the object + - + - Creates inventory link to another inventory item or folder + Select a single object. This will cause the to send us + an which will raise the event - Put newly created link in folder with this UUID - Original item's UUID - Name - Description - Asset Type - Inventory Type - Transaction UUID - Method to call upon creation of the link + The the object is located + The Local ID of the object + if true, a call to is + made immediately following the request + - + - + Select multiple objects. This will cause the to send us + an which will raise the event - - - - + The the objects are located + An array containing the Local IDs of the objects + Should objects be deselected immediately after selection + - + - + Select multiple objects. This will cause the to send us + an which will raise the event - - - - - + The the objects are located + An array containing the Local IDs of the objects + - + - + Update the properties of an object - - - - - + The the object is located + The Local ID of the object + true to turn the objects physical property on + true to turn the objects temporary property on + true to turn the objects phantom property on + true to turn the objects cast shadows property on - + - Request a copy of an asset embedded within a notecard + Sets the sale properties of a single object - Usually UUID.Zero for copying an asset from a notecard - UUID of the notecard to request an asset from - Target folder for asset to go to in your inventory - UUID of the embedded asset - callback to run when item is copied to inventory + The the object is located + The Local ID of the object + One of the options from the enum + The price of the object - + - + Sets the sale properties of multiple objects - + The the objects are located + An array containing the Local IDs of the objects + One of the options from the enum + The price of the object - + - + Deselect a single object - + The the object is located + The Local ID of the object - + - + Deselect multiple objects. - - + The the objects are located + An array containing the Local IDs of the objects - + - + Perform a click action on an object - - - + The the object is located + The Local ID of the object - + - Save changes to notecard embedded in object contents + Perform a click action (Grab) on a single object - Encoded notecard asset data - Notecard UUID - Object's UUID - Called upon finish of the upload with status information + The the object is located + The Local ID of the object + The texture coordinates to touch + The surface coordinates to touch + The face of the position to touch + The region coordinates of the position to touch + The surface normal of the position to touch (A normal is a vector perpindicular to the surface) + The surface binormal of the position to touch (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - + - Upload new gesture asset for an inventory gesture item + Create (rez) a new prim object in a simulator - Encoded gesture asset - Gesture inventory UUID - Callback whick will be called when upload is complete + A reference to the object to place the object in + Data describing the prim object to rez + Group ID that this prim will be set to, or UUID.Zero if you + do not want the object to be associated with a specific group + An approximation of the position at which to rez the prim + Scale vector to size this prim + Rotation quaternion to rotate this prim + Due to the way client prim rezzing is done on the server, + the requested position for an object is only close to where the prim + actually ends up. If you desire exact placement you'll need to + follow up by moving the object after it has been created. This + function will not set textures, light and flexible data, or other + extended primitive properties - + - Update an existing script in an agents Inventory + Create (rez) a new prim object in a simulator - A byte[] array containing the encoded scripts contents - the itemID of the script - if true, sets the script content to run on the mono interpreter - + A reference to the object to place the object in + Data describing the prim object to rez + Group ID that this prim will be set to, or UUID.Zero if you + do not want the object to be associated with a specific group + An approximation of the position at which to rez the prim + Scale vector to size this prim + Rotation quaternion to rotate this prim + Specify the + Due to the way client prim rezzing is done on the server, + the requested position for an object is only close to where the prim + actually ends up. If you desire exact placement you'll need to + follow up by moving the object after it has been created. This + function will not set textures, light and flexible data, or other + extended primitive properties - + - Update an existing script in an task Inventory + Rez a Linden tree - A byte[] array containing the encoded scripts contents - the itemID of the script - UUID of the prim containting the script - if true, sets the script content to run on the mono interpreter - if true, sets the script to running - + A reference to the object where the object resides + The size of the tree + The rotation of the tree + The position of the tree + The Type of tree + The of the group to set the tree to, + or UUID.Zero if no group is to be set + true to use the "new" Linden trees, false to use the old - + - Rez an object from inventory + Rez grass and ground cover - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details + A reference to the object where the object resides + The size of the grass + The rotation of the grass + The position of the grass + The type of grass from the enum + The of the group to set the tree to, + or UUID.Zero if no group is to be set - + - Rez an object from inventory + Set the textures to apply to the faces of an object - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The texture data to apply - + - Rez an object from inventory + Set the textures to apply to the faces of an object - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object - User defined queryID to correlate replies - If set to true, the CreateSelected flag - will be set on the rezzed object + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The texture data to apply + A media URL (not used) - + - DeRez an object from the simulator to the agents Objects folder in the agents Inventory + Set the Light data on an object - The simulator Local ID of the object - If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A object containing the data to set - + - DeRez an object from the simulator and return to inventory + Set the flexible data on an object - The simulator Local ID of the object - The type of destination from the enum - The destination inventory folders -or- - if DeRezzing object to a tasks Inventory, the Tasks - The transaction ID for this request which - can be used to correlate this request with other packets - If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A object containing the data to set - + - Rez an item from inventory to its previous simulator location + Set the sculptie texture and data on an object - - - - + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A object containing the data to set - + - Give an inventory item to another avatar + Unset additional primitive parameters on an object - The of the item to give - The name of the item - The type of the item from the enum - The of the recipient - true to generate a beameffect during transfer + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The extra parameters to set - + - Give an inventory Folder with contents to another avatar + Link multiple prims into a linkset - The of the Folder to give - The name of the folder - The type of the item from the enum - The of the recipient - true to generate a beameffect during transfer + A reference to the object where the objects reside + An array which contains the IDs of the objects to link + The last object in the array will be the root object of the linkset TODO: Is this true? - + - Copy or move an from agent inventory to a task (primitive) inventory + Delink/Unlink multiple prims from a linkset - The target object - The item to copy or move from inventory - - For items with copy permissions a copy of the item is placed in the tasks inventory, - for no-copy items the object is moved to the tasks inventory + A reference to the object where the objects reside + An array which contains the IDs of the objects to delink - + - Retrieve a listing of the items contained in a task (Primitive) + Change the rotation of an object - The tasks - The tasks simulator local ID - milliseconds to wait for reply from simulator - A list containing the inventory items inside the task or null - if a timeout occurs - This request blocks until the response from the simulator arrives - or timeoutMS is exceeded + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new rotation of the object - + - Request the contents of a tasks (primitives) inventory from the - current simulator + Set the name of an object - The LocalID of the object - + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A string containing the new name of the object - + - Request the contents of a tasks (primitives) inventory + Set the name of multiple objects - The simulator Local ID of the object - A reference to the simulator object that contains the object - + A reference to the object where the objects reside + An array which contains the IDs of the objects to change the name of + An array which contains the new names of the objects - + - Move an item from a tasks (Primitive) inventory to the specified folder in the avatars inventory + Set the description of an object - LocalID of the object in the simulator - UUID of the task item to move - The ID of the destination folder in this agents inventory - Simulator Object - Raises the event + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A string containing the new description of the object - + - Remove an item from an objects (Prim) Inventory + Set the descriptions of multiple objects - LocalID of the object in the simulator - UUID of the task item to remove - Simulator Object - You can confirm the removal by comparing the tasks inventory serial before and after the - request with the request combined with - the event - - - - Copy an InventoryScript item from the Agents Inventory into a primitives task inventory - - An unsigned integer representing a primitive being simulated - An which represents a script object from the agents inventory - true to set the scripts running state to enabled - A Unique Transaction ID - - The following example shows the basic steps necessary to copy a script from the agents inventory into a tasks inventory - and assumes the script exists in the agents inventory. - - uint primID = 95899503; // Fake prim ID - UUID scriptID = UUID.Parse("92a7fe8a-e949-dd39-a8d8-1681d8673232"); // Fake Script UUID in Inventory - - Client.Inventory.FolderContents(Client.Inventory.FindFolderForType(AssetType.LSLText), Client.Self.AgentID, - false, true, InventorySortOrder.ByName, 10000); - - Client.Inventory.RezScript(primID, (InventoryItem)Client.Inventory.Store[scriptID]); - - + A reference to the object where the objects reside + An array which contains the IDs of the objects to change the description of + An array which contains the new descriptions of the objects - + - Request the running status of a script contained in a task (primitive) inventory + Attach an object to this avatar - The ID of the primitive containing the script - The ID of the script - The event can be used to obtain the results of the - request - + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The point on the avatar the object will be attached + The rotation of the attached object - + - Send a request to set the running state of a script contained in a task (primitive) inventory + Drop an attached object from this avatar - The ID of the primitive containing the script - The ID of the script - true to set the script running, false to stop a running script - To verify the change you can use the method combined - with the event + A reference to the + object where the objects reside. This will always be the simulator the avatar is currently in + + The object's ID which is local to the simulator the object is in - + - Create a CRC from an InventoryItem + Detach an object from yourself - The source InventoryItem - A uint representing the source InventoryItem as a CRC + A reference to the + object where the objects reside + This will always be the simulator the avatar is currently in + + An array which contains the IDs of the objects to detach - + - Reverses a cheesy XORing with a fixed UUID to convert a shadow_id to an asset_id + Change the position of an object, Will change position of entire linkset - Obfuscated shadow_id value - Deobfuscated asset_id value + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new position of the object - + - Does a cheesy XORing with a fixed UUID to convert an asset_id to a shadow_id + Change the position of an object - asset_id value to obfuscate - Obfuscated shadow_id value + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new position of the object + if true, will change position of (this) child prim only, not entire linkset - + - Wrapper for creating a new object + Change the Scale (size) of an object - The type of item from the enum - The of the newly created object - An object with the type and id passed + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new scale of the object + If true, will change scale of this prim only, not entire linkset + True to resize prims uniformly - + - Parse the results of a RequestTaskInventory() response + Change the Rotation of an object that is either a child or a whole linkset - A string which contains the data from the task reply - A List containing the items contained within the tasks inventory - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new scale of the object + If true, will change rotation of this prim only, not entire linkset - + - UpdateCreateInventoryItem packets are received when a new inventory item - is created. This may occur when an object that's rezzed in world is - taken into inventory, when an item is created using the CreateInventoryItem - packet, or when an object is purchased + Send a Multiple Object Update packet to change the size, scale or rotation of a primitive - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Raised when the simulator sends us data containing - ... - - - Raised when the simulator sends us data containing - ... - - - Raised when the simulator sends us data containing - an inventory object sent by another avatar or primitive - - - Raised when the simulator sends us data containing - ... - - - Raised when the simulator sends us data containing - ... - - - Raised when the simulator sends us data containing - ... + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new rotation, size, or position of the target object + The flags from the Enum - - Raised when the simulator sends us data containing - ... + + + Deed an object (prim) to a group, Object must be shared with group which + can be accomplished with SetPermissions() + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The of the group to deed the object to - - Raised when the simulator sends us data containing - ... + + + Deed multiple objects (prims) to a group, Objects must be shared with group which + can be accomplished with SetPermissions() + + A reference to the object where the object resides + An array which contains the IDs of the objects to deed + The of the group to deed the object to - + - Get this agents Inventory data + Set the permissions on multiple objects + A reference to the object where the objects reside + An array which contains the IDs of the objects to set the permissions on + The new Who mask to set + The new Permissions mark to set + TODO: What does this do? - + - Callback for inventory item creation finishing + Request additional properties for an object - Whether the request to create an inventory - item succeeded or not - Inventory item being created. If success is - false this will be null + A reference to the object where the object resides + + - + - Callback for an inventory item being create from an uploaded asset + Request additional properties for an object - true if inventory item creation was successful - - - + A reference to the object where the object resides + Absolute UUID of the object + Whether to require server acknowledgement of this request - + - + Set the ownership of a list of objects to the specified group - + A reference to the object where the objects reside + An array which contains the IDs of the objects to set the group id on + The Groups ID - + - Reply received when uploading an inventory asset + Update current URL of the previously set prim media - Has upload been successful - Error message if upload failed - Inventory asset UUID - New asset UUID + UUID of the prim + Set current URL to this + Prim face number + Simulator in which prim is located - + - Delegate that is invoked when script upload is completed + Set object media - Has upload succeded (note, there still might be compile errors) - Upload status message - Is compilation successful - If compilation failed, list of error messages, null on compilation success - Script inventory UUID - Script's new asset UUID - - - Set to true to accept offer, false to decline it - - - The folder to accept the inventory into, if null default folder for will be used + UUID of the prim + Array the length of prims number of faces. Null on face indexes where there is + no media, on faces which contain the media + Simulatior in which prim is located - + - Callback when an inventory object is accepted and received from a - task inventory. This is the callback in which you actually get - the ItemID, as in ObjectOfferedCallback it is null when received - from a task. + Retrieve information about object media + UUID of the primitive + Simulator where prim is located + Call this callback when done - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + - Holds group information for Avatars such as those you might find in a profile + A terse object update, used when a transformation matrix or + velocity/acceleration for an object changes but nothing else + (scale/position/rotation/acceleration/velocity) + The sender + The EventArgs object containing the packet data - - true of Avatar accepts group notices - - - Groups Key + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Texture Key for groups insignia + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Name of the group + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Powers avatar has in the group + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Avatars Currently selected title + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - true of Avatar has chosen to list this in their profile + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - Contains an animation currently being played by an agent + Setup construction data for a basic primitive shape + Primitive shape to construct + Construction data that can be plugged into a - - The ID of the animation asset - - - A number to indicate start order of currently playing animations - On Linden Grids this number is unique per region, with OpenSim it is per client - - - - - + - Holds group information on an individual profile pick + + + + + + + + - + - Retrieve friend status notifications, and retrieve avatar names and - profiles + + + + - - The event subscribers, null of no subscribers - - - Raises the AvatarAnimation Event - An AvatarAnimationEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - The event subscribers, null of no subscribers - - - Raises the AvatarAppearance Event - A AvatarAppearanceEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - The event subscribers, null of no subscribers - - - Raises the UUIDNameReply Event - A UUIDNameReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - The event subscribers, null of no subscribers - - - Raises the AvatarInterestsReply Event - A AvatarInterestsReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - The event subscribers, null of no subscribers - - - Raises the AvatarPropertiesReply Event - A AvatarPropertiesReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object + + + Set the Shape data of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + Data describing the prim shape - - The event subscribers, null of no subscribers + + + Set the Material data of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new material of the object - - Raises the AvatarGroupsReply Event - A AvatarGroupsReplyEventArgs object containing - the data sent from the simulator + + + + + + + + + + + - - Thread sync lock object + + + + + + + + + + + - - The event subscribers, null of no subscribers + + Provides data for the event + + The event occurs when the simulator sends + an containing a Primitive, Foliage or Attachment data + Note 1: The event will not be raised when the object is an Avatar + Note 2: It is possible for the to be + raised twice for the same object if for example the primitive moved to a new simulator, then returned to the current simulator or + if an Avatar crosses the border into a new simulator and returns to the current simulator + + + The following code example uses the , , and + properties to display new Primitives and Attachments on the window. + + // Subscribe to the event that gives us prim and foliage information + Client.Objects.ObjectUpdate += Objects_ObjectUpdate; + private void Objects_ObjectUpdate(object sender, PrimEventArgs e) + { + Console.WriteLine("Primitive {0} {1} in {2} is an attachment {3}", e.Prim.ID, e.Prim.LocalID, e.Simulator.Name, e.IsAttachment); + } + + + + - - Raises the AvatarPickerReply Event - A AvatarPickerReplyEventArgs object containing - the data sent from the simulator + + + Construct a new instance of the PrimEventArgs class + + The simulator the object originated from + The Primitive + The simulator time dilation + The prim was not in the dictionary before this update + true if the primitive represents an attachment to an agent - - Thread sync lock object + + Get the simulator the originated from - - The event subscribers, null of no subscribers + + Get the details - - Raises the ViewerEffectPointAt Event - A ViewerEffectPointAtEventArgs object containing - the data sent from the simulator + + true if the did not exist in the dictionary before this update (always true if object tracking has been disabled) - - Thread sync lock object + + true if the is attached to an - - The event subscribers, null of no subscribers + + Get the simulator Time Dilation - - Raises the ViewerEffectLookAt Event - A ViewerEffectLookAtEventArgs object containing - the data sent from the simulator + + Provides data for the event + + The event occurs when the simulator sends + an containing Avatar data + Note 1: The event will not be raised when the object is an Avatar + Note 2: It is possible for the to be + raised twice for the same avatar if for example the avatar moved to a new simulator, then returned to the current simulator + + + The following code example uses the property to make a request for the top picks + using the method in the class to display the names + of our own agents picks listings on the window. + + // subscribe to the AvatarUpdate event to get our information + Client.Objects.AvatarUpdate += Objects_AvatarUpdate; + Client.Avatars.AvatarPicksReply += Avatars_AvatarPicksReply; + private void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e) + { + // we only want our own data + if (e.Avatar.LocalID == Client.Self.LocalID) + { + // Unsubscribe from the avatar update event to prevent a loop + // where we continually request the picks every time we get an update for ourselves + Client.Objects.AvatarUpdate -= Objects_AvatarUpdate; + // make the top picks request through AvatarManager + Client.Avatars.RequestAvatarPicks(e.Avatar.ID); + } + } + private void Avatars_AvatarPicksReply(object sender, AvatarPicksReplyEventArgs e) + { + // we'll unsubscribe from the AvatarPicksReply event since we now have the data + // we were looking for + Client.Avatars.AvatarPicksReply -= Avatars_AvatarPicksReply; + // loop through the dictionary and extract the names of the top picks from our profile + foreach (var pickName in e.Picks.Values) + { + Console.WriteLine(pickName); + } + } + + + - - Thread sync lock object + + + Construct a new instance of the AvatarUpdateEventArgs class + + The simulator the packet originated from + The data + The simulator time dilation + The avatar was not in the dictionary before this update - - The event subscribers, null of no subscribers + + Get the simulator the object originated from - - Raises the ViewerEffect Event - A ViewerEffectEventArgs object containing - the data sent from the simulator + + Get the data - - Thread sync lock object + + Get the simulator time dilation - - The event subscribers, null of no subscribers + + true if the did not exist in the dictionary before this update (always true if avatar tracking has been disabled) - - Raises the AvatarPicksReply Event - A AvatarPicksReplyEventArgs object containing - the data sent from the simulator + + Provides additional primitive data for the event + + The event occurs when the simulator sends + an containing additional details for a Primitive, Foliage data or Attachment data + The event is also raised when a request is + made. + + + The following code example uses the , and + + properties to display new attachments and send a request for additional properties containing the name of the + attachment then display it on the window. + + // Subscribe to the event that provides additional primitive details + Client.Objects.ObjectProperties += Objects_ObjectProperties; + // handle the properties data that arrives + private void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e) + { + Console.WriteLine("Primitive Properties: {0} Name is {1}", e.Properties.ObjectID, e.Properties.Name); + } + - - Thread sync lock object + + + Construct a new instance of the ObjectPropertiesEventArgs class + + The simulator the object is located + The primitive Properties - - The event subscribers, null of no subscribers + + Get the simulator the object is located - - Raises the PickInfoReply Event - A PickInfoReplyEventArgs object containing - the data sent from the simulator + + Get the primitive properties - - Thread sync lock object + + Provides additional primitive data for the event + + The event occurs when the simulator sends + an containing additional details for a Primitive or Foliage data that is currently + being tracked in the dictionary + The event is also raised when a request is + made and is enabled + - - The event subscribers, null of no subscribers + + + Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class + + The simulator the object is located + The Primitive + The primitive Properties - - Raises the AvatarClassifiedReply Event - A AvatarClassifiedReplyEventArgs object containing - the data sent from the simulator + + Get the simulator the object is located - - Thread sync lock object + + Get the primitive details - - The event subscribers, null of no subscribers + + Get the primitive properties - - Raises the ClassifiedInfoReply Event - A ClassifiedInfoReplyEventArgs object containing - the data sent from the simulator + + Provides additional primitive data, permissions and sale info for the event + + The event occurs when the simulator sends + an containing additional details for a Primitive, Foliage data or Attachment. This includes + Permissions, Sale info, and other basic details on an object + The event is also raised when a request is + made, the viewer equivalent is hovering the mouse cursor over an object + - - Thread sync lock object + + Get the simulator the object is located - + - Represents other avatars - - - - Tracks the specified avatar on your map - Avatar ID to track - + - Request a single avatar name - The avatar key to retrieve a name for - + + Provides primitive data containing updated location, velocity, rotation, textures for the event + + The event occurs when the simulator sends updated location, velocity, rotation, etc + + + + Get the simulator the object is located + + + Get the primitive details + + - Request a list of avatar names - The avatar keys to retrieve names for - + - Start a request for Avatar Properties - - + - Search for an avatar (first name, last name) - The name to search for - An ID to associate with this query - + + Get the simulator the object is located + + + Get the primitive details + + - Start a request for Avatar Picks - UUID of the avatar - + - Start a request for Avatar Classifieds - UUID of the avatar - + - Start a request for details of a specific profile pick - UUID of the avatar - UUID of the profile pick - + - Start a request for details of a specific profile classified - UUID of the avatar - UUID of the profile classified - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the + event - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Get the simulator the object is located - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The LocalID of the object - + - Crossed region handler for message that comes across the EventQueue. Sent to an agent - when the agent crosses a sim border into a new region. + Provides updates sit position data - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Get the simulator the object is located - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + - - Raised when the simulator sends us data containing - an agents animation playlist + + + - - Raised when the simulator sends us data containing - the appearance information for an agent + + + - - Raised when the simulator sends us data containing - agent names/id values + + Get the simulator the object is located - - Raised when the simulator sends us data containing - the interests listed in an agents profile + + + - - Raised when the simulator sends us data containing - profile property information for an agent + + + - - Raised when the simulator sends us data containing - the group membership an agent is a member of + + + - - Raised when the simulator sends us data containing - name/id pair + + + Indicates if the operation was successful + - - Raised when the simulator sends us data containing - the objects and effect when an agent is pointing at + + + Media version string + - - Raised when the simulator sends us data containing - the objects and effect when an agent is looking at + + + Array of media entries indexed by face number + - - Raised when the simulator sends us data containing - an agents viewer effect information + + + Create an allocated UDP packet buffer for receiving a packet + - - Raised when the simulator sends us data containing - the top picks from an agents profile + + + Create an allocated UDP packet buffer for sending a packet + + EndPoint of the remote host - - Raised when the simulator sends us data containing - the Pick details + + + Create an allocated UDP packet buffer for sending a packet + + EndPoint of the remote host + Size of the buffer to allocate for packet data - - Raised when the simulator sends us data containing - the classified ads an agent has placed + + Size of the byte array used to store raw packet data - - Raised when the simulator sends us data containing - the details of a classified ad + + Raw packet data buffer - - Provides data for the event - The event occurs when the simulator sends - the animation playlist for an agent - - The following code example uses the and - properties to display the animation playlist of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAnimation += Avatars_AvatarAnimation; - - private void Avatars_AvatarAnimation(object sender, AvatarAnimationEventArgs e) - { - // create a dictionary of "known" animations from the Animations class using System.Reflection - Dictionary<UUID, string> systemAnimations = new Dictionary<UUID, string>(); - Type type = typeof(Animations); - System.Reflection.FieldInfo[] fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); - foreach (System.Reflection.FieldInfo field in fields) - { - systemAnimations.Add((UUID)field.GetValue(type), field.Name); - } - - // find out which animations being played are known animations and which are assets - foreach (Animation animation in e.Animations) - { - if (systemAnimations.ContainsKey(animation.AnimationID)) - { - Console.WriteLine("{0} is playing {1} ({2}) sequence {3}", e.AvatarID, - systemAnimations[animation.AnimationID], animation.AnimationSequence); - } - else - { - Console.WriteLine("{0} is playing {1} (Asset) sequence {2}", e.AvatarID, - animation.AnimationID, animation.AnimationSequence); - } - } - } - - + + Length of the data to transmit - + + EndPoint of the remote host + + - Construct a new instance of the AvatarAnimationEventArgs class + Object pool for packet buffers. This is used to allocate memory for all + incoming and outgoing packets, and zerocoding buffers for those packets - The ID of the agent - The list of animations to start - - - Get the ID of the agent - - Get the list of animations to start - - - Provides data for the event - The event occurs when the simulator sends - the appearance data for an avatar - - The following code example uses the and - properties to display the selected shape of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; - - // handle the data when the event is raised - void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) - { - Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") - } - - + + + Initialize the object pool in client mode + + Server to connect to + + + + - + - Construct a new instance of the AvatarAppearanceEventArgs class + Initialize the object pool in server mode - The ID of the agent - true of the agent is a trial account - The default agent texture - The agents appearance layer textures - The for the agent + + + + - - Get the ID of the agent + + + Returns a packet buffer with EndPoint set if the buffer is in + client mode, or with EndPoint set to null in server mode + + Initialized UDPPacketBuffer object - - true if the agent is a trial account + + + Default constructor + - - Get the default agent texture + + + Check a packet buffer out of the pool + + A packet buffer object - - Get the agents appearance layer textures + + + Returns an instance of the class that has been checked out of the Object Pool. + - - Get the for the agent + + + Checks the instance back into the object pool + - - Represents the interests from the profile of an agent + + + Creates a new instance of the ObjectPoolBase class. Initialize MUST be called + after using this constructor. + - - Get the ID of the agent + + + Creates a new instance of the ObjectPool Base class. + + The object pool is composed of segments, which + are allocated whenever the size of the pool is exceeded. The number of items + in a segment should be large enough that allocating a new segmeng is a rare + thing. For example, on a server that will have 10k people logged in at once, + the receive buffer object pool should have segment sizes of at least 1000 + byte arrays per segment. + + The minimun number of segments that may exist. + Perform a full GC.Collect whenever a segment is allocated, and then again after allocation to compact the heap. + The frequency which segments are checked to see if they're eligible for cleanup. - - The properties of an agent + + + The total number of segments created. Intended to be used by the Unit Tests. + - - Get the ID of the agent + + + The number of items that are in a segment. Items in a segment + are all allocated at the same time, and are hopefully close to + each other in the managed heap. + - - Get the ID of the agent + + + The minimum number of segments. When segments are reclaimed, + this number of segments will always be left alone. These + segments are allocated at startup. + - - Get the ID of the agent + + + The age a segment must be before it's eligible for cleanup. + This is used to prevent thrash, and typical values are in + the 5 minute range. + - - Get the ID of the avatar + + + The frequence which the cleanup thread runs. This is typically + expected to be in the 5 minute range. + - + - Sent to the client to indicate a teleport request has completed + Forces the segment cleanup algorithm to be run. This method is intended + primarly for use from the Unit Test libraries. - - The of the agent + + + Responsible for allocate 1 instance of an object that will be stored in a segment. + + An instance of whatever objec the pool is pooling. - - + + + Checks in an instance of T owned by the object pool. This method is only intended to be called + by the WrappedObject class. + + The segment from which the instance is checked out. + The instance of T to check back into the segment. - - The simulators handle the agent teleported to + + + Checks an instance of T from the pool. If the pool is not sufficient to + allow the checkout, a new segment is created. + + A WrappedObject around the instance of T. To check + the instance back into the segment, be sureto dispose the WrappedObject + when finished. - - A Uri which contains a list of Capabilities the simulator supports + + + - - Indicates the level of access required - to access the simulator, or the content rating, or the simulators - map status + + + - - The IP Address of the simulator + + + - - The UDP Port the simulator will listen for UDP traffic on + + + - - Status flags indicating the state of the Agent upon arrival, Flying, etc. + + + The ObservableDictionary class is used for storing key/value pairs. It has methods for firing + events to subscribers when items are added, removed, or changed. + + Key + Value - + - Serialize the object + Initializes a new instance of the Class + with the specified key/value, has the default initial capacity. - An containing the objects data + + + // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value. + public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(); + + - + - Deserialize the message + Initializes a new instance of the Class + with the specified key/value, With its initial capacity specified. - An containing the data + Initial size of dictionary + + + // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value, + // initially allocated room for 10 entries. + public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(10); + + - + - Sent to the viewer when a neighboring simulator is requesting the agent make a connection to it. + A dictionary of callbacks to fire when specified action occurs - + + Internal dictionary that this class wraps around. Do not + modify or enumerate the contents of this dictionary without locking + + - Serialize the object + Indexer for the dictionary - An containing the objects data + The key + The value - + - Deserialize the message - - An containing the data + Gets the number of Key/Value pairs contained in the - + - Serialize the object + Register a callback to be fired when an action occurs - An containing the objects data + The action + The callback to fire - + - Deserialize the message + Unregister a callback - An containing the data + The action + The callback to fire - + - Serialize the object - An containing the objects data + + + + - + - Deserialize the message + Try to get entry from the with specified key - An containing the data + Key to use for lookup + Value returned + + if specified key exists, if not found + + + // find your avatar using the Simulator.ObjectsAvatars ObservableDictionary: + Avatar av; + if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) + Console.WriteLine("Found Avatar {0}", av.Name); + + + - + - A message sent to the client which indicates a teleport request has failed - and contains some information on why it failed + Finds the specified match. + The match. + Matched value + + + // use a delegate to find a prim in the ObjectsPrimitives ObservableDictionary + // with the ID 95683496 + uint findID = 95683496; + Primitive findPrim = sim.ObjectsPrimitives.Find( + delegate(Primitive prim) { return prim.ID == findID; }); + + - - + + Find All items in an + return matching items. + a containing found items. + + Find All prims within 20 meters and store them in a List + + int radius = 20; + List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( + delegate(Primitive prim) { + Vector3 pos = prim.Position; + return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); + } + ); + - - A string key of the reason the teleport failed e.g. CouldntTPCloser - Which could be used to look up a value in a dictionary or enum + + Find All items in an + return matching keys. + a containing found keys. + + Find All keys which also exist in another dictionary + + List<UUID> matches = myDict.FindAll( + delegate(UUID id) { + return myOtherDict.ContainsKey(id); + } + ); + - - The of the Agent + + Check if Key exists in Dictionary + Key to check for + + if found, otherwise - - A string human readable message containing the reason - An example: Could not teleport closer to destination + + Check if Value exists in Dictionary + Value to check for + + if found, otherwise - + - Serialize the object - - An containing the objects data + Adds the specified key to the dictionary, dictionary locking is not performed, + + The key + The value - + - Deserialize the message + Removes the specified key, dictionary locking is not performed - An containing the data + The key. + + if successful, otherwise - + - Serialize the object + Clear the contents of the dictionary - An containing the objects data - + - Deserialize the message + Enumerator for iterating dictionary entries - An containing the data + + - + - Contains a list of prim owner information for a specific parcel in a simulator + A custom decoder callback - - A Simulator will always return at least 1 entry - If agent does not have proper permission the OwnerID will be UUID.Zero - If agent does not have proper permission OR there are no primitives on parcel - the DataBlocksExtended map will not be sent from the simulator - - - - An Array of objects + The key of the object + the data to decode + A string represending the fieldData - + - Serialize the object + Add a custom decoder callback - An containing the objects data + The key of the field to decode + The custom decode handler - + - Deserialize the message + Remove a custom decoder callback - An containing the data + The key of the field to decode + The custom decode handler - + - Prim ownership information for a specified owner on a single parcel + Creates a formatted string containing the values of a Packet + The Packet + A formatted string of values of the nested items in the Packet object - - The of the prim owner, - UUID.Zero if agent has no permission to view prim owner information - - - The total number of prims - - - True if the OwnerID is a - - - True if the owner is online - This is no longer used by the LL Simulators - - - The date the most recent prim was rezzed - - + - The details of a single parcel in a region, also contains some regionwide globals + Decode an IMessage object into a beautifully formatted string + The IMessage object + Recursion level (used for indenting) + A formatted string containing the names and values of the source object - - Simulator-local ID of this parcel - - - Maximum corner of the axis-aligned bounding box for this - parcel - - - Minimum corner of the axis-aligned bounding box for this - parcel - - - Total parcel land area - - - - - - Key of authorized buyer - - - Bitmap describing land layout in 4x4m squares across the - entire region - - - - - - Date land was claimed - - - Appears to always be zero - - - Parcel Description - - - - - - + + + Type of return to use when returning objects from a parcel + - - Total number of primitives owned by the parcel group on - this parcel + + + - - Whether the land is deeded to a group or not + + Return objects owned by parcel owner - - + + Return objects set to group - - Maximum number of primitives this parcel supports + + Return objects not owned by parcel owner or set to group - - The Asset UUID of the Texture which when applied to a - primitive will display the media + + Return a specific list of objects on parcel - - A URL which points to any Quicktime supported media type + + Return objects that are marked for-sale - - A byte, if 0x1 viewer should auto scale media to fit object + + + Blacklist/Whitelist flags used in parcels Access List + - - URL For Music Stream + + Agent is denied access - - Parcel Name + + Agent is granted access - - Autoreturn value in minutes for others' objects + + + The result of a request for parcel properties + - - + + No matches were found for the request - - Total number of other primitives on this parcel + + Request matched a single parcel - - UUID of the owner of this parcel + + Request matched multiple parcels - - Total number of primitives owned by the parcel owner on - this parcel + + + Flags used in the ParcelAccessListRequest packet to specify whether + we want the access list (whitelist), ban list (blacklist), or both + - - + + Request the access list - - How long is pass valid for + + Request the ban list - - Price for a temporary pass + + Request both White and Black lists - - + + + Sequence ID in ParcelPropertiesReply packets (sent when avatar + tries to cross a parcel border) + - - + + Parcel is currently selected - - + + Parcel restricted to a group the avatar is not a + member of - - This field is no longer used + + Avatar is banned from the parcel - - The result of a request for parcel properties + + Parcel is restricted to an access list that the + avatar is not on - - Sale price of the parcel, only useful if ForSale is set - The SalePrice will remain the same after an ownership - transfer (sale), so it can be used to see the purchase price after - a sale if the new owner has not changed it + + Response to hovering over a parcel - + - Number of primitives your avatar is currently - selecting and sitting on in this parcel + The tool to use when modifying terrain levels - - - - - - A number which increments by 1, starting at 0 for each ParcelProperties request. - Can be overriden by specifying the sequenceID with the ParcelPropertiesRequest being sent. - a Negative number indicates the action in has occurred. - + + Level the terrain - - Maximum primitives across the entire simulator + + Raise the terrain - - Total primitives across the entire simulator + + Lower the terrain - - + + Smooth the terrain - - Key of parcel snapshot + + Add random noise to the terrain - - Parcel ownership status + + Revert terrain to simulator default - - Total number of primitives on this parcel + + + The tool size to use when changing terrain levels + - - + + Small - - + + Medium - - TRUE of region denies access to age unverified users + + Large - - A description of the media + + + Reasons agent is denied access to a parcel on the simulator + - - An Integer which represents the height of the media + + Agent is not denied, access is granted - - An integer which represents the width of the media + + Agent is not a member of the group set for the parcel, or which owns the parcel - - A boolean, if true the viewer should loop the media + + Agent is not on the parcels specific allow list - - A string which contains the mime type of the media + + Agent is on the parcels ban list - - true to obscure (hide) media url + + Unknown - - true to obscure (hide) music url + + Agent is not age verified and parcel settings deny access to non age verified avatars - + - Serialize the object + Parcel overlay type. This is used primarily for highlighting and + coloring which is why it is a single integer instead of a set of + flags - An containing the objects data + These values seem to be poorly thought out. The first three + bits represent a single value, not flags. For example Auction (0x05) is + not a combination of OwnedByOther (0x01) and ForSale(0x04). However, + the BorderWest and BorderSouth values are bit flags that get attached + to the value stored in the first three bits. Bits four, five, and six + are unused - - - Deserialize the message - - An containing the data + + Public land - - A message sent from the viewer to the simulator to updated a specific parcels settings + + Land is owned by another avatar - - The of the agent authorized to purchase this - parcel of land or a NULL if the sale is authorized to anyone + + Land is owned by a group - - true to enable auto scaling of the parcel media + + Land is owned by the current avatar - - The category of this parcel used when search is enabled to restrict - search results + + Land is for sale - - A string containing the description to set + + Land is being auctioned - - The of the which allows for additional - powers and restrictions. + + To the west of this area is a parcel border - - The which specifies how avatars which teleport - to this parcel are handled + + To the south of this area is a parcel border - - The LocalID of the parcel to update settings on + + + Various parcel properties + - - A string containing the description of the media which can be played - to visitors + + No flags set - - + + Allow avatars to fly (a client-side only restriction) - - + + Allow foreign scripts to run - - + + This parcel is for sale - - + + Allow avatars to create a landmark on this parcel - - + + Allows all avatars to edit the terrain on this parcel - - + + Avatars have health and can take damage on this parcel. + If set, avatars can be killed and sent home here - - + + Foreign avatars can create objects here - - + + All objects on this parcel can be purchased - - + + Access is restricted to a group - - + + Access is restricted to a whitelist - - + + Ban blacklist is enabled - - + + Unknown - - + + List this parcel in the search directory - - + + Allow personally owned parcels to be deeded to group - - + + If Deeded, owner contributes required tier to group parcel is deeded to - - + + Restrict sounds originating on this parcel to the + parcel boundaries - - + + Objects on this parcel are sold when the land is + purchsaed - - - Deserialize the message - - An containing the data + + Allow this parcel to be published on the web - - - Serialize the object - - An containing the objects data + + The information for this parcel is mature content - - Base class used for the RemoteParcelRequest message + + The media URL is an HTML page - - - A message sent from the viewer to the simulator to request information - on a remote parcel - + + The media URL is a raw HTML string - - Local sim position of the parcel we are looking up + + Restrict foreign object pushes - - Region handle of the parcel we are looking up + + Ban all non identified/transacted avatars - - Region of the parcel we are looking up + + Allow group-owned scripts to run - - - Serialize the object - - An containing the objects data + + Allow object creation by group members or group + objects - - - Deserialize the message - - An containing the data + + Allow all objects to enter this parcel - - - A message sent from the simulator to the viewer in response to a - which will contain parcel information - + + Only allow group and owner objects to enter this parcel - - The grid-wide unique parcel ID + + Voice Enabled on this parcel - - - Serialize the object - - An containing the objects data + + Use Estate Voice channel for Voice on this parcel - - - Deserialize the message - - An containing the data + + Deny Age Unverified Users - + - A message containing a request for a remote parcel from a viewer, or a response - from the simulator to that request + Parcel ownership status - - The request or response details block + + Placeholder - - - Serialize the object - - An containing the objects data + + Parcel is leased (owned) by an avatar or group - - - Deserialize the message - - An containing the data + + Parcel is in process of being leased (purchased) by an avatar or group - - - Serialize the object - - An containing the objects data + + Parcel has been abandoned back to Governor Linden - + - Deserialize the message + Category parcel is listed in under search - An containing the data - - - A message sent from the simulator to an agent which contains - the groups the agent is in - + + No assigned category - - The Agent receiving the message + + Linden Infohub or public area - - An array containing information - for each the agent is a member of + + Adult themed area - - An array containing information - for each the agent is a member of + + Arts and Culture - - - Serialize the object - - An containing the objects data + + Business - - - Deserialize the message - - An containing the data + + Educational - - Group Details specific to the agent + + Gaming - - true of the agent accepts group notices + + Hangout or Club - - The agents tier contribution to the group + + Newcomer friendly - - The Groups + + Parks and Nature - - The of the groups insignia + + Residential - - The name of the group + + Shopping - - The aggregate permissions the agent has in the group for all roles the agent - is assigned + + Not Used? - - An optional block containing additional agent specific information + + Other - - true of the agent allows this group to be - listed in their profile + + Not an actual category, only used for queries - + - A message sent from the viewer to the simulator which - specifies the language and permissions for others to detect - the language specified + Type of teleport landing for a parcel - - A string containng the default language - to use for the agent + + Unset, simulator default - - true of others are allowed to - know the language setting + + Specific landing point set for this parcel - - - Serialize the object - - An containing the objects data + + No landing point set, direct teleports enabled for + this parcel - + - Deserialize the message + Parcel Media Command used in ParcelMediaCommandMessage - An containing the data - - - An EventQueue message sent from the simulator to an agent when the agent - leaves a group - + + Stop the media stream and go back to the first frame - - - An Array containing the AgentID and GroupID - + + Pause the media stream (stop playing but stay on current frame) - - - Serialize the object - - An containing the objects data + + Start the current media stream playing and stop when the end is reached - - - Deserialize the message - - An containing the data + + Start the current media stream playing, + loop to the beginning when the end is reached and continue to play - - An object containing the Agents UUID, and the Groups UUID + + Specifies the texture to replace with video + If passing the key of a texture, it must be explicitly typecast as a key, + not just passed within double quotes. - - The ID of the Agent leaving the group + + Specifies the movie URL (254 characters max) - - The GroupID the Agent is leaving + + Specifies the time index at which to begin playing - - Base class for Asset uploads/results via Capabilities + + Specifies a single agent to apply the media command to - - - The request state - + + Unloads the stream. While the stop command sets the texture to the first frame of the movie, + unload resets it to the real texture that the movie was replacing. - - - Serialize the object - - An containing the objects data + + Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties + (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter. - - - Deserialize the message - - An containing the data + + Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only). + Use "text/html" for HTML. - - - A message sent from the viewer to the simulator to request a temporary upload capability - which allows an asset to be uploaded - + + Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only). + This might still not be working - - The Capability URL sent by the simulator to upload the baked texture to + + Sets a description for the media being displayed (1.19.1 RC0 and later only). - + - A message sent from the simulator that will inform the agent the upload is complete, - and the UUID of the uploaded asset + Some information about a parcel of land returned from a DirectoryManager search - - The uploaded texture asset ID + + Global Key of record - - - A message sent from the viewer to the simulator to request a temporary - capability URI which is used to upload an agents baked appearance textures - + + Parcel Owners - - Object containing request or response + + Name field of parcel, limited to 128 characters - - - Serialize the object - - An containing the objects data + + Description field of parcel, limited to 256 characters - - - Deserialize the message - - An containing the data + + Total Square meters of parcel - - - A message sent from the simulator which indicates the minimum version required for - using voice chat - + + Total area billable as Tier, for group owned land this will be 10% less than ActualArea - - Major Version Required + + True of parcel is in Mature simulator - - Minor version required + + Grid global X position of parcel - - The name of the region sending the version requrements + + Grid global Y position of parcel - - - Serialize the object - - An containing the objects data + + Grid global Z position of parcel (not used) - - - Deserialize the message - - An containing the data + + Name of simulator parcel is located in - - - A message sent from the simulator to the viewer containing the - voice server URI - + + Texture of parcels display picture - - The Parcel ID which the voice server URI applies + + Float representing calculated traffic based on time spent on parcel by avatars - - The name of the region + + Sale price of parcel (not used) - - A uri containing the server/channel information - which the viewer can utilize to participate in voice conversations + + Auction ID of parcel - + - Serialize the object + Parcel Media Information - An containing the objects data - - - Deserialize the message - - An containing the data + + A byte, if 0x1 viewer should auto scale media to fit object - - - - + + A boolean, if true the viewer should loop the media - - + + The Asset UUID of the Texture which when applied to a + primitive will display the media - - + + A URL which points to any Quicktime supported media type - - - Serialize the object - - An containing the objects data + + A description of the media - - - Deserialize the message - - An containing the data + + An Integer which represents the height of the media - - - A message sent by the viewer to the simulator to request a temporary - capability for a script contained with in a Tasks inventory to be updated - + + An integer which represents the width of the media - - Object containing request or response + + A string which contains the mime type of the media - + - Serialize the object + Parcel of land, a portion of virtual real estate in a simulator - An containing the objects data - + - Deserialize the message + Defalt constructor - An containing the data + Local ID of this parcel - - - A message sent from the simulator to the viewer to indicate - a Tasks scripts status. - + + The total number of contiguous 4x4 meter blocks your agent owns within this parcel - - The Asset ID of the script + + The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own - - True of the script is compiled/ran using the mono interpreter, false indicates it - uses the older less efficient lsl2 interprter + + Deprecated, Value appears to always be 0 - - The Task containing the scripts + + Simulator-local ID of this parcel - - true of the script is in a running state + + UUID of the owner of this parcel - - - Serialize the object - - An containing the objects data + + Whether the land is deeded to a group or not - + - Deserialize the message - An containing the data - - - A message containing the request/response used for updating a gesture - contained with an agents inventory - + + Date land was claimed - - Object containing request or response + + Appears to always be zero - - - Serialize the object - - An containing the objects data + + This field is no longer used - - - Deserialize the message - - An containing the data + + Minimum corner of the axis-aligned bounding box for this + parcel - - - A message request/response which is used to update a notecard contained within - a tasks inventory - + + Maximum corner of the axis-aligned bounding box for this + parcel - - The of the Task containing the notecard asset to update + + Bitmap describing land layout in 4x4m squares across the + entire region - - The notecard assets contained in the tasks inventory + + Total parcel land area - + - Serialize the object - An containing the objects data - - - Deserialize the message - - An containing the data + + Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used - - - A reusable class containing a message sent from the viewer to the simulator to request a temporary uploader capability - which is used to update an asset in an agents inventory - + + Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel + owned by the agent or group that owns this parcel - - - The Notecard AssetID to replace - + + Maximum number of primitives this parcel supports - - - Serialize the object - - An containing the objects data + + Total number of primitives on this parcel - - - Deserialize the message - - An containing the data + + For group-owned parcels this indicates the total number of prims deeded to the group, + for parcels owned by an individual this inicates the number of prims owned by the individual - - - A message containing the request/response used for updating a notecard - contained with an agents inventory - + + Total number of primitives owned by the parcel group on + this parcel, or for parcels owned by an individual with a group set the + total number of prims set to that group. - - Object containing request or response + + Total number of prims owned by other avatars that are not set to group, or not the parcel owner - - - Serialize the object - - An containing the objects data + + A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect + the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed - - - Deserialize the message - - An containing the data + + Autoreturn value in minutes for others' objects - + - Serialize the object - An containing the objects data - - - Deserialize the message - - An containing the data + + Sale price of the parcel, only useful if ForSale is set + The SalePrice will remain the same after an ownership + transfer (sale), so it can be used to see the purchase price after + a sale if the new owner has not changed it - + + Parcel Name + + + Parcel Description + + + URL For Music Stream + + - A message sent from the simulator to the viewer which indicates - an error occurred while attempting to update a script in an agents or tasks - inventory - - true of the script was successfully compiled by the simulator - - - A string containing the error which occured while trying - to update the script + + Price for a temporary pass - - A new AssetID assigned to the script + + How long is pass valid for - + - A message sent from the viewer to the simulator - requesting the update of an existing script contained - within a tasks inventory - - if true, set the script mode to running + + Key of authorized buyer - - The scripts InventoryItem ItemID to update + + Key of parcel snapshot - - A lowercase string containing either "mono" or "lsl2" which - specifies the script is compiled and ran on the mono runtime, or the older - lsl runtime + + The landing point location - - The tasks which contains the script to update + + The landing point LookAt - + + The type of landing enforced from the enum + + - Serialize the object - An containing the objects data - + - Deserialize the message - An containing the data - + - A message containing either the request or response used in updating a script inside - a tasks inventory - - Object containing request or response + + Access list of who is whitelisted on this + parcel - - - Serialize the object - - An containing the objects data + + Access list of who is blacklisted on this + parcel - - - Deserialize the message - - An containing the data + + TRUE of region denies access to age unverified users - - - Response from the simulator to notify the viewer the upload is completed, and - the UUID of the script asset and its compiled status - + + true to obscure (hide) media url - - The uploaded texture asset ID + + true to obscure (hide) music url - - true of the script was compiled successfully + + A struct containing media details - + - A message sent from a viewer to the simulator requesting a temporary uploader capability - used to update a script contained in an agents inventory + Displays a parcel object in string format + string containing key=value pairs of a parcel object - - The existing asset if of the script in the agents inventory to replace - - - The language of the script - Defaults to lsl version 2, "mono" might be another possible option - - + - Serialize the object + Update the simulator with any local changes to this Parcel object - An containing the objects data + Simulator to send updates to + Whether we want the simulator to confirm + the update with a reply packet or not - + - Deserialize the message + Set Autoreturn time - An containing the data + Simulator to send the update to - + - A message containing either the request or response used in updating a script inside - an agents inventory + Parcel (subdivided simulator lots) subsystem - - Object containing request or response - - + - Serialize the object + Default constructor - An containing the objects data + A reference to the GridClient object - + - Deserialize the message + Parcel Accesslist - An containing the data - + + Agents + + - Serialize the object - An containing the objects data - + + Flags for specific entry in white/black lists + + - Deserialize the message + Owners of primitives on parcel - An containing the data - - Base class for Map Layers via Capabilities + + Prim Owners - - + + True of owner is group - - - Serialize the object - - An containing the objects data + + Total count of prims owned by OwnerID - - - Deserialize the message - - An containing the data + + true of OwnerID is currently online and is not a group - - - Sent by an agent to the capabilities server to request map layers - + + The date of the most recent prim left by OwnerID - + - A message sent from the simulator to the viewer which contains an array of map images and their grid coordinates + Called once parcel resource usage information has been collected + Indicates if operation was successfull + Parcel resource usage information - - An array containing LayerData items + + The event subscribers. null if no subcribers - - - Serialize the object - - An containing the objects data + + Thread sync lock object - - - Deserialize the message - - An containing the data + + The event subscribers. null if no subcribers - - - An object containing map location details - + + Thread sync lock object - - The Asset ID of the regions tile overlay + + The event subscribers. null if no subcribers - - The grid location of the southern border of the map tile + + Thread sync lock object - - The grid location of the western border of the map tile + + The event subscribers. null if no subcribers - - The grid location of the eastern border of the map tile + + Thread sync lock object - - The grid location of the northern border of the map tile + + The event subscribers. null if no subcribers - - Object containing request or response + + Thread sync lock object - - - Serialize the object - - An containing the objects data + + The event subscribers. null if no subcribers - - - Deserialize the message - - An containing the data + + Thread sync lock object - - - New as of 1.23 RC1, no details yet. - + + The event subscribers. null if no subcribers - - - Serialize the object - - An containing the objects data + + Thread sync lock object - - - Deserialize the message - - An containing the data + + The event subscribers. null if no subcribers - - - Serialize the object - - An containing the objects data + + Thread sync lock object - - - Deserialize the message - - An containing the data + + The event subscribers. null if no subcribers - - A string containing the method used + + Thread sync lock object + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a request + + + Raised when the simulator responds to a Parcel Update request - - - A request sent from an agent to the Simulator to begin a new conference. - Contains a list of Agents which will be included in the conference - + + Raised when the parcel your agent is located sends a ParcelMediaCommand - - An array containing the of the agents invited to this conference + + Raises the ParcelDwellReply event + A ParcelDwellReplyEventArgs object containing the + data returned from the simulator - - The conferences Session ID + + Raises the ParcelInfoReply event + A ParcelInfoReplyEventArgs object containing the + data returned from the simulator - - - Serialize the object - - An containing the objects data + + Raises the ParcelProperties event + A ParcelPropertiesEventArgs object containing the + data returned from the simulator - - - Deserialize the message - - An containing the data + + Raises the ParcelAccessListReply event + A ParcelAccessListReplyEventArgs object containing the + data returned from the simulator - - - A moderation request sent from a conference moderator - Contains an agent and an optional action to take - + + Raises the ParcelObjectOwnersReply event + A ParcelObjectOwnersReplyEventArgs object containing the + data returned from the simulator - - The Session ID + + Raises the SimParcelsDownloaded event + A SimParcelsDownloadedEventArgs object containing the + data returned from the simulator - - + + Raises the ForceSelectObjectsReply event + A ForceSelectObjectsReplyEventArgs object containing the + data returned from the simulator - - A list containing Key/Value pairs, known valid values: - key: text value: true/false - allow/disallow specified agents ability to use text in session - key: voice value: true/false - allow/disallow specified agents ability to use voice in session - - "text" or "voice" + + Raises the ParcelMediaUpdateReply event + A ParcelMediaUpdateReplyEventArgs object containing the + data returned from the simulator - - + + Raises the ParcelMediaCommand event + A ParcelMediaCommandEventArgs object containing the + data returned from the simulator - + - Serialize the object + Request basic information for a single parcel - An containing the objects data + Simulator-local ID of the parcel - + - Deserialize the message + Request properties of a single parcel - An containing the data + Simulator containing the parcel + Simulator-local ID of the parcel + An arbitrary integer that will be returned + with the ParcelProperties reply, useful for distinguishing between + multiple simultaneous requests - + - A message sent from the agent to the simulator which tells the - simulator we've accepted a conference invitation + Request the access list for a single parcel + Simulator containing the parcel + Simulator-local ID of the parcel + An arbitrary integer that will be returned + with the ParcelAccessList reply, useful for distinguishing between + multiple simultaneous requests + + - - The conference SessionID - - + - Serialize the object + Request properties of parcels using a bounding box selection - An containing the objects data + Simulator containing the parcel + Northern boundary of the parcel selection + Eastern boundary of the parcel selection + Southern boundary of the parcel selection + Western boundary of the parcel selection + An arbitrary integer that will be returned + with the ParcelProperties reply, useful for distinguishing between + different types of parcel property requests + A boolean that is returned with the + ParcelProperties reply, useful for snapping focus to a single + parcel - + - Deserialize the message + Request all simulator parcel properties (used for populating the Simulator.Parcels + dictionary) - An containing the data + Simulator to request parcels from (must be connected) - + - Serialize the object + Request all simulator parcel properties (used for populating the Simulator.Parcels + dictionary) - An containing the objects data + Simulator to request parcels from (must be connected) + If TRUE, will force a full refresh + Number of milliseconds to pause in between each request - + - Deserialize the message + Request the dwell value for a parcel - An containing the data + Simulator containing the parcel + Simulator-local ID of the parcel - + - Serialize the object + Send a request to Purchase a parcel of land - An containing the objects data + The Simulator the parcel is located in + The parcels region specific local ID + true if this parcel is being purchased by a group + The groups + true to remove tier contribution if purchase is successful + The parcels size + The purchase price of the parcel + + - + - Deserialize the message + Reclaim a parcel of land - An containing the data + The simulator the parcel is in + The parcels region specific local ID - + - Serialize the object + Deed a parcel to a group - An containing the objects data + The simulator the parcel is in + The parcels region specific local ID + The groups - + - Deserialize the message + Request prim owners of a parcel of land. - An containing the data - - - Key of sender - - - Name of sender - - - Key of destination avatar - - - ID of originating estate - - - Key of originating region - - - Coordinates in originating region - - - Instant message type - - - Group IM session toggle - - - Key of IM session, for Group Messages, the groups UUID - - - Timestamp of the instant message - - - Instant message text - - - Whether this message is held for offline avatars - - - Context specific packed data + Simulator parcel is in + The parcels region specific local ID - - Is this invitation for voice group/conference chat + + + Return objects from a parcel + + Simulator parcel is in + The parcels region specific local ID + the type of objects to return, + A list containing object owners s to return - + - Serialize the object + Subdivide (split) a parcel - An containing the objects data + + + + + + + + + + - + - Deserialize the message + Join two parcels of land creating a single parcel - An containing the data + + + + + + + + + + - + - Sent from the simulator to the viewer. - - When an agent initially joins a session the AgentUpdatesBlock object will contain a list of session members including - a boolean indicating they can use voice chat in this session, a boolean indicating they are allowed to moderate - this session, and lastly a string which indicates another agent is entering the session with the Transition set to "ENTER" - - During the session lifetime updates on individuals are sent. During the update the booleans sent during the initial join are - excluded with the exception of the Transition field. This indicates a new user entering or exiting the session with - the string "ENTER" or "LEAVE" respectively. + Get a parcels LocalID + Simulator parcel is in + Vector3 position in simulator (Z not used) + 0 on failure, or parcel LocalID on success. + A call to Parcels.RequestAllSimParcels is required to populate map and + dictionary. - + - Serialize the object + Terraform (raise, lower, etc) an area or whole parcel of land - An containing the objects data + Simulator land area is in. + LocalID of parcel, or -1 if using bounding box + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + true on successful request sent. + Settings.STORE_LAND_PATCHES must be true, + Parcel information must be downloaded using RequestAllSimParcels() - + - Deserialize the message + Terraform (raise, lower, etc) an area or whole parcel of land - An containing the data + Simulator land area is in. + west border of area to modify + south border of area to modify + east border of area to modify + north border of area to modify + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + true on successful request sent. + Settings.STORE_LAND_PATCHES must be true, + Parcel information must be downloaded using RequestAllSimParcels() - + - An EventQueue message sent when the agent is forcibly removed from a chatterbox session + Terraform (raise, lower, etc) an area or whole parcel of land + Simulator land area is in. + LocalID of parcel, or -1 if using bounding box + west border of area to modify + south border of area to modify + east border of area to modify + north border of area to modify + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + How many meters + or - to lower, 1 = 1 meter + true on successful request sent. + Settings.STORE_LAND_PATCHES must be true, + Parcel information must be downloaded using RequestAllSimParcels() - + - A string containing the reason the agent was removed + Terraform (raise, lower, etc) an area or whole parcel of land + Simulator land area is in. + LocalID of parcel, or -1 if using bounding box + west border of area to modify + south border of area to modify + east border of area to modify + north border of area to modify + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + How many meters + or - to lower, 1 = 1 meter + Height at which the terraform operation is acting at - + - The ChatterBoxSession's SessionID + Sends a request to the simulator to return a list of objects owned by specific owners + Simulator local ID of parcel + Owners, Others, Etc + List containing keys of avatars objects to select; + if List is null will return Objects of type selectType + Response data is returned in the event - + - Serialize the object + Eject and optionally ban a user from a parcel - An containing the objects data + target key of avatar to eject + true to also ban target - + - Deserialize the message + Freeze or unfreeze an avatar over your land - An containing the data + target key to freeze + true to freeze, false to unfreeze - + - Serialize the object + Abandon a parcel of land - An containing the objects data + Simulator parcel is in + Simulator local ID of parcel - + - Deserialize the message + Requests the UUID of the parcel in a remote region at a specified location - An containing the data + Location of the parcel in the remote region + Remote region handle + Remote region UUID + If successful UUID of the remote parcel, UUID.Zero otherwise - + - Serialize the object + Retrieves information on resources used by the parcel - An containing the objects data + UUID of the parcel + Should per object resource usage be requested + Callback invoked when the request is complete - - - Deserialize the message - - An containing the data + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - - Serialize the object - - An containing the objects data + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - - Deserialize the message - - An containing the data + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - - Serialize the object - - An containing the objects data + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - - Deserialize the message - - An containing the data + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Serialize the object - - An containing the objects data + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - - Deserialize the message - - An containing the data + + Contains a parcels dwell data returned from the simulator in response to an - + - Serialize the object + Construct a new instance of the ParcelDwellReplyEventArgs class - An containing the objects data + The global ID of the parcel + The simulator specific ID of the parcel + The calculated dwell for the parcel - - - Deserialize the message - - An containing the data + + Get the global ID of the parcel - - - Serialize the object - - An containing the objects data + + Get the simulator specific ID of the parcel - - - Deserialize the message - - An containing the data + + Get the calculated dwell - - - A message sent from the viewer to the simulator which - specifies that the user has changed current URL - of the specific media on a prim face - + + Contains basic parcel information data returned from the + simulator in response to an request - + - New URL + Construct a new instance of the ParcelInfoReplyEventArgs class + The object containing basic parcel info - - - Prim UUID where navigation occured - + + Get the object containing basic parcel info - - - Face index - + + Contains basic parcel information data returned from the simulator in response to an request - + - Serialize the object + Construct a new instance of the ParcelPropertiesEventArgs class - An containing the objects data + The object containing the details + The object containing the details + The result of the request + The number of primitieves your agent is + currently selecting and or sitting on in this parcel + The user assigned ID used to correlate a request with + these results + TODO: - - - Deserialize the message - - An containing the data + + Get the simulator the parcel is located in - - Base class used for the ObjectMedia message + + Get the object containing the details + If Result is NoData, this object will not contain valid data - - - Message used to retrive prim media data - + + Get the result of the request - - - Prim UUID - + + Get the number of primitieves your agent is + currently selecting and or sitting on in this parcel - - - Requested operation, either GET or UPDATE - + + Get the user assigned ID used to correlate a request with + these results - - - Serialize object - - Serialized object as OSDMap + + TODO: - - - Deserialize the message - - An containing the data + + Contains blacklist and whitelist data returned from the simulator in response to an request - + - Message used to update prim media data + Construct a new instance of the ParcelAccessListReplyEventArgs class + The simulator the parcel is located in + The user assigned ID used to correlate a request with + these results + The simulator specific ID of the parcel + TODO: + The list containing the white/blacklisted agents for the parcel - - - Prim UUID - + + Get the simulator the parcel is located in - - - Array of media entries indexed by face number - + + Get the user assigned ID used to correlate a request with + these results - - - Media version string - + + Get the simulator specific ID of the parcel + + + TODO: + + + Get the list containing the white/blacklisted agents for the parcel + + + Contains blacklist and whitelist data returned from the + simulator in response to an request - + - Serialize object + Construct a new instance of the ParcelObjectOwnersReplyEventArgs class - Serialized object as OSDMap + The simulator the parcel is located in + The list containing prim ownership counts - - - Deserialize the message - - An containing the data + + Get the simulator the parcel is located in - - - Message used to update prim media data - + + Get the list containing prim ownership counts - - - Prim UUID - + + Contains the data returned when all parcel data has been retrieved from a simulator - + - Array of media entries indexed by face number + Construct a new instance of the SimParcelsDownloadedEventArgs class + The simulator the parcel data was retrieved from + The dictionary containing the parcel data + The multidimensional array containing a x,y grid mapped + to each 64x64 parcel's LocalID. - - - Requested operation, either GET or UPDATE - + + Get the simulator the parcel data was retrieved from - - - Serialize object - - Serialized object as OSDMap + + A dictionary containing the parcel data where the key correlates to the ParcelMap entry - - - Deserialize the message - - An containing the data + + Get the multidimensional array containing a x,y grid mapped + to each 64x64 parcel's LocalID. - + + Contains the data returned when a request + + - Message for setting or getting per face MediaEntry + Construct a new instance of the ForceSelectObjectsReplyEventArgs class + The simulator the parcel data was retrieved from + The list of primitive IDs + true if the list is clean and contains the information + only for a given request - - The request or response details block + + Get the simulator the parcel data was retrieved from - - - Serialize the object - - An containing the objects data + + Get the list of primitive IDs - - - Deserialize the message - - An containing the data + + true if the list is clean and contains the information + only for a given request - + + Contains data when the media data for a parcel the avatar is on changes + + - Represents a texture + Construct a new instance of the ParcelMediaUpdateReplyEventArgs class + the simulator the parcel media data was updated in + The updated media information - - A object containing image data - - - + + Get the simulator the parcel media data was updated in - - + + Get the updated media information - - Initializes a new instance of an AssetTexture object + + Contains the media command for a parcel the agent is currently on - + - Initializes a new instance of an AssetTexture object + Construct a new instance of the ParcelMediaCommandEventArgs class - A unique specific to this asset - A byte array containing the raw asset data + The simulator the parcel media command was issued in + + + + + The media command that was sent + + - + + Get the simulator the parcel media command was issued in + + - Initializes a new instance of an AssetTexture object - A object containing texture data - + - Populates the byte array with a JPEG2000 - encoded image created from the data in - + + Get the media command that was sent + + - Decodes the JPEG2000 data in AssetData to the - object - True if the decoding was successful, otherwise false - + - Decodes the begin and end byte positions for each quality layer in - the image - - - - Override the base classes AssetType - + - Add a custom decoder callback - The key of the field to decode - The custom decode handler - + - Remove a custom decoder callback - The key of the field to decode - The custom decode handler - + - Creates a formatted string containing the values of a Packet - The Packet - A formatted string of values of the nested items in the Packet object - + - Decode an IMessage object into a beautifully formatted string - The IMessage object - Recursion level (used for indenting) - A formatted string containing the names and values of the source object - + - A custom decoder callback - The key of the object - the data to decode - A string represending the fieldData - + - Static helper functions and global variables - - This header flag signals that ACKs are appended to the packet - - - This header flag signals that this packet has been sent before - - - This header flags signals that an ACK is expected for this packet - - - This header flag signals that the message is compressed using zerocoding + + + - + - - - - + - - - - - + - - - - + - - - - - + - Given an X/Y location in absolute (grid-relative) terms, a region - handle is returned along with the local X/Y location in that region - The absolute X location, a number such as - 255360.35 - The absolute Y location, a number such as - 255360.35 - The sim-local X position of the global X - position, a value from 0.0 to 256.0 - The sim-local Y position of the global Y - position, a value from 0.0 to 256.0 - A 64-bit region handle that can be used to teleport to - + - Converts a floating point number to a terse string format used for - transmitting numbers in wearable asset files - Floating point number to convert to a string - A terse string representation of the input number - + - Convert a variable length field (byte array) to a string, with a - field name prepended to each line of the output - If the byte array has unprintable characters in it, a - hex dump will be written instead - The StringBuilder object to write to - The byte array to convert to a string - A field name to prepend to each line of output - + - Decode a zerocoded byte array, used to decompress packets marked - with the zerocoded flag - Any time a zero is encountered, the next byte is a count - of how many zeroes to expand. One zero is encoded with 0x00 0x01, - two zeroes is 0x00 0x02, three zeroes is 0x00 0x03, etc. The - first four bytes are copied directly to the output buffer. - - The byte array to decode - The length of the byte array to decode. This - would be the length of the packet up to (but not including) any - appended ACKs - The output byte array to decode to - The length of the output buffer - + - Encode a byte array with zerocoding. Used to compress packets marked - with the zerocoded flag. Any zeroes in the array are compressed down - to a single zero byte followed by a count of how many zeroes to expand - out. A single zero becomes 0x00 0x01, two zeroes becomes 0x00 0x02, - three zeroes becomes 0x00 0x03, etc. The first four bytes are copied - directly to the output buffer. - The byte array to encode - The length of the byte array to encode - The output byte array to encode to - The length of the output buffer - + + + + + - Calculates the CRC (cyclic redundancy check) needed to upload inventory. - Creation date - Sale type - Inventory type - Type - Asset ID - Group ID - Sale price - Owner ID - Creator ID - Item ID - Folder ID - Everyone mask (permissions) - Flags - Next owner mask (permissions) - Group mask (permissions) - Owner mask (permissions) - The calculated CRC - + - Attempts to load a file embedded in the assembly - The filename of the resource to load - A Stream for the requested file, or null if the resource - was not successfully loaded - + - Attempts to load a file either embedded in the assembly or found in - a given search path - The filename of the resource to load - An optional path that will be searched if - the asset is not found embedded in the assembly - A Stream for the requested file, or null if the resource - was not successfully loaded - + - Converts a list of primitives to an object that can be serialized - with the LLSD system - Primitives to convert to a serializable object - An object that can be serialized with LLSD - + - Deserializes OSD in to a list of primitives - Structure holding the serialized primitive list, - must be of the SDMap type - A list of deserialized primitives - - - Converts a struct or class object containing fields only into a key value separated string - - The struct object - A string containing the struct fields as the keys, and the field value as the value separated - - - // Add the following code to any struct or class containing only fields to override the ToString() - // method to display the values of the passed object - - /// Print the struct data as a string - ///A string containing the field name, and field value - public override string ToString() - { - return Helpers.StructToString(this); - } - - + + + - + - Passed to Logger.Log() to identify the severity of a log entry - - No logging information will be output + + + - - Non-noisy useful information, may be helpful in - debugging a problem + + + - - A non-critical error occurred. A warning will not - prevent the rest of the library from operating as usual, - although it may be indicative of an underlying issue + + + - - A critical error has occurred. Generally this will - be followed by the network layer shutting down, although the - stability of the library after an error is uncertain + + + - - Used for internal testing, this logging level can - generate very noisy (long and/or repetitive) messages. Don't - pass this to the Log() function, use DebugLog() instead. + + - - = + + + - - Number of times we've received an unknown CAPS exception in series. + + + - - For exponential backoff on error. + + + - + - Constants for the archiving module - + - The location of the archive control file - + - Path for the assets held in an archive - + - Path for the prims file + + + + - + - Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. - + - Path for region settings. - + - The character the separates the uuid from extension information in an archived asset filename - + - Extensions used for asset types in the archive - + - - - + + + + + + + - - + + + - - + + + - + - Thrown when a packet could not be successfully deserialized - + - Default constructor - + - Constructor that takes an additional error message - An error message to attach to this exception - + - The header of a message template packet. Holds packet flags, sequence - number, packet ID, and any ACKs that will be appended at the end of - the packet - + - Convert the AckList to a byte array, used for packet serializing - Reference to the target byte array - Beginning position to start writing to in the byte - array, will be updated with the ending position of the ACK list - + - - - - - - + - - - - + + + + - + - A block of data in a packet. Packets are composed of one or more blocks, - each block containing one or more fields - + - Create a block from a byte array - Byte array containing the serialized block - Starting position of the block in the byte array. - This will point to the data after the end of the block when the - call returns - + - Serialize this block into a byte array - Byte array to serialize this block into - Starting position in the byte array to serialize to. - This will point to the position directly after the end of the - serialized block when the call returns - - Current length of the data in this packet + + + - - A generic value, not an actual packet type + + + - - + + + + + + + - - + + + + + + + - - + + + + + + + + + - - + + + - - + + + + + + + - - + + + + + + + - - + + + + + - - + + + Class for controlling various system settings. + + Some values are readonly because they affect things that + happen when the GridClient object is initialized, so changing them at + runtime won't do any good. Non-readonly values may affect things that + happen at login or dynamically - - + + Constructor + Reference to a GridClient object - - + + Main grid login server - - + + Beta grid login server - - + + + InventoryManager requests inventory information on login, + GridClient initializes an Inventory store for main inventory. + - - + + + InventoryManager requests library information on login, + GridClient initializes an Inventory store for the library. + - - + + Number of milliseconds between sending pings to each sim - - + + Number of milliseconds between sending camera updates - - + + Number of milliseconds between updating the current + positions of moving, non-accelerating and non-colliding objects - - + + Millisecond interval between ticks, where all ACKs are + sent out and the age of unACKed packets is checked - - + + The initial size of the packet inbox, where packets are + stored before processing - - + + Maximum size of packet that we want to send over the wire - - + + The maximum value of a packet sequence number before it + rolls over back to one - - + + The maximum size of the sequence number archive, used to + check for resent and/or duplicate packets - - + + The relative directory where external resources are kept - - + + Login server to connect to - - + + IP Address the client will bind to - - + + Use XML-RPC Login or LLSD Login, default is XML-RPC Login - - + + Number of milliseconds before an asset transfer will time + out - - + + Number of milliseconds before a teleport attempt will time + out - - + + Number of milliseconds before NetworkManager.Logout() will + time out - - + + Number of milliseconds before a CAPS call will time out + Setting this too low will cause web requests time out and + possibly retry repeatedly - - + + Number of milliseconds for xml-rpc to timeout - - + + Milliseconds before a packet is assumed lost and resent - - + + Milliseconds without receiving a packet before the + connection to a simulator is assumed lost - - + + Milliseconds to wait for a simulator info request through + the grid interface - - + + Maximum number of queued ACKs to be sent before SendAcks() + is forced - - + + Network stats queue length (seconds) - - + + Enable/disable storing terrain heightmaps in the + TerrainManager - - + + Enable/disable sending periodic camera updates - - + + Enable/disable automatically setting agent appearance at + login and after sim crossing - - + + Enable/disable automatically setting the bandwidth throttle + after connecting to each simulator + The default throttle uses the equivalent of the maximum + bandwidth setting in the official client. If you do not set a + throttle your connection will by default be throttled well below + the minimum values and you may experience connection problems - - + + Enable/disable the sending of pings to monitor lag and + packet loss - - + + Should we connect to multiple sims? This will allow + viewing in to neighboring simulators and sim crossings + (Experimental) - - + + If true, all object update packets will be decoded in to + native objects. If false, only updates for our own agent will be + decoded. Registering an event handler will force objects for that + type to always be decoded. If this is disabled the object tracking + will have missing or partial prim and avatar information - - + + If true, when a cached object check is received from the + server the full object info will automatically be requested - - + + Whether to establish connections to HTTP capabilities + servers for simulators - - + + Whether to decode sim stats - - + + The capabilities servers are currently designed to + periodically return a 502 error which signals for the client to + re-establish a connection. Set this to true to log those 502 errors - - + + If true, any reference received for a folder or item + the library is not aware of will automatically be fetched - - + + If true, and SEND_AGENT_UPDATES is true, + AgentUpdate packets will continuously be sent out to give the bot + smoother movement and autopiloting - - + + If true, currently visible avatars will be stored + in dictionaries inside Simulator.ObjectAvatars. + If false, a new Avatar or Primitive object will be created + each time an object update packet is received - - + + If true, currently visible avatars will be stored + in dictionaries inside Simulator.ObjectPrimitives. + If false, a new Avatar or Primitive object will be created + each time an object update packet is received - - + + If true, position and velocity will periodically be + interpolated (extrapolated, technically) for objects and + avatars that are being tracked by the library. This is + necessary to increase the accuracy of speed and position + estimates for simulated objects - - + + + If true, utilization statistics will be tracked. There is a minor penalty + in CPU time for enabling this option. + - - + + If true, parcel details will be stored in the + Simulator.Parcels dictionary as they are received - - + + + If true, an incoming parcel properties reply will automatically send + a request for the parcel access list + - - + + + if true, an incoming parcel properties reply will automatically send + a request for the traffic count. + - - + + + If true, images, and other assets downloaded from the server + will be cached in a local directory + - - + + Path to store cached texture data - - + + Maximum size cached files are allowed to take on disk (bytes) - - + + Default color used for viewer particle effects - - + + Maximum number of times to resend a failed packet - - + + Throttle outgoing packet rate - - + + UUID of a texture used by some viewers to indentify type of client used - - + + + Download textures using GetTexture capability when available + - - + + The maximum number of concurrent texture downloads allowed + Increasing this number will not necessarily increase texture retrieval times due to + simulator throttles - - + + + The Refresh timer inteval is used to set the delay between checks for stalled texture downloads + + This is a static variable which applies to all instances - - + + + Textures taking longer than this value will be flagged as timed out and removed from the pipeline + - - + + + Get or set the minimum log level to output to the console by default + If the library is not compiled with DEBUG defined and this level is set to DEBUG + You will get no output on the console. This behavior can be overriden by creating + a logger configuration file for log4net + - - + + Attach avatar names to log messages - - + + Log packet retransmission info - - + + Cost of uploading an asset + Read-only since this value is dynamically fetched at login - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + + Simulator (region) properties + - - + + No flags set - - + + Agents can take damage and be killed - - + + Landmarks can be created here - - + + Home position can be set in this sim - - + + Home position is reset when an agent teleports away - - + + Sun does not move - - + + No object, land, etc. taxes - - + + Disable heightmap alterations (agents can still plant + foliage) - - + + Land cannot be released, sold, or purchased - - + + All content is wiped nightly - - + + Unknown: Related to the availability of an overview world map tile.(Think mainland images when zoomed out.) - - + + Unknown: Related to region debug flags. Possibly to skip processing of agent interaction with world. - - + + Region does not update agent prim interest lists. Internal debugging option. - - + + No collision detection for non-agent objects - - + + No scripts are ran - - + + All physics processing is turned off - - + + Region can be seen from other regions on world map. (Legacy world map option?) - - + + Region can be seen from mainland on world map. (Legacy world map option?) - - + + Agents not explicitly on the access list can visit the region. - - + + Traffic calculations are not run across entire region, overrides parcel settings. - - + + Flight is disabled (not currently enforced by the sim) - - + + Allow direct (p2p) teleporting - - + + Estate owner has temporarily disabled scripting - - + + Restricts the usage of the LSL llPushObject function, applies to whole region. - - + + Deny agents with no payment info on file - - + + Deny agents with payment info on file - - + + Deny agents who have made a monetary transaction - - + + Parcels within the region may be joined or divided by anyone, not just estate owners/managers. - - + + Abuse reports sent from within this region are sent to the estate owner defined email. - - + + Region is Voice Enabled - - + + Removes the ability from parcel owners to set their parcels to show in search. - - + + Deny agents who have not been age verified from entering the region. - - + + + Access level for a simulator + - - + + Unknown or invalid access level - - + + Trial accounts allowed - - + + PG rating - - + + Mature rating - - + + Adult rating - - + + Simulator is offline - - + + Simulator does not exist - - + + + - - + + + + Reference to the GridClient object + IPEndPoint of the simulator + handle of the simulator - - + + + Simulator Statistics + - - + + Total number of packets sent by this simulator to this agent - - + + Total number of packets received by this simulator to this agent - - + + Total number of bytes sent by this simulator to this agent - - + + Total number of bytes received by this simulator to this agent - - + + Time in seconds agent has been connected to simulator - - + + Total number of packets that have been resent - - + + Total number of resent packets recieved - - + + Total number of pings sent to this simulator by this agent - - + + Total number of ping replies sent to this agent by this simulator - - + + + Incoming bytes per second + + It would be nice to have this claculated on the fly, but + this is far, far easier - - + + + Outgoing bytes per second + + It would be nice to have this claculated on the fly, but + this is far, far easier - - + + Time last ping was sent - - + + ID of last Ping sent - - + + + - - + + + - - + + Current time dilation of this simulator - - + + Current Frames per second of simulator - - + + Current Physics frames per second of simulator - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + Total number of objects Simulator is simulating - - + + Total number of Active (Scripted) objects running - - + + Number of agents currently in this simulator - - + + Number of agents in neighbor simulators - - + + Number of Active scripts running in this simulator - - + + + - - + + + - - + + + - - + + Number of downloads pending - - + + Number of uploads pending - - + + + - - + + + - - + + Number of local uploads pending - - + + Unacknowledged bytes in queue - - + + A public reference to the client that this Simulator object + is attached to - - + + A Unique Cache identifier for this simulator - - + + The capabilities for this simulator - - + + + - - + + The current version of software this simulator is running - - + + + - - + + A 64x64 grid of parcel coloring values. The values stored + in this array are of the type - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + true if your agent has Estate Manager rights on this region - - + + + - - + + + - - + + + - - + + Statistics information for this simulator and the + connection to the simulator, calculated by the simulator itself + and the library - - + + The regions Unique ID - - + + The physical data center the simulator is located + Known values are: + DallasChandlerSF - - + + The CPU Class of the simulator + Most full mainland/estate sims appear to be 5, + Homesteads and Openspace appear to be 501 - - + + The number of regions sharing the same CPU as this one + "Full Sims" appear to be 1, Homesteads appear to be 4 - - + + The billing product name + Known values are: + Mainland / Full Region (Sku: 023)Estate / Full Region (Sku: 024)Estate / Openspace (Sku: 027)Estate / Homestead (Sku: 029)Mainland / Homestead (Sku: 129) (Linden Owned)Mainland / Linden Homes (Sku: 131) - - + + The billing product SKU + Known values are: + 023 Mainland / Full Region024 Estate / Full Region027 Estate / Openspace029 Estate / Homestead129 Mainland / Homestead (Linden Owned)131 Linden Homes / Full Region - - + + The current sequence number for packets sent to this + simulator. Must be Interlocked before modifying. Only + useful for applications manipulating sequence numbers - - + + + A thread-safe dictionary containing avatars in a simulator + - - + + + A thread-safe dictionary containing primitives in a simulator + - - + + + Provides access to an internal thread-safe dictionary containing parcel + information found in this simulator + - - + + Used internally to track sim disconnections - - + + Event that is triggered when the simulator successfully + establishes a connection - - + + Whether this sim is currently connected or not. Hooked up + to the property Connected - - + + Coarse locations of avatars in this simulator - - + + AvatarPositions key representing TrackAgent target - - + + Sequence numbers of packets we've received + (for duplicate checking) - - + + Packets we sent out that need ACKs from the simulator - - + + Sequence number for pause/resume - - + + Indicates if UDP connection to the sim is fully established - - + + + Provides access to an internal thread-safe multidimensional array containing a x,y grid mapped + to each 64x64 parcel's LocalID. + - - + + The IP address and port of the server - - + + Whether there is a working connection to the simulator or + not - - + + Coarse locations of avatars in this simulator - - + + AvatarPositions key representing TrackAgent target - - + + Indicates if UDP connection to the sim is fully established - - + + + Checks simulator parcel map to make sure it has downloaded all data successfully + + true if map is full (contains no 0's) - - + + + Called when this Simulator object is being destroyed + - - + + + Attempt to connect to this simulator + + Whether to move our agent in to this sim or not + True if the connection succeeded or connection status is + unknown, false if there was a failure - - + + + Initiates connection to the simulator + - - + + + Disconnect from this simulator + - - + + + Instructs the simulator to stop sending update (and possibly other) packets + - - + + + Instructs the simulator to resume sending update packets (unpause) + - - + + + Retrieve the terrain height at a given coordinate + + Sim X coordinate, valid range is from 0 to 255 + Sim Y coordinate, valid range is from 0 to 255 + The terrain height at the given point if the + lookup was successful, otherwise 0.0f + True if the lookup was successful, otherwise false - - + + + Sends a packet + + Packet to be sent - - + + + - - + + + Returns Simulator Name as a String + + + - - + + + + + - - + + + + + + + - - + + + Sends out pending acknowledgements + + Number of ACKs sent - - + + + Resend unacknowledged packets + - - + + + - - + + + Construct a new instance of the SoundManager class, used for playing and receiving + sound assets + + A reference to the current GridClient instance - - + + The event subscribers, null of no subscribers - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Thread sync lock object - - + + Raised when the simulator sends us data containing + sound - - + + Raised when the simulator sends us data containing + ... - - + + Raised when the simulator sends us data containing + ... - - + + Raised when the simulator sends us data containing + ... - - + + Raises the AttachedSound Event + A AttachedSoundEventArgs object containing + the data sent from the simulator - - + + Raises the AttachedSoundGainChange Event + A AttachedSoundGainChangeEventArgs object containing + the data sent from the simulator - - + + Raises the SoundTrigger Event + A SoundTriggerEventArgs object containing + the data sent from the simulator - - + + Raises the PreloadSound Event + A PreloadSoundEventArgs object containing + the data sent from the simulator - - + + + Plays a sound in the current region at full volume from avatar position + + UUID of the sound to be played - - + + + Plays a sound in the current region at full volume + + UUID of the sound to be played. + position for the sound to be played at. Normally the avatar. - - + + + Plays a sound in the current region + + UUID of the sound to be played. + position for the sound to be played at. Normally the avatar. + volume of the sound, from 0.0 to 1.0 - - + + + Plays a sound in the specified sim + + UUID of the sound to be played. + UUID of the sound to be played. + position for the sound to be played at. Normally the avatar. + volume of the sound, from 0.0 to 1.0 - - + + + Play a sound asset + + UUID of the sound to be played. + handle id for the sim to be played in. + position for the sound to be played at. Normally the avatar. + volume of the sound, from 0.0 to 1.0 - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Provides data for the event + The event occurs when the simulator sends + the sound data which emits from an agents attachment + + The following code example shows the process to subscribe to the event + and a stub to handle the data passed from the simulator + + // Subscribe to the AttachedSound event + Client.Sound.AttachedSound += Sound_AttachedSound; + // process the data raised in the event here + private void Sound_AttachedSound(object sender, AttachedSoundEventArgs e) + { + // ... Process AttachedSoundEventArgs here ... + } + - - + + + Construct a new instance of the SoundTriggerEventArgs class + + Simulator where the event originated + The sound asset id + The ID of the owner + The ID of the object + The volume level + The - - + + Simulator where the event originated - - + + Get the sound asset id - - + + Get the ID of the owner - - + + Get the ID of the Object - - + + Get the volume level - - + + Get the - - + + Provides data for the event + The event occurs when an attached sound + changes its volume level - - + + + Construct a new instance of the AttachedSoundGainChangedEventArgs class + + Simulator where the event originated + The ID of the Object + The new volume level - - + + Simulator where the event originated - - + + Get the ID of the Object - - + + Get the volume level - - + + Provides data for the event + + The event occurs when the simulator forwards + a request made by yourself or another agent to play either an asset sound or a built in sound + Requests to play sounds where the is not one of the built-in + will require sending a request to download the sound asset before it can be played + + + The following code example uses the , + and + properties to display some information on a sound request on the window. + + // subscribe to the event + Client.Sound.SoundTrigger += Sound_SoundTrigger; + // play the pre-defined BELL_TING sound + Client.Sound.SendSoundTrigger(Sounds.BELL_TING); + // handle the response data + private void Sound_SoundTrigger(object sender, SoundTriggerEventArgs e) + { + Console.WriteLine("{0} played the sound {1} at volume {2}", + e.OwnerID, e.SoundID, e.Gain); + } + - - + + + Construct a new instance of the SoundTriggerEventArgs class + + Simulator where the event originated + The sound asset id + The ID of the owner + The ID of the object + The ID of the objects parent + The volume level + The regionhandle + The source position - - + + Simulator where the event originated - - + + Get the sound asset id - - + + Get the ID of the owner - - + + Get the ID of the Object - - + + Get the ID of the objects parent - - + + Get the volume level - - + + Get the regionhandle - - + + Get the source position - - + + Provides data for the event + The event occurs when the simulator sends + the appearance data for an avatar + + The following code example uses the and + properties to display the selected shape of an avatar on the window. + + // subscribe to the event + Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; + // handle the data when the event is raised + void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) + { + Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") + } + - - + + + Construct a new instance of the PreloadSoundEventArgs class + + Simulator where the event originated + The sound asset id + The ID of the owner + The ID of the object - - + + Simulator where the event originated - - + + Get the sound asset id - - + + Get the ID of the owner - - + + Get the ID of the Object - - + + + pre-defined built in sounds + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + coins - - + + cash register bell - - + + + - - + + + - - + + rubber - - + + plastic - - + + flesh - - + + wood splintering? - - + + glass break - - + + metal clunk - - + + whoosh - - + + shake - - + + + - - + + ding - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + A dictionary containing all pre-defined sounds + + A dictionary containing the pre-defined sounds, + where the key is the sounds ID, and the value is a string + containing a name to identify the purpose of the sound - - + + X position of this patch - - + + Y position of this patch - - + + A 16x16 array of floats holding decompressed layer data - - + + + Creates a LayerData packet for compressed land data given a full + simulator heightmap and an array of indices of patches to compress + + A 256 * 256 array of floating point values + specifying the height at each meter in the simulator + Array of indexes in the 16x16 grid of patches + for this simulator. For example if 1 and 17 are specified, patches + x=1,y=0 and x=1,y=1 are sent + + - - + + + Add a patch of terrain to a BitPacker + + BitPacker to write the patch to + Heightmap of the simulator, must be a 256 * + 256 float array + X offset of the patch to create, valid values are + from 0 to 15 + Y offset of the patch to create, valid values are + from 0 to 15 - - + + + Default constructor + + + - - + + The event subscribers. null if no subcribers - - + + Thread sync lock object - - + + Raised when the simulator responds sends - - + + Raises the LandPatchReceived event + A LandPatchReceivedEventArgs object containing the + data returned from the simulator - - + + Simulator from that sent tha data - - + + Sim coordinate of the patch - - + + Sim coordinate of the patch - - + + Size of tha patch - - + + Heightmap for the patch - - + + + The current status of a texture request as it moves through the pipeline or final result of a texture request. + - - + + The initial state given to a request. Requests in this state + are waiting for an available slot in the pipeline - - + + A request that has been added to the pipeline and the request packet + has been sent to the simulator - - + + A request that has received one or more packets back from the simulator - - + + A request that has received all packets back from the simulator - - + + A request that has taken longer than + to download OR the initial packet containing the packet information was never received - - + + The texture request was aborted by request of the agent - - + + The simulator replied to the request that it was not able to find the requested texture - - + + + Texture request download handler, allows a configurable number of download slots which manage multiple + concurrent texture downloads from the + This class makes full use of the internal + system for full texture downloads. - - + + + Default constructor, Instantiates a new copy of the TexturePipeline class + + Reference to the instantiated object - - + + + A request task containing information and status of a request as it is processed through the - - + + The current which identifies the current status of the request - - + + The Unique Request ID, This is also the Asset ID of the texture being requested - - + + The slot this request is occupying in the threadpoolSlots array - - + + The ImageType of the request. - - + + The callback to fire when the request is complete, will include + the and the + object containing the result data - - + + If true, indicates the callback will be fired whenever new data is returned from the simulator. + This is used to progressively render textures as portions of the texture are received. - - + + An object that maintains the data of an request thats in-process. - - + + A dictionary containing all pending and in-process transfer requests where the Key is both the RequestID + and also the Asset Texture ID, and the value is an object containing the current state of the request and also + the asset data as it is being re-assembled - - + + Holds the reference to the client object - - + + Maximum concurrent texture requests allowed at a time - - + + An array of objects used to manage worker request threads - - + + An array of worker slots which shows the availablity status of the slot - - + + The primary thread which manages the requests. - - + + true if the TexturePipeline is currently running - - + + A synchronization object used by the primary thread - - + + A refresh timer used to increase the priority of stalled requests - - + + Current number of pending and in-process transfers - - + + + Initialize callbacks required for the TexturePipeline to operate + - - + + + Shutdown the TexturePipeline and cleanup any callbacks or transfers + - - + + + Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + A float indicating the requested priority for the transfer. Higher priority values tell the simulator + to prioritize the request before lower valued requests. An image already being transferred using the can have + its priority changed by resending the request with the new priority value + Number of quality layers to discard. + This controls the end marker of the data sent + The packet number to begin the request at. A value of 0 begins the request + from the start of the asset texture + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + If true, the callback will be fired for each chunk of the downloaded image. + The callback asset parameter will contain all previously received chunks of the texture asset starting + from the beginning of the request - - + + + Sends the actual request packet to the simulator + + The image to download + Type of the image to download, either a baked + avatar texture or a normal texture + Priority level of the download. Default is + 1,013,000.0f + Number of quality layers to discard. + This controls the end marker of the data sent + Packet number to start the download at. + This controls the start marker of the data sent + Sending a priority of 0 and a discardlevel of -1 aborts + download - - + + + Cancel a pending or in process texture request + + The texture assets unique ID - - + + + Master Download Thread, Queues up downloads in the threadpool + - - + + + The worker thread that sends the request and handles timeouts + + A object containing the request details - - + + + Handle responses from the simulator that tell us a texture we have requested is unable to be located + or no longer exists. This will remove the request from the pipeline and free up a slot if one is in use + + The sender + The EventArgs object containing the packet data - - + + + Handles the remaining Image data that did not fit in the initial ImageData packet + + The sender + The EventArgs object containing the packet data - - + + + Handle the initial ImageDataPacket sent from the simulator + + The sender + The EventArgs object containing the packet data - - + + + - - + + + Delegate to wrap another delegate and its arguments + + + + + - - + + + An instance of DelegateWrapper which calls InvokeWrappedDelegate, + which in turn calls the DynamicInvoke method of the wrapped + delegate + - - + + + Callback used to call EndInvoke on the asynchronously + invoked DelegateWrapper + - - + + + Executes the specified delegate with the specified arguments + asynchronously on a thread pool thread + + + + + - - + + + Invokes the wrapped delegate synchronously + + + + + - - + + + Calls EndInvoke on the wrapper and Close on the resulting WaitHandle + to prevent resource leaks + + + - - + + + - - + + + Initialize the UDP packet handler in server mode + + Port to listening for incoming UDP packets on - - + + + Initialize the UDP packet handler in client mode + + Remote UDP server to connect to - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + Thrown when a packet could not be successfully deserialized + - - + + + Default constructor + - - + + + Constructor that takes an additional error message + + An error message to attach to this exception - - + + + The header of a message template packet. Holds packet flags, sequence + number, packet ID, and any ACKs that will be appended at the end of + the packet + - - + + + Convert the AckList to a byte array, used for packet serializing + + Reference to the target byte array + Beginning position to start writing to in the byte + array, will be updated with the ending position of the ACK list - - + + + + + + + + + + + - - + + + + + + + + + - - + + + A block of data in a packet. Packets are composed of one or more blocks, + each block containing one or more fields + - - + + Current length of the data in this packet - - + + + Create a block from a byte array + + Byte array containing the serialized block + Starting position of the block in the byte array. + This will point to the data after the end of the block when the + call returns - - + + + Serialize this block into a byte array + + Byte array to serialize this block into + Starting position in the byte array to serialize to. + This will point to the position directly after the end of the + serialized block when the call returns - - + + A generic value, not an actual packet type - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + - - The avatar has no rights + + - - The avatar can see the online status of the target avatar + + - - The avatar can see the location of the target avatar on the map + + - - The avatar can modify the ojects of the target avatar + + - - - This class holds information about an avatar in the friends list. There are two ways - to interface to this class. The first is through the set of boolean properties. This is the typical - way clients of this class will use it. The second interface is through two bitflag properties, - TheirFriendsRights and MyFriendsRights - + + - - - Used internally when building the initial list of friends at login time - - System ID of the avatar being prepesented - Rights the friend has to see you online and to modify your objects - Rights you have to see your friend online and to modify their objects + + - - - FriendInfo represented as a string - - A string reprentation of both my rights and my friends rights + + - - - System ID of the avatar - + + - - - full name of the avatar - + + - - - True if the avatar is online - + + - - - True if the friend can see if I am online - + + - - - True if the friend can see me on the map - + + - - - True if the freind can modify my objects - + + - - - True if I can see if my friend is online - + + - - - True if I can see if my friend is on the map - + + - - - True if I can modify my friend's objects - + + - - - My friend's rights represented as bitmapped flags - + + - - - My rights represented as bitmapped flags - + + - - - This class is used to add and remove avatars from your friends list and to manage their permission. - + + - - The event subscribers. null if no subcribers + + - - Raises the FriendOnline event - A FriendInfoEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendOffline event - A FriendInfoEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendRightsUpdate event - A FriendInfoEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendNames event - A FriendNamesEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendshipOffered event - A FriendshipOfferedEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendshipResponse event - A FriendshipResponseEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendshipTerminated event - A FriendshipTerminatedEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Raises the FriendFoundReply event - A FriendFoundReplyEventArgs object containing the - data returned from the data server + + - - Thread sync lock object + + - - - A dictionary of key/value pairs containing known friends of this avatar. - - The Key is the of the friend, the value is a - object that contains detailed information including permissions you have and have given to the friend - + + - - - A Dictionary of key/value pairs containing current pending frienship offers. - - The key is the of the avatar making the request, - the value is the of the request which is used to accept - or decline the friendship offer - + + - - - Internal constructor - - A reference to the GridClient Object + + - - - Accept a friendship request - - agentID of avatatar to form friendship with - imSessionID of the friendship request message + + - - - Decline a friendship request - - of friend - imSessionID of the friendship request message + + - - - Overload: Offer friendship to an avatar. - - System ID of the avatar you are offering friendship to + + - - - Offer friendship to an avatar. - - System ID of the avatar you are offering friendship to - A message to send with the request + + - - - Terminate a friendship with an avatar - - System ID of the avatar you are terminating the friendship with + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - - Change the rights of a friend avatar. - - the of the friend - the new rights to give the friend - This method will implicitly set the rights to those passed in the rights parameter. + + - - - Use to map a friends location on the grid. - - Friends UUID to find - + + - - - Use to track a friends movement on the grid - - Friends Key + + - - - Ask for a notification of friend's online status - - Friend's UUID + + - - - This handles the asynchronous response of a RequestAvatarNames call. - - - names cooresponding to the the list of IDs sent the the RequestAvatarNames call. + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - - Populate FriendList with data from the login reply - - true if login was successful - true if login request is requiring a redirect - A string containing the response to the login request - A string containing the reason for the request - A object containing the decoded - reply from the login server + + - - Raised when the simulator sends notification one of the members in our friends list comes online + + - - Raised when the simulator sends notification one of the members in our friends list goes offline + + - - Raised when the simulator sends notification one of the members in our friends list grants or revokes permissions + + - - Raised when the simulator sends us the names on our friends list + + - - Raised when the simulator sends notification another agent is offering us friendship + + - - Raised when a request we sent to friend another agent is accepted or declined + + - - Raised when the simulator sends notification one of the members in our friends list has terminated - our friendship + + - - Raised when the simulator sends the location of a friend we have - requested map location info for + + - - Contains information on a member of our friends list + + - - - Construct a new instance of the FriendInfoEventArgs class - - The FriendInfo + + - - Get the FriendInfo + + - - Contains Friend Names + + - - - Construct a new instance of the FriendNamesEventArgs class - - A dictionary where the Key is the ID of the Agent, - and the Value is a string containing their name + + - - A dictionary where the Key is the ID of the Agent, - and the Value is a string containing their name + + - - Sent when another agent requests a friendship with our agent + + - - - Construct a new instance of the FriendshipOfferedEventArgs class - - The ID of the agent requesting friendship - The name of the agent requesting friendship - The ID of the session, used in accepting or declining the - friendship offer + + - - Get the ID of the agent requesting friendship + + - - Get the name of the agent requesting friendship + + - - Get the ID of the session, used in accepting or declining the - friendship offer + + - - A response containing the results of our request to form a friendship with another agent + + - - - Construct a new instance of the FriendShipResponseEventArgs class - - The ID of the agent we requested a friendship with - The name of the agent we requested a friendship with - true if the agent accepted our friendship offer + + - - Get the ID of the agent we requested a friendship with + + - - Get the name of the agent we requested a friendship with + + - - true if the agent accepted our friendship offer + + - - Contains data sent when a friend terminates a friendship with us + + - - - Construct a new instance of the FrindshipTerminatedEventArgs class - - The ID of the friend who terminated the friendship with us - The name of the friend who terminated the friendship with us + + - - Get the ID of the agent that terminated the friendship with us + + - - Get the name of the agent that terminated the friendship with us + + - - - Data sent in response to a request which contains the information to allow us to map the friends location - + + - - - Construct a new instance of the FriendFoundReplyEventArgs class - - The ID of the agent we have requested location information for - The region handle where our friend is located - The simulator local position our friend is located + + - - Get the ID of the agent we have received location information for + + - - Get the region handle where our mapped friend is located + + - - Get the simulator local position where our friend is located + + - - - - - Looking direction, must be a normalized vector - Up direction, must be a normalized vector + + - - - Align the coordinate frame X and Y axis with a given rotation - around the Z axis in radians - - Absolute rotation around the Z axis in - radians + + - - Origin position of this coordinate frame + + - - X axis of this coordinate frame, or Forward/At in grid terms + + - - Y axis of this coordinate frame, or Left in grid terms + + - - Z axis of this coordinate frame, or Up in grid terms + + - - - Throttles the network traffic for various different traffic types. - Access this class through GridClient.Throttle - + + - - - Default constructor, uses a default high total of 1500 KBps (1536000) - + + - - - Constructor that decodes an existing AgentThrottle packet in to - individual values - - Reference to the throttle data in an AgentThrottle - packet - Offset position to start reading at in the - throttle data - This is generally not needed in clients as the server will - never send a throttle packet to the client + + - - - Send an AgentThrottle packet to the current server using the - current values - + + - - - Send an AgentThrottle packet to the specified server using the - current values - + + - - - Convert the current throttle values to a byte array that can be put - in an AgentThrottle packet - - Byte array containing all the throttle values + + - - Maximum bits per second for resending unacknowledged packets + + - - Maximum bits per second for LayerData terrain + + - - Maximum bits per second for LayerData wind data + + - - Maximum bits per second for LayerData clouds + + - - Unknown, includes object data + + - - Maximum bits per second for textures + + - - Maximum bits per second for downloaded assets + + - - Maximum bits per second the entire connection, divided up - between invidiual streams using default multipliers + + - - - Permission request flags, asked when a script wants to control an Avatar - + + - - Placeholder for empty values, shouldn't ever see this + + - - Script wants ability to take money from you + + - - Script wants to take camera controls for you + + - - Script wants to remap avatars controls + + - - Script wants to trigger avatar animations - This function is not implemented on the grid + + - - Script wants to attach or detach the prim or primset to your avatar + + - - Script wants permission to release ownership - This function is not implemented on the grid - The concept of "public" objects does not exist anymore. + + - - Script wants ability to link/delink with other prims + + - - Script wants permission to change joints - This function is not implemented on the grid + + - - Script wants permissions to change permissions - This function is not implemented on the grid + + + + + - - Script wants to track avatars camera position and rotation + + - - Script wants to control your camera + + - - - Special commands used in Instant Messages - + + - - Indicates a regular IM from another agent + + - - Simple notification box with an OK button + + - - You've been invited to join a group. + + - - Inventory offer + + - - Accepted inventory offer + + - - Declined inventory offer + + - - Group vote + + - - An object is offering its inventory + + - - Accept an inventory offer from an object + + - - Decline an inventory offer from an object + + - - Unknown + + - - Start a session, or add users to a session + + - - Start a session, but don't prune offline users + + - - Start a session with your group + + - - Start a session without a calling card (finder or objects) + + - - Send a message to a session + + - - Leave a session + + - - Indicates that the IM is from an object + + - - Sent an IM to a busy user, this is the auto response + + - - Shows the message in the console and chat history + + - - Send a teleport lure + + - - Response sent to the agent which inititiated a teleport invitation + + - - Response sent to the agent which inititiated a teleport invitation + + - - Only useful if you have Linden permissions + + - - A placeholder type for future expansion, currently not - used + + - - IM to tell the user to go to an URL + + - - IM for help + + - - IM sent automatically on call for help, sends a lure - to each Helper reached + + - - Like an IM but won't go to email + + - - IM from a group officer to all group members + + - - Unknown + + - - Unknown + + - - Accept a group invitation + + - - Decline a group invitation + + - - Unknown + + - - An avatar is offering you friendship + + - - An avatar has accepted your friendship offer + + - - An avatar has declined your friendship offer + + - - Indicates that a user has started typing + + - - Indicates that a user has stopped typing + + - - - Flag in Instant Messages, whether the IM should be delivered to - offline avatars as well - + + - - Only deliver to online avatars + + - - If the avatar is offline the message will be held until - they login next, and possibly forwarded to their e-mail account + + - - - Conversion type to denote Chat Packet types in an easier-to-understand format - + + - - Whisper (5m radius) + + - - Normal chat (10/20m radius), what the official viewer typically sends + + - - Shouting! (100m radius) + + - - Event message when an Avatar has begun to type + + - - Event message when an Avatar has stopped typing + + - - Send the message to the debug channel + + - - Event message when an object uses llOwnerSay + + - - Special value to support llRegionSay, never sent to the client + + - - - Identifies the source of a chat message - + + - - Chat from the grid or simulator + + - - Chat from another avatar + + - - Chat from an object + + - - - - + + - - + + - - + + - - + + - - - Effect type used in ViewerEffect packets - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - Project a beam from a source to a destination, such as - the one used when editing an object + + - - + + - - + + - - + + - - Create a swirl of particles around an object + + - - + + - - + + - - Cause an avatar to look at an object + + - - Cause an avatar to point at an object + + - - - The action an avatar is doing when looking at something, used in - ViewerEffect packets for the LookAt effect - + + - - + + - - + + - - + + - - + + - - + + - - + + - - Deprecated + + - - + + - - + + - - + + - - + + - - - The action an avatar is doing when pointing at something, used in - ViewerEffect packets for the PointAt effect - + + - - + + - - + + - - + + - - + + - - - Money transaction types - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - Flags sent when a script takes or releases a control - - NOTE: (need to verify) These might be a subset of the ControlFlags enum in Movement, + + - - No Flags set + + - - Forward (W or up Arrow) + + - - Back (S or down arrow) + + - - Move left (shift+A or left arrow) + + - - Move right (shift+D or right arrow) + + - - Up (E or PgUp) + + - - Down (C or PgDown) + + - - Rotate left (A or left arrow) + + - - Rotate right (D or right arrow) + + - - Left Mouse Button + + - - Left Mouse button in MouseLook + + - - - Currently only used to hide your group title - + + - - No flags set + + - - Hide your group title + + - - - Action state of the avatar, which can currently be typing and - editing - + + - - + + - - + + - - + + - - - Current teleport status - + + - - Unknown status + + - - Teleport initialized + + - - Teleport in progress + + - - Teleport failed + + - - Teleport completed + + - - Teleport cancelled + + - - - - + + - - No flags set, or teleport failed + + - - Set when newbie leaves help island for first time + + - - + + - - Via Lure + + - - Via Landmark + + - - Via Location + + - - Via Home + + - - Via Telehub + + - - Via Login + + - - Linden Summoned + + - - Linden Forced me + + - - + + - - Agent Teleported Home via Script + + - - + + - - + + - - + + - - forced to new location for example when avatar is banned or ejected + + - - Teleport Finished via a Lure + + - - Finished, Sim Changed + + - - Finished, Same Sim + + - - - - + + - - + + - - + + - - + + - - - - + + - - + + - - + + - - + + - - + + - - - Instant Message - + + - - Key of sender + + - - Name of sender + + - - Key of destination avatar + + - - ID of originating estate + + - - Key of originating region + + - - Coordinates in originating region + + - - Instant message type + + - - Group IM session toggle + + - - Key of IM session, for Group Messages, the groups UUID + + - - Timestamp of the instant message + + - - Instant message text + + - - Whether this message is held for offline avatars + + - - Context specific packed data + + - - Print the struct data as a string - A string containing the field name, and field value + + - - - - + + - - - Construct a new instance of the ChatEventArgs object - - Sim from which the message originates - The message sent - The audible level of the message - The type of message sent: whisper, shout, etc - The source type of the message sender - The name of the agent or object sending the message - The ID of the agent or object sending the message - The ID of the object owner, or the agent ID sending the message - The position of the agent or object sending the message + + - - Get the simulator sending the message + + - - Get the message sent + + - - Get the audible level of the message + + - - Get the type of message sent: whisper, shout, etc + + - - Get the source type of the message sender + + - - Get the name of the agent or object sending the message + + - - Get the ID of the agent or object sending the message + + - - Get the ID of the object owner, or the agent ID sending the message + + - - Get the position of the agent or object sending the message + + - - Contains the data sent when a primitive opens a dialog with this agent + + - - - Construct a new instance of the ScriptDialogEventArgs - - The dialog message - The name of the object that sent the dialog request - The ID of the image to be displayed - The ID of the primitive sending the dialog - The first name of the senders owner - The last name of the senders owner - The communication channel the dialog was sent on - The string labels containing the options presented in this dialog + + - - Get the dialog message + + - - Get the name of the object that sent the dialog request + + - - Get the ID of the image to be displayed + + - - Get the ID of the primitive sending the dialog + + - - Get the first name of the senders owner + + - - Get the last name of the senders owner + + - - Get the communication channel the dialog was sent on, responses - should also send responses on this same channel + + - - Get the string labels containing the options presented in this dialog + + - - Contains the data sent when a primitive requests debit or other permissions - requesting a YES or NO answer + + - - - Construct a new instance of the ScriptQuestionEventArgs - - The simulator containing the object sending the request - The ID of the script making the request - The ID of the primitive containing the script making the request - The name of the primitive making the request - The name of the owner of the object making the request - The permissions being requested + + - - Get the simulator containing the object sending the request + + - - Get the ID of the script making the request + + - - Get the ID of the primitive containing the script making the request + + - - Get the name of the primitive making the request + + - - Get the name of the owner of the object making the request + + - - Get the permissions being requested + + - - Contains the data sent when a primitive sends a request - to an agent to open the specified URL + + - - - Construct a new instance of the LoadUrlEventArgs - - The name of the object sending the request - The ID of the object sending the request - The ID of the owner of the object sending the request - True if the object is owned by a group - The message sent with the request - The URL the object sent + + + + + - - Get the name of the object sending the request + + - - Get the ID of the object sending the request + + - - Get the ID of the owner of the object sending the request + + - - True if the object is owned by a group + + - - Get the message sent with the request + + - - Get the URL the object sent + + - - The date received from an ImprovedInstantMessage + + - + + + + + + + - Construct a new instance of the InstantMessageEventArgs object + Operation to apply when applying color to texture - the InstantMessage object - the simulator where the InstantMessage origniated - - Get the InstantMessage object - - - Get the simulator where the InstantMessage origniated + + + Information needed to translate visual param value to RGBA color + - - Contains the currency balance + + + Construct VisualColorParam + + Operation to apply when applying color to texture + Colors - + - Construct a new BalanceEventArgs object + Represents alpha blending and bump infor for a visual parameter + such as sleive length - The currenct balance - + - Get the currenct balance + Create new alhpa information for a visual param + Stregth of the alpha to apply + File containing the alpha channel + Skip blending if parameter value is 0 + Use miltiply insted of alpha blending - - Contains the transaction summary when an item is purchased, - money is given, or land is purchased + + Stregth of the alpha to apply - + + File containing the alpha channel + + + Skip blending if parameter value is 0 + + + Use miltiply insted of alpha blending + + - Construct a new instance of the MoneyBalanceReplyEventArgs object + A single visual characteristic of an avatar mesh, such as eyebrow height - The ID of the transaction - True of the transaction was successful - The current currency balance - The meters credited - The meters comitted - A brief description of the transaction - - Get the ID of the transaction + + + Set all the values through the constructor + + Index of this visual param + Internal name + + + + + Displayable label of this characteristic + Displayable label for the minimum value of this characteristic + Displayable label for the maximum value of this characteristic + Default value + Minimum value + Maximum value + Is this param used for creation of bump layer? + Array of param IDs that are drivers for this parameter + Alpha blending/bump info + Color information - - True of the transaction was successful + + Index of this visual param - - Get the remaining currency balance + + Internal name - - Get the meters credited + + Group ID this parameter belongs to - - Get the meters comitted + + Name of the wearable this parameter belongs to - - Get the description of the transaction + + Displayable label of this characteristic - - Data sent from the simulator containing information about your agent and active group information + + Displayable label for the minimum value of this characteristic - - - Construct a new instance of the AgentDataReplyEventArgs object - - The agents first name - The agents last name - The agents active group ID - The group title of the agents active group - The combined group powers the agent has in the active group - The name of the group the agent has currently active + + Displayable label for the maximum value of this characteristic - - Get the agents first name + + Default value - - Get the agents last name + + Minimum value - - Get the active group ID of your agent + + Maximum value - - Get the active groups title of your agent + + Is this param used for creation of bump layer? - - Get the combined group powers of your agent + + Alpha blending/bump info - - Get the active group name of your agent + + Color information - - Data sent by the simulator to indicate the active/changed animations - applied to your agent + + Array of param IDs that are drivers for this parameter - + - Construct a new instance of the AnimationsChangedEventArgs class + Holds the Params array of all the avatar appearance parameters - The dictionary that contains the changed animations - - Get the dictionary that contains the changed animations + + + Base class for all Asset types + - + - Data sent from a simulator indicating a collision with your agent + Construct a new Asset object - + - Construct a new instance of the MeanCollisionEventArgs class + Construct a new Asset object - The type of collision that occurred - The ID of the agent or object that perpetrated the agression - The ID of the Victim - The strength of the collision - The Time the collision occurred + A unique specific to this asset + A byte array containing the raw asset data - - Get the Type of collision + + A byte array containing the raw asset data - - Get the ID of the agent or object that collided with your agent + + True if the asset it only stored on the server temporarily - - Get the ID of the agent that was attacked + + A unique ID - - A value indicating the strength of the collision + + The assets unique ID - - Get the time the collision occurred + + + The "type" of asset, Notecard, Animation, etc + - - Data sent to your agent when it crosses region boundaries + + + Regenerates the AssetData byte array from the properties + of the derived class. + + + + + Decodes the AssetData, placing it in appropriate properties of the derived + class. + + True if the asset decoding succeeded, otherwise false + + + + Constants for the archiving module + + + + + The location of the archive control file + + + + + Path for the assets held in an archive + + + + + Path for the prims file + + + + + Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. + - + - Construct a new instance of the RegionCrossedEventArgs class + Path for region settings. - The simulator your agent just left - The simulator your agent is now in - - - Get the simulator your agent just left - - Get the simulator your agent is now in + + + The character the separates the uuid from extension information in an archived asset filename + - - Data sent from the simulator when your agent joins a group chat session + + + Extensions used for asset types in the archive + - + - Construct a new instance of the GroupChatJoinedEventArgs class + Archives assets - The ID of the session - The name of the session - A temporary session id used for establishing new sessions - True of your agent successfully joined the session - - Get the ID of the group chat session + + + Archive assets + - - Get the name of the session + + + Archive the assets given to this archiver to the given archive. + + + - - Get the temporary session ID used for establishing new sessions + + + Write an assets metadata file to the given archive + + + - - True if your agent successfully joined the session + + + Write asset data files to the given archive + + + - - The session information when your agent exits a group chat session + + + Temporary code to do the bare minimum required to read a tar archive for our purposes + - + - Construct a new instance of the GroupChatLeftEventArgs class + Generate a tar reader which reads from the given stream. - The ID of the session your agent left + + - - Get the ID of the session your agent left + + + Binary reader for the underlying stream + - - Data sent by the simulator containing urgent messages + + + Used to trim off null chars + - + - Construct a new instance of the AlertMessageEventArgs class + Used to trim off space chars - The alert message - - Get the alert message + + + Read the next entry in the tar file. + + + + + + the data for the entry. Returns null if there are no more entries - - Data sent by a script requesting to take or release specified controls to your agent + + + Read the next 512 byte chunk of data as a tar header. + + A tar header struct. null if we have reached the end of the archive. - + - Construct a new instance of the ScriptControlEventArgs class + Read data following a header - The controls the script is attempting to take or release to the agent - True if the script is passing controls back to the agent - True if the script is requesting controls be released to the script + + + + - - Get the controls the script is attempting to take or release to the agent + + + Convert octal bytes to a decimal representation + + + + + + + + + - - True if the script is passing controls back to the agent + + + Temporary code to produce a tar archive in tar v7 format + - - True if the script is requesting controls be released to the script + + + Binary writer for the underlying stream + - + - Data sent from the simulator to an agent to indicate its view limits + Write a directory entry to the tar archive. We can only handle one path level right now! + + - + - Construct a new instance of the CameraConstraintEventArgs class + Write a file to the tar archive - The collision plane + + + + - - Get the collision plane + + + Write a file to the tar archive + + + + + - + - Data containing script sensor requests which allow an agent to know the specific details - of a primitive sending script sensor requests + Finish writing the raw tar archive data to a stream. The stream will be closed on completion. - + - Construct a new instance of the ScriptSensorReplyEventArgs + Write a particular entry - The ID of the primitive sending the sensor - The ID of the group associated with the primitive - The name of the primitive sending the sensor - The ID of the primitive sending the sensor - The ID of the owner of the primitive sending the sensor - The position of the primitive sending the sensor - The range the primitive specified to scan - The rotation of the primitive sending the sensor - The type of sensor the primitive sent - The velocity of the primitive sending the sensor + + + + + + - - Get the ID of the primitive sending the sensor + + + Represents an Animation + - - Get the ID of the group associated with the primitive + + Default Constructor - - Get the name of the primitive sending the sensor + + + Construct an Asset object of type Animation + + A unique specific to this asset + A byte array containing the raw asset data - - Get the ID of the primitive sending the sensor + + Override the base classes AssetType - - Get the ID of the owner of the primitive sending the sensor + + + Represents an that represents an avatars body ie: Hair, Etc. + - - Get the position of the primitive sending the sensor + + Initializes a new instance of an AssetBodyPart object - - Get the range the primitive specified to scan + + Initializes a new instance of an AssetBodyPart object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - Get the rotation of the primitive sending the sensor + + Override the base classes AssetType - - Get the type of sensor the primitive sent + + + Represents an that can be worn on an avatar + such as a Shirt, Pants, etc. + - - Get the velocity of the primitive sending the sensor + + Initializes a new instance of an AssetScriptBinary object - - Contains the response data returned from the simulator in response to a + + Initializes a new instance of an AssetScriptBinary object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - Construct a new instance of the AvatarSitResponseEventArgs object + + Override the base classes AssetType - - Get the ID of the primitive the agent will be sitting on + + + Type of gesture step + - - True if the simulator Autopilot functions were involved + + + Base class for gesture steps + - - Get the camera offset of the agent when seated + + + Retururns what kind of gesture step this is + - - Get the camera eye offset of the agent when seated + + + Describes animation step of a gesture + - - True of the agent will be in mouselook mode when seated + + + If true, this step represents start of animation, otherwise animation stop + - - Get the position of the agent when seated + + + Animation asset - - Get the rotation of the agent when seated + + + Animation inventory name + - - Data sent when an agent joins a chat session your agent is currently participating in + + + Returns what kind of gesture step this is + - + - Construct a new instance of the ChatSessionMemberAddedEventArgs object + Describes sound step of a gesture - The ID of the chat session - The ID of the agent joining - - Get the ID of the chat session + + + Sound asset - - Get the ID of the agent that joined + + + Sound inventory name + - - Data sent when an agent exits a chat session your agent is currently participating in + + + Returns what kind of gesture step this is + - + - Construct a new instance of the ChatSessionMemberLeftEventArgs object + Describes sound step of a gesture - The ID of the chat session - The ID of the Agent that left - - Get the ID of the chat session + + + Text to output in chat + - - Get the ID of the agent that left + + + Returns what kind of gesture step this is + - + - Identifier code for primitive types + Describes sound step of a gesture - - None + + + If true in this step we wait for all animations to finish + - - A Primitive + + + If true gesture player should wait for the specified amount of time + - - A Avatar + + + Time in seconds to wait if WaitForAnimation is false + - - Linden grass + + + Returns what kind of gesture step this is + - - Linden tree + + + Describes the final step of a gesture + - - A primitive that acts as the source for a particle stream + + + Returns what kind of gesture step this is + - - A Linden tree + + + Represents a sequence of animations, sounds, and chat actions + - + - Primary parameters for primitives such as Physics Enabled or Phantom + Constructs guesture asset - - Deprecated + + + Constructs guesture asset + + A unique specific to this asset + A byte array containing the raw asset data - - Whether physics are enabled for this object + + + Keyboard key that triggers the gestyre + - - + + + Modifier to the trigger key + - - + + + String that triggers playing of the gesture sequence + - - + + + Text that replaces trigger in chat once gesture is triggered + - - + + + Sequence of gesture steps + - - + + + Returns asset type + - - + + + Encodes gesture asset suitable for uplaod + - - Whether this object contains an active touch script + + + Decodes gesture assset into play sequence + + true if the asset data was decoded successfully - - + + + Represents a Landmark with RegionID and Position vector + - - Whether this object can receive payments + + Construct an Asset of type Landmark - - Whether this object is phantom (no collisions) + + + Construct an Asset object of type Landmark + + A unique specific to this asset + A byte array containing the raw asset data - - + + UUID of the Landmark target region - - + + Local position of the target - - + + Override the base classes AssetType - - + + + Encode the raw contents of a string with the specific Landmark format + - - Deprecated + + + Decode the raw asset data, populating the RegionID and Position + + true if the AssetData was successfully decoded to a UUID and Vector - - + + + Represents a string of characters encoded with specific formatting properties + - - + + Construct an Asset of type Notecard - - + + + Construct an Asset object of type Notecard + + A unique specific to this asset + A byte array containing the raw asset data - - Deprecated + + A text string containing main text of the notecard - - + + List of s embedded on the notecard - - + + Override the base classes AssetType - - + + + Encode the raw contents of a string with the specific Linden Text properties + - - + + + Decode the raw asset data including the Linden Text properties + + true if the AssetData was successfully decoded - - Server flag, will not be sent to clients. Specifies that - the object is destroyed when it touches a simulator edge + + + A linkset asset, containing a parent primitive and zero or more children + - - Server flag, will not be sent to clients. Specifies that - the object will be returned to the owner's inventory when it - touches a simulator edge + + Initializes a new instance of an AssetPrim object - - Server flag, will not be sent to clients. + + + Initializes a new instance of an AssetPrim object + + A unique specific to this asset + A byte array containing the raw asset data - - Server flag, will not be sent to client. Specifies that - the object is hovering/flying + + + Only used internally for XML serialization/deserialization + - - + + Override the base classes AssetType - - + + + - - + + + + + - - + + + The deserialized form of a single primitive in a linkset asset + - + - Sound flags for sounds attached to primitives + Represents an AssetScriptBinary object containing the + LSO compiled bytecode of an LSL script - - + + Initializes a new instance of an AssetScriptBinary object - - + + Initializes a new instance of an AssetScriptBinary object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - + + Override the base classes AssetType - - + + + TODO: Encodes a scripts contents into a LSO Bytecode file + - - + + + TODO: Decode LSO Bytecode into a string + + true - - + + + Represents an LSL Text object containing a string of UTF encoded characters + - - + + Initializes a new AssetScriptText object - + - Material type for a primitive + Initializes a new AssetScriptText object with parameters + A unique specific to this asset + A byte array containing the raw asset data + + + A string of characters represting the script contents - - + + Override the base classes AssetType - - + + + Encode a string containing the scripts contents into byte encoded AssetData + - - + + + Decode a byte array containing the scripts contents into a string + + true if decoding is successful - - + + + Represents a Sound Asset + - - + + Initializes a new instance of an AssetSound object - - + + Initializes a new instance of an AssetSound object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - + + Override the base classes AssetType - - + + + TODO: Encodes a sound file + - + - Used in a helper function to roughly determine prim shape + TODO: Decode a sound file + true - + - Extra parameters for primitives, these flags are for features that have - been added after the original ObjectFlags that has all eight bits - reserved already + Represents a texture - - Whether this object has flexible parameters - - - Whether this object has light parameters - - - Whether this object is a sculpted prim + + Initializes a new instance of an AssetTexture object - + - + Initializes a new instance of an AssetTexture object + A unique specific to this asset + A byte array containing the raw asset data - - - - - - - - - - + - + Initializes a new instance of an AssetTexture object + A object containing texture data - - - - - - - - - - - - - - - - - - - - + + A object containing image data - + - - - - - - - - - - - - - - - + + + - - + + Override the base classes AssetType - - + + + Populates the byte array with a JPEG2000 + encoded image created from the data in - - + + + Decodes the JPEG2000 data in AssetData to the + object + True if the decoding was successful, otherwise false - - + + + Decodes the begin and end byte positions for each quality layer in + the image + + + - + - + Represents a Wearable Asset, Clothing, Hair, Skin, Etc - - + + Initializes a new instance of an AssetWearable object - - + + Initializes a new instance of an AssetWearable object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - + + A string containing the name of the asset - - + + A string containing a short description of the asset - - + + The Assets WearableType - - + + The For-Sale status of the object - - + + An Integer representing the purchase price of the asset - - - Attachment points for objects on avatar bodies - - - Both InventoryObject and InventoryAttachment types can be attached - + + The of the assets creator - - Right hand if object was not previously attached + + The of the assets current owner - - Chest + + The of the assets prior owner - - Skull + + The of the Group this asset is set to - - Left shoulder + + True if the asset is owned by a - - Right shoulder + + The Permissions mask of the asset - - Left hand + + A Dictionary containing Key/Value pairs of the objects parameters - - Right hand + + A Dictionary containing Key/Value pairs where the Key is the textures Index and the Value is the Textures - - Left foot + + + Decode an assets byte encoded data to a string + + true if the asset data was decoded successfully - - Right foot + + + Encode the assets string represantion into a format consumable by the asset server + - - Spine + + = - - Pelvis + + Number of times we've received an unknown CAPS exception in series. - - Mouth + + For exponential backoff on error. - - Chin + + + A set of textures that are layered on texture of each other and "baked" + in to a single texture, for avatar appearances + - - Left ear + + + Default constructor + + Bake type - - Right ear + + Final baked texture - - Left eyeball + + Component layers - - Right eyeball + + Width of the final baked image and scratchpad - - Nose + + Height of the final baked image and scratchpad - - Right upper arm + + Bake type - - Right forearm + + Final baked texture - - Left upper arm + + Component layers - - Left forearm + + Width of the final baked image and scratchpad - - Right hip + + Height of the final baked image and scratchpad - - Right upper leg + + Bake type - - Right lower leg + + Is this one of the 3 skin bakes - - Left hip + + + Adds layer for baking + + TexturaData struct that contains texture and its params - - Left upper leg + + + Converts avatar texture index (face) to Bake type + + Face number (AvatarTextureIndex) + BakeType, layer to which this texture belongs to - - Left lower leg + + + Make sure images exist, resize source if needed to match the destination + + Destination image + Source image + Sanitization was succefull - - Stomach + + + Fills a baked layer as a solid *appearing* color. The colors are + subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from + compressing it too far since it seems to cause upload failures if + the image is a pure solid color + + Color of the base of this layer - - Left pectoral + + + Fills a baked layer as a solid *appearing* color. The colors are + subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from + compressing it too far since it seems to cause upload failures if + the image is a pure solid color + + Red value + Green value + Blue value - - Right pectoral + + + Create a new blank image + + width + height + channel flags - - HUD Center position 2 + + + + + - - HUD Top-right + + + Image width + - - HUD Top + + + Image height + - - HUD Top-left + + + Image channel flags + - - HUD Center + + + Red channel data + - - HUD Bottom-left + + + Green channel data + - - HUD Bottom + + + Blue channel data + - - HUD Bottom-right + + + Alpha channel data + - + - Tree foliage types + Bump channel data - - Pine1 tree + + + Convert the channels in the image. Channels are created or destroyed as required. + + new channel flags - - Oak tree + + + Resize or stretch the image using nearest neighbor (ugly) resampling + + new width + new height - - Tropical Bush1 + + + Create a byte array containing 32-bit RGBA data with a bottom-left + origin, suitable for feeding directly into OpenGL + + A byte array containing raw texture data - - Palm1 tree + + + A Wrapper around openjpeg to encode and decode images to and from byte arrays + - - Dogwood tree + + + Defines the beginning and ending file positions of a layer in an + LRCP-progression JPEG2000 file + - - Tropical Bush2 + + + This structure is used to marshal both encoded and decoded images. + MUST MATCH THE STRUCT IN dotnet.h! + - - Palm2 tree + + + Information about a single packet in a JPEG2000 stream + - - Cypress1 tree + + Packet start position - - Cypress2 tree + + Packet header end position - - Pine2 tree + + Packet end position - - Plumeria + + TGA Header size - - Winter pinetree1 + + OpenJPEG is not threadsafe, so this object is used to lock + during calls into unmanaged code - - Winter Aspen tree + + + Encode a object into a byte array + + The object to encode + true to enable lossless conversion, only useful for small images ie: sculptmaps + A byte array containing the encoded Image object - - Winter pinetree2 + + + Encode a object into a byte array + + The object to encode + a byte array of the encoded image - - Eucalyptus tree + + + Decode JPEG2000 data to an and + + JPEG2000 encoded data + ManagedImage object to decode to + Image object to decode to + True if the decode succeeds, otherwise false - - Fern + + + + + + + + + - - Eelgrass + + + + + + + + + + + - - Sea Sword + + + Encode a object into a byte array + + The source object to encode + true to enable lossless decoding + A byte array containing the source Bitmap object - - Kelp1 plant + + + Capability to load TGAs to Bitmap + - - Beach grass + + + Interface requirements for Messaging system + - - Kelp2 plant + + + Abstract base for rendering plugins + - + - Grass foliage types + Generates a basic mesh structure from a primitive + Primitive to generate the mesh from + Level of detail to generate the mesh at + The generated mesh - - + + + Generates a basic mesh structure from a sculpted primitive and + texture + + Sculpted primitive to generate the mesh from + Sculpt texture + Level of detail to generate the mesh at + The generated mesh - - + + + Generates a series of faces, each face containing a mesh and + metadata + + Primitive to generate the mesh from + Level of detail to generate the mesh at + The generated mesh - - + + + Generates a series of faces for a sculpted prim, each face + containing a mesh and metadata + + Sculpted primitive to generate the mesh from + Sculpt texture + Level of detail to generate the mesh at + The generated mesh - - + + + Apply texture coordinate modifications from a + to a list of vertices + + Vertex list to modify texture coordinates for + Center-point of the face + Face texture parameters - - + + + Sent to the client to indicate a teleport request has completed + - - + + The of the agent - + - Action associated with clicking on an object - - Touch object - - - Sit on object + + The simulators handle the agent teleported to - - Purchase object or contents + + A Uri which contains a list of Capabilities the simulator supports - - Pay the object + + Indicates the level of access required + to access the simulator, or the content rating, or the simulators + map status - - Open task inventory + + The IP Address of the simulator - - Play parcel media + + The UDP Port the simulator will listen for UDP traffic on - - Open parcel media + + Status flags indicating the state of the Agent upon arrival, Flying, etc. - + - A set of textures that are layered on texture of each other and "baked" - in to a single texture, for avatar appearances + Serialize the object + An containing the objects data - - Final baked texture - - - Component layers - - - Width of the final baked image and scratchpad - - - Height of the final baked image and scratchpad - - - Bake type - - + - Default constructor + Deserialize the message - Bake type + An containing the data - + - Adds layer for baking + Sent to the viewer when a neighboring simulator is requesting the agent make a connection to it. - TexturaData struct that contains texture and its params - + - Converts avatar texture index (face) to Bake type + Serialize the object - Face number (AvatarTextureIndex) - BakeType, layer to which this texture belongs to + An containing the objects data - + - Make sure images exist, resize source if needed to match the destination + Deserialize the message - Destination image - Source image - Sanitization was succefull + An containing the data - + - Fills a baked layer as a solid *appearing* color. The colors are - subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from - compressing it too far since it seems to cause upload failures if - the image is a pure solid color + Serialize the object - Color of the base of this layer + An containing the objects data - + - Fills a baked layer as a solid *appearing* color. The colors are - subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from - compressing it too far since it seems to cause upload failures if - the image is a pure solid color + Deserialize the message - Red value - Green value - Blue value - - - Final baked texture - - - Component layers - - - Width of the final baked image and scratchpad - - - Height of the final baked image and scratchpad - - - Bake type - - - Is this one of the 3 skin bakes - - - The event subscribers. null if no subcribers - - - Raises the LandPatchReceived event - A LandPatchReceivedEventArgs object containing the - data returned from the simulator + An containing the data - - Thread sync lock object + + + Serialize the object + + An containing the objects data - + - Default constructor + Deserialize the message - + An containing the data - + - Retrieve the terrain height at a given coordinate + A message sent to the client which indicates a teleport request has failed + and contains some information on why it failed - The region that the point of interest is in - Sim X coordinate, valid range is from 0 to 255 - Sim Y coordinate, valid range is from 0 to 255 - The terrain height at the given point if the - lookup was successful, otherwise 0.0f - True if the lookup was successful, otherwise false - - Raised when the simulator responds sends + + + - - Simulator from that sent tha data + + A string key of the reason the teleport failed e.g. CouldntTPCloser + Which could be used to look up a value in a dictionary or enum - - Sim coordinate of the patch + + The of the Agent - - Sim coordinate of the patch + + A string human readable message containing the reason + An example: Could not teleport closer to destination - - Size of tha patch + + + Serialize the object + + An containing the objects data - - Heightmap for the patch + + + Deserialize the message + + An containing the data - + - The InternalDictionary class is used through the library for storing key/value pairs. - It is intended to be a replacement for the generic Dictionary class and should - be used in its place. It contains several methods for allowing access to the data from - outside the library that are read only and thread safe. - + Serialize the object - Key - Value + An containing the objects data - - Internal dictionary that this class wraps around. Do not - modify or enumerate the contents of this dictionary without locking - on this member + + + Deserialize the message + + An containing the data - + - Initializes a new instance of the Class - with the specified key/value, has the default initial capacity. + Contains a list of prim owner information for a specific parcel in a simulator - - - // initialize a new InternalDictionary named testDict with a string as the key and an int as the value. - public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(); - - + + A Simulator will always return at least 1 entry + If agent does not have proper permission the OwnerID will be UUID.Zero + If agent does not have proper permission OR there are no primitives on parcel + the DataBlocksExtended map will not be sent from the simulator + - + - Initializes a new instance of the Class - with the specified key/value, has its initial valies copied from the specified - + Prim ownership information for a specified owner on a single parcel - - to copy initial values from - - - // initialize a new InternalDictionary named testAvName with a UUID as the key and an string as the value. - // populates with copied values from example KeyNameCache Dictionary. - - // create source dictionary - Dictionary<UUID, string> KeyNameCache = new Dictionary<UUID, string>(); - KeyNameCache.Add("8300f94a-7970-7810-cf2c-fc9aa6cdda24", "Jack Avatar"); - KeyNameCache.Add("27ba1e40-13f7-0708-3e98-5819d780bd62", "Jill Avatar"); - - // Initialize new dictionary. - public InternalDictionary<UUID, string> testAvName = new InternalDictionary<UUID, string>(KeyNameCache); - - - + + The of the prim owner, + UUID.Zero if agent has no permission to view prim owner information + + + The total number of prims + + + True if the OwnerID is a + + + True if the owner is online + This is no longer used by the LL Simulators + + + The date the most recent prim was rezzed + + + An Array of objects + + - Initializes a new instance of the Class - with the specified key/value, With its initial capacity specified. + Serialize the object - Initial size of dictionary - - - // initialize a new InternalDictionary named testDict with a string as the key and an int as the value, - // initially allocated room for 10 entries. - public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(10); - - + An containing the objects data - + - Try to get entry from with specified key + Deserialize the message - Key to use for lookup - Value returned - if specified key exists, if not found - - - // find your avatar using the Simulator.ObjectsAvatars InternalDictionary: - Avatar av; - if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) - Console.WriteLine("Found Avatar {0}", av.Name); - - - + An containing the data - + - Finds the specified match. + The details of a single parcel in a region, also contains some regionwide globals - The match. - Matched value - - - // use a delegate to find a prim in the ObjectsPrimitives InternalDictionary - // with the ID 95683496 - uint findID = 95683496; - Primitive findPrim = sim.ObjectsPrimitives.Find( - delegate(Primitive prim) { return prim.ID == findID; }); - - - - Find All items in an - return matching items. - a containing found items. - - Find All prims within 20 meters and store them in a List - - int radius = 20; - List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( - delegate(Primitive prim) { - Vector3 pos = prim.Position; - return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); - } - ); - - + + Simulator-local ID of this parcel - - Find All items in an - return matching keys. - a containing found keys. - - Find All keys which also exist in another dictionary - - List<UUID> matches = myDict.FindAll( - delegate(UUID id) { - return myOtherDict.ContainsKey(id); - } - ); - - + + Maximum corner of the axis-aligned bounding box for this + parcel - - Perform an on each entry in an - to perform - - - // Iterates over the ObjectsPrimitives InternalDictionary and prints out some information. - Client.Network.CurrentSim.ObjectsPrimitives.ForEach( - delegate(Primitive prim) - { - if (prim.Text != null) - { - Console.WriteLine("NAME={0} ID = {1} TEXT = '{2}'", - prim.PropertiesFamily.Name, prim.ID, prim.Text); - } - }); - - + + Minimum corner of the axis-aligned bounding box for this + parcel - - Perform an on each key of an - to perform + + Total parcel land area - + - Perform an on each KeyValuePair of an - to perform - - Check if Key exists in Dictionary - Key to check for - if found, otherwise + + Key of authorized buyer - - Check if Value exists in Dictionary - Value to check for - if found, otherwise + + Bitmap describing land layout in 4x4m squares across the + entire region - + - Adds the specified key to the dictionary, dictionary locking is not performed, - - The key - The value - - - Removes the specified key, dictionary locking is not performed - - The key. - if successful, otherwise + + Date land was claimed - - - Gets the number of Key/Value pairs contained in the - + + Appears to always be zero - + + Parcel Description + + - Indexer for the dictionary - The key - The value - + - Avatar group management - - Key of Group Member - - - Total land contribution - - - Online status information - - - Abilities that the Group Member has - - - Current group title + + Total number of primitives owned by the parcel group on + this parcel - - Is a group owner + + Whether the land is deeded to a group or not - + - Role manager for a group - - Key of the group + + Maximum number of primitives this parcel supports - - Key of Role + + The Asset UUID of the Texture which when applied to a + primitive will display the media - - Name of Role + + A URL which points to any Quicktime supported media type - - Group Title associated with Role + + A byte, if 0x1 viewer should auto scale media to fit object - - Description of Role + + URL For Music Stream - - Abilities Associated with Role + + Parcel Name - - Returns the role's title - The role's title + + Autoreturn value in minutes for others' objects - + - Class to represent Group Title - - Key of the group - - - ID of the role title belongs to - - - Group Title + + Total number of other primitives on this parcel - - Whether title is Active + + UUID of the owner of this parcel - - Returns group title + + Total number of primitives owned by the parcel owner on + this parcel - + - Represents a group on the grid - - Key of Group - - - Key of Group Insignia + + How long is pass valid for - - Key of Group Founder + + Price for a temporary pass - - Key of Group Role for Owners + + + - - Name of Group + + + - - Text of Group Charter + + + - - Title of "everyone" role + + + - - Is the group open for enrolement to everyone + + True if the region denies access to age unverified users - - Will group show up in search + + + - - + + This field is no longer used - - + + The result of a request for parcel properties + + Sale price of the parcel, only useful if ForSale is set + The SalePrice will remain the same after an ownership + transfer (sale), so it can be used to see the purchase price after + a sale if the new owner has not changed it - - + + + Number of primitives your avatar is currently + selecting and sitting on in this parcel + - - Is the group Mature + + + - - Cost of group membership + + + A number which increments by 1, starting at 0 for each ParcelProperties request. + Can be overriden by specifying the sequenceID with the ParcelPropertiesRequest being sent. + a Negative number indicates the action in has occurred. + - - + + Maximum primitives across the entire simulator - - + + Total primitives across the entire simulator - - The total number of current members this group has + + + - - The number of roles this group has configured + + Key of parcel snapshot - - Show this group in agent's profile + + Parcel ownership status - - Returns the name of the group - A string containing the name of the group + + Total number of primitives on this parcel - + - A group Vote - - Key of Avatar who created Vote + + + - - Text of the Vote proposal + + A description of the media - - Total number of votes + + An Integer which represents the height of the media - - - A group proposal - + + An integer which represents the width of the media - - The Text of the proposal + + A boolean, if true the viewer should loop the media - - The minimum number of members that must vote before proposal passes or failes + + A string which contains the mime type of the media - - The required ration of yes/no votes required for vote to pass - The three options are Simple Majority, 2/3 Majority, and Unanimous - TODO: this should be an enum + + true to obscure (hide) media url - - The duration in days votes are accepted + + true to obscure (hide) music url - + - + Serialize the object + An containing the objects data - - - - - - - - + + + Deserialize the message + + An containing the data - - + + A message sent from the viewer to the simulator to updated a specific parcels settings - - + + The of the agent authorized to purchase this + parcel of land or a NULL if the sale is authorized to anyone - - + + true to enable auto scaling of the parcel media - - + + The category of this parcel used when search is enabled to restrict + search results - - + + A string containing the description to set - - + + The of the which allows for additional + powers and restrictions. - - + + The which specifies how avatars which teleport + to this parcel are handled - - + + The LocalID of the parcel to update settings on - - + + A string containing the description of the media which can be played + to visitors - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - - + + + - + - Struct representing a group notice - - + + + - - + + + - - + + + - - + + + - + - - - + - Struct representing a group notice list entry - - Notice ID + + + - - Creation timestamp of notice + + + - - Agent name who created notice + + + - - Notice subject + + + Deserialize the message + + An containing the data - - Is there an attachment? + + + Serialize the object + + An containing the objects data - - Attachment Type + + Base class used for the RemoteParcelRequest message - + - Struct representing a member of a group chat session and their settings + A message sent from the viewer to the simulator to request information + on a remote parcel - - The of the Avatar + + Local sim position of the parcel we are looking up - - True if user has voice chat enabled + + Region handle of the parcel we are looking up - - True of Avatar has moderator abilities + + Region of the parcel we are looking up - - True if a moderator has muted this avatars chat + + + Serialize the object + + An containing the objects data - - True if a moderator has muted this avatars voice + + + Deserialize the message + + An containing the data - + - Role update flags + A message sent from the simulator to the viewer in response to a + which will contain parcel information - - + + The grid-wide unique parcel ID - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - + + + A message containing a request for a remote parcel from a viewer, or a response + from the simulator to that request + - - + + The request or response details block - - + + + Serialize the object + + An containing the objects data - - + + + Deserialize the message + + An containing the data - - Can send invitations to groups default role + + + Serialize the object + + An containing the objects data - - Can eject members from group + + + Deserialize the message + + An containing the data - - Can toggle 'Open Enrollment' and change 'Signup fee' + + + Serialize the object + + An containing the objects data - - Member is visible in the public member list + + + Deserialize the message + + An containing the data + + + + A message sent from the simulator to an agent which contains + the groups the agent is in + - - Can create new roles + + Group Details specific to the agent - - Can delete existing roles + + true of the agent accepts group notices - - Can change Role names, titles and descriptions + + The agents tier contribution to the group - - Can assign other members to assigners role + + The Groups - - Can assign other members to any role + + The of the groups insignia - - Can remove members from roles + + The name of the group - - Can assign and remove abilities in roles + + The aggregate permissions the agent has in the group for all roles the agent + is assigned - - Can change group Charter, Insignia, 'Publish on the web' and which - members are publicly visible in group member listings + + An optional block containing additional agent specific information - - Can buy land or deed land to group + + true of the agent allows this group to be + listed in their profile - - Can abandon group owned land to Governor Linden on mainland, or Estate owner for - private estates + + The Agent receiving the message - - Can set land for-sale information on group owned parcels + + An array containing information + for each the agent is a member of - - Can subdivide and join parcels + + An array containing information + for each the agent is a member of - - Can join group chat sessions + + + Serialize the object + + An containing the objects data - - Can use voice chat in Group Chat sessions + + + Deserialize the message + + An containing the data - - Can moderate group chat sessions + + + A message sent from the viewer to the simulator which + specifies the language and permissions for others to detect + the language specified + - - Can toggle "Show in Find Places" and set search category + + A string containng the default language + to use for the agent - - Can change parcel name, description, and 'Publish on web' settings + + true of others are allowed to + know the language setting - - Can set the landing point and teleport routing on group land + + + Serialize the object + + An containing the objects data - - Can change music and media settings + + + Deserialize the message + + An containing the data - - Can toggle 'Edit Terrain' option in Land settings + + + An EventQueue message sent from the simulator to an agent when the agent + leaves a group + - - Can toggle various About Land > Options settings + + An object containing the Agents UUID, and the Groups UUID - - Can always terraform land, even if parcel settings have it turned off + + The ID of the Agent leaving the group - - Can always fly while over group owned land + + The GroupID the Agent is leaving - - Can always rez objects on group owned land + + + An Array containing the AgentID and GroupID + - - Can always create landmarks for group owned parcels + + + Serialize the object + + An containing the objects data - - Can set home location on any group owned parcel + + + Deserialize the message + + An containing the data - - Can modify public access settings for group owned parcels + + Base class for Asset uploads/results via Capabilities - - Can manager parcel ban lists on group owned land + + + The request state + - - Can manage pass list sales information + + + Serialize the object + + An containing the objects data - - Can eject and freeze other avatars on group owned land + + + Deserialize the message + + An containing the data - - Can return objects set to group + + + A message sent from the viewer to the simulator to request a temporary upload capability + which allows an asset to be uploaded + - - Can return non-group owned/set objects + + The Capability URL sent by the simulator to upload the baked texture to - - Can return group owned objects + + + A message sent from the simulator that will inform the agent the upload is complete, + and the UUID of the uploaded asset + - - Can landscape using Linden plants + + The uploaded texture asset ID - - Can deed objects to group + + + A message sent from the viewer to the simulator to request a temporary + capability URI which is used to upload an agents baked appearance textures + - - Can move group owned objects + + Object containing request or response - - Can set group owned objects for-sale + + + Serialize the object + + An containing the objects data - - Pay group liabilities and receive group dividends + + + Deserialize the message + + An containing the data - - Can send group notices + + + A message sent from the simulator which indicates the minimum version required for + using voice chat + - - Can receive group notices + + Major Version Required - - Can create group proposals + + Minor version required - - Can vote on group proposals + + The name of the region sending the version requrements - + - Handles all network traffic related to reading and writing group - information + Serialize the object + An containing the objects data - - The event subscribers. null if no subcribers - - - Raises the CurrentGroups event - A CurrentGroupsEventArgs object containing the - data sent from the simulator - - - Thread sync lock object + + + Deserialize the message + + An containing the data - - The event subscribers. null if no subcribers + + + A message sent from the simulator to the viewer containing the + voice server URI + - - Raises the GroupNamesReply event - A GroupNamesEventArgs object containing the - data response from the simulator + + The Parcel ID which the voice server URI applies - - Thread sync lock object + + The name of the region - - The event subscribers. null if no subcribers + + A uri containing the server/channel information + which the viewer can utilize to participate in voice conversations - - Raises the GroupProfile event - An GroupProfileEventArgs object containing the - data returned from the simulator + + + Serialize the object + + An containing the objects data - - Thread sync lock object + + + Deserialize the message + + An containing the data - - The event subscribers. null if no subcribers + + + - - Raises the GroupMembers event - A GroupMembersEventArgs object containing the - data returned from the simulator + + + - - Thread sync lock object + + + - - The event subscribers. null if no subcribers + + + Serialize the object + + An containing the objects data - - Raises the GroupRolesDataReply event - A GroupRolesDataReplyEventArgs object containing the - data returned from the simulator + + + Deserialize the message + + An containing the data - - Thread sync lock object + + + A message sent by the viewer to the simulator to request a temporary + capability for a script contained with in a Tasks inventory to be updated + - - The event subscribers. null if no subcribers + + Object containing request or response - - Raises the GroupRoleMembersReply event - A GroupRolesRoleMembersReplyEventArgs object containing the - data returned from the simulator + + + Serialize the object + + An containing the objects data - - Thread sync lock object + + + Deserialize the message + + An containing the data - - The event subscribers. null if no subcribers + + + A message sent from the simulator to the viewer to indicate + a Tasks scripts status. + - - Raises the GroupTitlesReply event - A GroupTitlesReplyEventArgs object containing the - data returned from the simulator + + The Asset ID of the script - - Thread sync lock object + + True of the script is compiled/ran using the mono interpreter, false indicates it + uses the older less efficient lsl2 interprter - - The event subscribers. null if no subcribers + + The Task containing the scripts - - Raises the GroupAccountSummary event - A GroupAccountSummaryReplyEventArgs object containing the - data returned from the simulator + + true of the script is in a running state - - Thread sync lock object + + + Serialize the object + + An containing the objects data - - The event subscribers. null if no subcribers + + + Deserialize the message + + An containing the data - - Raises the GroupCreated event - An GroupCreatedEventArgs object containing the - data returned from the simulator + + + A message containing the request/response used for updating a gesture + contained with an agents inventory + - - Thread sync lock object + + Object containing request or response - - The event subscribers. null if no subcribers + + + Serialize the object + + An containing the objects data - - Raises the GroupJoined event - A GroupOperationEventArgs object containing the - result of the operation returned from the simulator + + + Deserialize the message + + An containing the data - - Thread sync lock object + + + A message request/response which is used to update a notecard contained within + a tasks inventory + - - The event subscribers. null if no subcribers + + The of the Task containing the notecard asset to update - - Raises the GroupLeft event - A GroupOperationEventArgs object containing the - result of the operation returned from the simulator + + The notecard assets contained in the tasks inventory - - Thread sync lock object + + + Serialize the object + + An containing the objects data - - The event subscribers. null if no subcribers + + + Deserialize the message + + An containing the data - - Raises the GroupDropped event - An GroupDroppedEventArgs object containing the - the group your agent left + + + A reusable class containing a message sent from the viewer to the simulator to request a temporary uploader capability + which is used to update an asset in an agents inventory + - - Thread sync lock object + + + The Notecard AssetID to replace + - - The event subscribers. null if no subcribers + + + Serialize the object + + An containing the objects data - - Raises the GroupMemberEjected event - An GroupMemberEjectedEventArgs object containing the - data returned from the simulator + + + Deserialize the message + + An containing the data - - Thread sync lock object + + + A message containing the request/response used for updating a notecard + contained with an agents inventory + - - The event subscribers. null if no subcribers + + Object containing request or response - - Raises the GroupNoticesListReply event - An GroupNoticesListReplyEventArgs object containing the - data returned from the simulator + + + Serialize the object + + An containing the objects data - - Thread sync lock object + + + Deserialize the message + + An containing the data - - The event subscribers. null if no subcribers + + + Serialize the object + + An containing the objects data - - Raises the GroupInvitation event - An GroupInvitationEventArgs object containing the - data returned from the simulator + + + Deserialize the message + + An containing the data - - Thread sync lock object + + + A message sent from the simulator to the viewer which indicates + an error occurred while attempting to update a script in an agents or tasks + inventory + - - A reference to the current instance + + true of the script was successfully compiled by the simulator - - Currently-active group members requests + + A string containing the error which occured while trying + to update the script - - Currently-active group roles requests + + A new AssetID assigned to the script - - Currently-active group role-member requests + + + A message sent from the viewer to the simulator + requesting the update of an existing script contained + within a tasks inventory + - - Dictionary keeping group members while request is in progress + + if true, set the script mode to running - - Dictionary keeping mebmer/role mapping while request is in progress + + The scripts InventoryItem ItemID to update - - Dictionary keeping GroupRole information while request is in progress + + A lowercase string containing either "mono" or "lsl2" which + specifies the script is compiled and ran on the mono runtime, or the older + lsl runtime - - Caches group name lookups + + The tasks which contains the script to update - + - Construct a new instance of the GroupManager class + Serialize the object - A reference to the current instance + An containing the objects data - + - Request a current list of groups the avatar is a member of. + Deserialize the message - CAPS Event Queue must be running for this to work since the results - come across CAPS. + An containing the data - + - Lookup name of group based on groupID + A message containing either the request or response used in updating a script inside + a tasks inventory - groupID of group to lookup name for. - + + Object containing request or response + + - Request lookup of multiple group names + Serialize the object - List of group IDs to request. - - - Lookup group profile data such as name, enrollment, founder, logo, etc - Subscribe to OnGroupProfile event to receive the results. - group ID (UUID) - - - Request a list of group members. - Subscribe to OnGroupMembers event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache - - - Request group roles - Subscribe to OnGroupRoles event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + An containing the objects data - - Request members (members,role) role mapping for a group. - Subscribe to OnGroupRolesMembers event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + + Deserialize the message + + An containing the data - - Request a groups Titles - Subscribe to OnGroupTitles event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + + Response from the simulator to notify the viewer the upload is completed, and + the UUID of the script asset and its compiled status + - - Begin to get the group account summary - Subscribe to the OnGroupAccountSummary event to receive the results. - group ID (UUID) - How long of an interval - Which interval (0 for current, 1 for last) + + The uploaded texture asset ID - - Invites a user to a group - The group to invite to - A list of roles to invite a person to - Key of person to invite + + true of the script was compiled successfully - - Set a group as the current active group - group ID (UUID) + + + A message sent from a viewer to the simulator requesting a temporary uploader capability + used to update a script contained in an agents inventory + - - Change the role that determines your active title - Group ID to use - Role ID to change to + + The existing asset if of the script in the agents inventory to replace - - Set this avatar's tier contribution - Group ID to change tier in - amount of tier to donate + + The language of the script + Defaults to lsl version 2, "mono" might be another possible option - + - Save wheather agent wants to accept group notices and list this group in their profile + Serialize the object - Group - Accept notices from this group - List this group in the profile - - - Request to join a group - Subscribe to OnGroupJoined event for confirmation. - group ID (UUID) to join. + An containing the objects data - + - Request to create a new group. If the group is successfully - created, L$100 will automatically be deducted + Deserialize the message - Subscribe to OnGroupCreated event to receive confirmation. - Group struct containing the new group info - - - Update a group's profile and other information - Groups ID (UUID) to update. - Group struct to update. - - - Eject a user from a group - Group ID to eject the user from - Avatar's key to eject + An containing the data - - Update role information - Modified role to be updated - - - Create a new group role - Group ID to update - Role to create + + + A message containing either the request or response used in updating a script inside + an agents inventory + - - Delete a group role - Group ID to update - Role to delete + + Object containing request or response - - Remove an avatar from a role - Group ID to update - Role ID to be removed from - Avatar's Key to remove + + + Serialize the object + + An containing the objects data - - Assign an avatar to a role - Group ID to update - Role ID to assign to - Avatar's ID to assign to role + + + Deserialize the message + + An containing the data - - Request the group notices list - Group ID to fetch notices for + + + Serialize the object + + An containing the objects data - - Request a group notice by key - ID of group notice + + + Deserialize the message + + An containing the data - - Send out a group notice - Group ID to update - GroupNotice structure containing notice data + + Base class for Map Layers via Capabilities - - Start a group proposal (vote) - The Group ID to send proposal to - GroupProposal structure containing the proposal + + + - - Request to leave a group - Subscribe to OnGroupLeft event to receive confirmation - The group to leave + + + Serialize the object + + An containing the objects data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Deserialize the message + + An containing the data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Sent by an agent to the capabilities server to request map layers + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + A message sent from the simulator to the viewer which contains an array of map images and their grid coordinates + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + An object containing map location details + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The Asset ID of the regions tile overlay - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The grid location of the southern border of the map tile - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The grid location of the western border of the map tile - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The grid location of the eastern border of the map tile - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The grid location of the northern border of the map tile - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + An array containing LayerData items - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Serialize the object + + An containing the objects data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Deserialize the message + + An containing the data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Object containing request or response - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Serialize the object + + An containing the objects data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Deserialize the message + + An containing the data - - Raised when the simulator sends us data containing - our current group membership + + + New as of 1.23 RC1, no details yet. + - - Raised when the simulator responds to a RequestGroupName - or RequestGroupNames request + + + Serialize the object + + An containing the objects data - - Raised when the simulator responds to a request + + + Deserialize the message + + An containing the data - - Raised when the simulator responds to a request + + + Serialize the object + + An containing the objects data - - Raised when the simulator responds to a request + + + Deserialize the message + + An containing the data - - Raised when the simulator responds to a request + + A string containing the method used - - Raised when the simulator responds to a request + + + A request sent from an agent to the Simulator to begin a new conference. + Contains a list of Agents which will be included in the conference + - - Raised when a response to a RequestGroupAccountSummary is returned - by the simulator + + An array containing the of the agents invited to this conference - - Raised when a request to create a group is successful + + The conferences Session ID - - Raised when a request to join a group either - fails or succeeds + + + Serialize the object + + An containing the objects data - - Raised when a request to leave a group either - fails or succeeds + + + Deserialize the message + + An containing the data - - Raised when A group is removed from the group server + + + A moderation request sent from a conference moderator + Contains an agent and an optional action to take + - - Raised when a request to eject a member from a group either - fails or succeeds + + The Session ID - - Raised when the simulator sends us group notices - + + + - - Raised when another agent invites our avatar to join a group + + A list containing Key/Value pairs, known valid values: + key: text value: true/false - allow/disallow specified agents ability to use text in session + key: voice value: true/false - allow/disallow specified agents ability to use voice in session + + "text" or "voice" - - Contains the current groups your agent is a member of + + + - - Construct a new instance of the CurrentGroupsEventArgs class - The current groups your agent is a member of + + + Serialize the object + + An containing the objects data - - Get the current groups your agent is a member of + + + Deserialize the message + + An containing the data - - A Dictionary of group names, where the Key is the groups ID and the value is the groups name + + + A message sent from the agent to the simulator which tells the + simulator we've accepted a conference invitation + - - Construct a new instance of the GroupNamesEventArgs class - The Group names dictionary + + The conference SessionID - - Get the Group Names dictionary + + + Serialize the object + + An containing the objects data - - Represents the members of a group + + + Deserialize the message + + An containing the data - + - Construct a new instance of the GroupMembersReplyEventArgs class + Serialize the object - The ID of the request - The ID of the group - The membership list of the group + An containing the objects data - - Get the ID as returned by the request to correlate - this result set and the request + + + Deserialize the message + + An containing the data - - Get the ID of the group + + + Serialize the object + + An containing the objects data - - Get the dictionary of members + + + Deserialize the message + + An containing the data - - Represents the roles associated with a group + + + Serialize the object + + An containing the objects data - - Construct a new instance of the GroupRolesDataReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The dictionary containing the roles + + + Deserialize the message + + An containing the data - - Get the ID as returned by the request to correlate - this result set and the request + + Key of sender - - Get the ID of the group + + Name of sender - - Get the dictionary containing the roles + + Key of destination avatar - - Represents the Role to Member mappings for a group + + ID of originating estate - - Construct a new instance of the GroupRolesMembersReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The member to roles map + + Key of originating region - - Get the ID as returned by the request to correlate - this result set and the request + + Coordinates in originating region - - Get the ID of the group + + Instant message type - - Get the member to roles map + + Group IM session toggle - - Represents the titles for a group + + Key of IM session, for Group Messages, the groups UUID - - Construct a new instance of the GroupTitlesReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The titles + + Timestamp of the instant message - - Get the ID as returned by the request to correlate - this result set and the request + + Instant message text - - Get the ID of the group + + Whether this message is held for offline avatars - - Get the titles + + Context specific packed data - - Represents the summary data for a group + + Is this invitation for voice group/conference chat - - Construct a new instance of the GroupAccountSummaryReplyEventArgs class - The ID of the group - The summary data + + + Serialize the object + + An containing the objects data - - Get the ID of the group + + + Deserialize the message + + An containing the data - - Get the summary data + + + Sent from the simulator to the viewer. + When an agent initially joins a session the AgentUpdatesBlock object will contain a list of session members including + a boolean indicating they can use voice chat in this session, a boolean indicating they are allowed to moderate + this session, and lastly a string which indicates another agent is entering the session with the Transition set to "ENTER" + During the session lifetime updates on individuals are sent. During the update the booleans sent during the initial join are + excluded with the exception of the Transition field. This indicates a new user entering or exiting the session with + the string "ENTER" or "LEAVE" respectively. + - - A response to a group create request + + + Serialize the object + + An containing the objects data - - Construct a new instance of the GroupCreatedReplyEventArgs class - The ID of the group - the success or faulure of the request - A string containing additional information + + + Deserialize the message + + An containing the data - - Get the ID of the group + + + An EventQueue message sent when the agent is forcibly removed from a chatterbox session + - - true of the group was created successfully + + + A string containing the reason the agent was removed + - - A string containing the message + + + The ChatterBoxSession's SessionID + - - Represents a response to a request + + + Serialize the object + + An containing the objects data - - Construct a new instance of the GroupOperationEventArgs class - The ID of the group - true of the request was successful + + + Deserialize the message + + An containing the data - - Get the ID of the group + + + Serialize the object + + An containing the objects data - - true of the request was successful + + + Deserialize the message + + An containing the data - - Represents your agent leaving a group + + + Serialize the object + + An containing the objects data - - Construct a new instance of the GroupDroppedEventArgs class - The ID of the group + + + Deserialize the message + + An containing the data - - Get the ID of the group + + + Serialize the object + + An containing the objects data - - Represents a list of active group notices + + + Deserialize the message + + An containing the data - - Construct a new instance of the GroupNoticesListReplyEventArgs class - The ID of the group - The list containing active notices + + + Serialize the object + + An containing the objects data - - Get the ID of the group + + + Deserialize the message + + An containing the data - - Get the notices list + + + - - Represents the profile of a group + + + Serialize the object + + An containing the objects data - - Construct a new instance of the GroupProfileEventArgs class - The group profile + + + Deserialize the message + + An containing the data - - Get the group profile + + + Serialize the object + + An containing the objects data - + - Provides notification of a group invitation request sent by another Avatar + Deserialize the message - The invitation is raised when another avatar makes an offer for our avatar - to join a group. + An containing the data - - The ID of the Avatar sending the group invitation + + + Serialize the object + + An containing the objects data - - The name of the Avatar sending the group invitation + + + Deserialize the message + + An containing the data - - A message containing the request information which includes - the name of the group, the groups charter and the fee to join details + + + A message sent from the viewer to the simulator which + specifies that the user has changed current URL + of the specific media on a prim face + - - The Simulator + + + New URL + - - Set to true to accept invitation, false to decline + + + Prim UUID where navigation occured + - + - Wrapper around a byte array that allows bit to be packed and unpacked - one at a time or by a variable amount. Useful for very tightly packed - data like LayerData packets + Face index - - + + + Serialize the object + + An containing the objects data - + - Default constructor, initialize the bit packer / bit unpacker - with a byte array and starting position + Deserialize the message - Byte array to pack bits in to or unpack from - Starting position in the byte array + An containing the data - + + Base class used for the ObjectMedia message + + - Pack a floating point value in to the data + Message used to retrive prim media data - Floating point value to pack - + - Pack part or all of an integer in to the data + Prim UUID - Integer containing the data to pack - Number of bits of the integer to pack - + - Pack part or all of an unsigned integer in to the data + Requested operation, either GET or UPDATE - Unsigned integer containing the data to pack - Number of bits of the integer to pack - + - + Serialize object - - - - + Serialized object as OSDMap - + - + Deserialize the message - + An containing the data - + - + Message used to update prim media data - - + - Unpacking a floating point value from the data + Prim UUID - Unpacked floating point value - + - Unpack a variable number of bits from the data in to integer format + Array of media entries indexed by face number - Number of bits to unpack - An integer containing the unpacked bits - This function is only useful up to 32 bits - + - Unpack a variable number of bits from the data in to unsigned - integer format + Media version string - Number of bits to unpack - An unsigned integer containing the unpacked bits - This function is only useful up to 32 bits - + - Unpack a 16-bit signed integer + Serialize object - 16-bit signed integer + Serialized object as OSDMap - + - Unpack a 16-bit unsigned integer + Deserialize the message - 16-bit unsigned integer + An containing the data - + - Unpack a 32-bit signed integer + Message used to update prim media data - 32-bit signed integer - + - Unpack a 32-bit unsigned integer + Prim UUID - 32-bit unsigned integer - - - - - - - + - Avatar profile flags + Array of media entries indexed by face number - + - Represents an avatar (other than your own) + Requested operation, either GET or UPDATE - - Groups that this avatar is a member of - - - Positive and negative ratings - - - Avatar properties including about text, profile URL, image IDs and - publishing settings - - - Avatar interests including spoken languages, skills, and "want to" - choices - - - Movement control flags for avatars. Typically not set or used by - clients. To move your avatar, use Client.Self.Movement instead - - + - Contains the visual parameters describing the deformation of the avatar + Serialize object + Serialized object as OSDMap - + - Default constructor + Deserialize the message + An containing the data - - First name - - - Last name - - - Full name + + + Message for setting or getting per face MediaEntry + - - Active group + + The request or response details block - + - Positive and negative ratings + Serialize the object + An containing the objects data - - Positive ratings for Behavior + + + Deserialize the message + + An containing the data - - Negative ratings for Behavior + + Details about object resource usage - - Positive ratings for Appearance + + Object UUID - - Negative ratings for Appearance + + Object name - - Positive ratings for Building + + Indicates if object is group owned - - Negative ratings for Building + + Locatio of the object - - Positive ratings given by this avatar + + Object owner - - Negative ratings given by this avatar + + Resource usage, keys are resource names, values are resource usage for that specific resource - + - Avatar properties including about text, profile URL, image IDs and - publishing settings + Deserializes object from OSD + An containing the data - - First Life about text - - - First Life image ID - - - - - - - - - - - - - - - Profile image ID + + + Makes an instance based on deserialized data + + + serialized data + Instance containg deserialized data - - Flags of the profile + + Details about parcel resource usage - - Web URL for this profile + + Parcel UUID - - Should this profile be published on the web + + Parcel local ID - - Avatar Online Status + + Parcel name - - Is this a mature profile + + Indicates if parcel is group owned - - + + Parcel owner - - + + Array of containing per object resource usage - + - Avatar interests including spoken languages, skills, and "want to" - choices + Deserializes object from OSD + An containing the data - - Languages profile field - - - + + + Makes an instance based on deserialized data + + + serialized data + Instance containg deserialized data - - + + Resource usage base class, both agent and parcel resource + usage contains summary information - - + + Summary of available resources, keys are resource names, + values are resource usage for that specific resource - - + + Summary resource usage, keys are resource names, + values are resource usage for that specific resource - + - Index of TextureEntry slots for avatar appearances + Serializes object + + serialized data - + - Bake layers for avatar appearance + Deserializes object from OSD + An containing the data - - Maximum number of concurrent downloads for wearable assets and textures - - - Maximum number of concurrent uploads for baked textures - - - Timeout for fetching inventory listings - - - Timeout for fetching a single wearable, or receiving a single packet response - - - Timeout for fetching a single texture - - - Timeout for uploading a single baked texture - - - Number of times to retry bake upload - - - When changing outfit, kick off rebake after - 20 seconds has passed since the last change - - - Total number of wearables for each avatar - - - Total number of baked textures on each avatar - - - Total number of wearables per bake layer - - - Total number of textures on an avatar, baked or not - - - Mapping between BakeType and AvatarTextureIndex - - - Map of what wearables are included in each bake - - - Magic values to finalize the cache check hashes for each - bake - - - Default avatar texture, used to detect when a custom - texture is not set for a face - - - The event subscribers. null if no subcribers - - - Raises the AgentWearablesReply event - An AgentWearablesReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Raises the CachedBakesReply event - An AgentCachedBakesReplyEventArgs object containing the - data returned from the data server AgentCachedTextureResponse - - - Thread sync lock object - - - The event subscribers. null if no subcribers + + Agent resource usage - - Raises the AppearanceSet event - An AppearanceSetEventArgs object indicating if the operatin was successfull + + Per attachment point object resource usage - - Thread sync lock object + + + Deserializes object from OSD + + An containing the data - - The event subscribers. null if no subcribers + + + Makes an instance based on deserialized data + + + serialized data + Instance containg deserialized data - - Raises the RebakeAvatarRequested event - An RebakeAvatarTexturesEventArgs object containing the - data returned from the data server + + + Detects which class handles deserialization of this message + + An containing the data + Object capable of decoding this message - - Thread sync lock object + + Request message for parcel resource usage - - A cache of wearables currently being worn + + UUID of the parel to request resource usage info - - A cache of textures currently being worn + + + Serializes object + + + serialized data - - Incrementing serial number for AgentCachedTexture packets + + + Deserializes object from OSD + + An containing the data - - Incrementing serial number for AgentSetAppearance packets + + Response message for parcel resource usage - - Indicates whether or not the appearance thread is currently - running, to prevent multiple appearance threads from running - simultaneously + + URL where parcel resource usage details can be retrieved - - Reference to our agent + + URL where parcel resource usage summary can be retrieved - + - Timer used for delaying rebake on changing outfit + Serializes object + + serialized data - + - Main appearance thread + Deserializes object from OSD + An containing the data - + - Default constructor + Detects which class handles deserialization of this message - A reference to our agent + An containing the data + Object capable of decoding this message - + + Parcel resource usage + + + Array of containing per percal resource usage + + - Obsolete method for setting appearance. This function no longer does anything. - Use RequestSetAppearance() to manually start the appearance thread + Deserializes object from OSD + An containing the data - + - Obsolete method for setting appearance. This function no longer does anything. - Use RequestSetAppearance() to manually start the appearance thread + Return a decoded capabilities message as a strongly typed object - Unused parameter + A string containing the name of the capabilities message key + An to decode + A strongly typed object containing the decoded information from the capabilities message, or null + if no existing Message object exists for the specified event - + - Starts the appearance setting thread + Permissions for control of object media - + - Starts the appearance setting thread + Style of cotrols that shold be displayed to the user - True to force rebaking, otherwise false - + - Ask the server what textures our agent is currently wearing + Class representing media data for a single face - + + Is display of the alternative image enabled + + + Should media auto loop + + + Shoule media be auto played + + + Auto scale media to prim face + + + Should viewer automatically zoom in on the face when clicked + + + Should viewer interpret first click as interaction with the media + or when false should the first click be treated as zoom in commadn + + + Style of controls viewer should display when + viewer media on this face + + + Starting URL for the media + + + Currently navigated URL + + + Media height in pixes + + + Media width in pixels + + + Who can controls the media + + + Who can interact with the media + + + Is URL whitelist enabled + + + Array of URLs that are whitelisted + + - Build hashes out of the texture assetIDs for each baking layer to - ask the simulator whether it has cached copies of each baked texture + Serialize to OSD + OSDMap with the serialized data - + - Returns the AssetID of the asset that is currently being worn in a - given WearableType slot + Deserialize from OSD data - WearableType slot to get the AssetID for - The UUID of the asset being worn in the given slot, or - UUID.Zero if no wearable is attached to the given slot or wearables - have not been downloaded yet + Serialized OSD data + Deserialized object - + - Add a wearable to the current outfit and set appearance + Particle system specific enumerators, flags and methods. - Wearable to be added to the outfit - + - Add a list of wearables to the current outfit and set appearance + Default constructor - List of wearable inventory items to - be added to the outfit - + - Remove a wearable from the current outfit and set appearance + Complete structure for the particle system - Wearable to be removed from the outfit - + - Removes a list of wearables from the current outfit and set appearance + Decodes a byte[] array into a ParticleSystem Object - List of wearable inventory items to - be removed from the outfit + ParticleSystem object + Start position for BitPacker - + - Replace the current outfit with a list of wearables and set appearance + Particle source pattern - List of wearable inventory items that - define a new outfit - + + None + + + Drop particles from source position with no force + + + "Explode" particles in all directions + + + Particles shoot across a 2D area + + + Particles shoot across a 3D Cone + + + Inverse of AngleCone (shoot particles everywhere except the 3D cone defined + + - Checks if an inventory item is currently being worn + Particle Data Flags - The inventory item to check against the agent - wearables - The WearableType slot that the item is being worn in, - or WearbleType.Invalid if it is not currently being worn - + + None + + + Interpolate color and alpha from start to end + + + Interpolate scale from start to end + + + Bounce particles off particle sources Z height + + + velocity of particles is dampened toward the simulators wind + + + Particles follow the source + + + Particles point towards the direction of source's velocity + + + Target of the particles + + + Particles are sent in a straight line + + + Particles emit a glow + + + used for point/grab/touch + + - Returns a copy of the agents currently worn wearables + Particle Flags Enum - A copy of the agents currently worn wearables - Avoid calling this function multiple times as it will make - a copy of all of the wearable data each time - - - Calls either or - depending on the value of - replaceItems - - List of wearable inventory items to add - to the outfit or become a new outfit - True to replace existing items with the - new list of items, false to add these items to the existing outfit + + None + + + Acceleration and velocity for particles are + relative to the object rotation + + + Particles use new 'correct' angle parameters + + + Particle Flags + There appears to be more data packed in to this area + for many particle systems. It doesn't appear to be flag values + and serialization breaks unless there is a flag for every + possible bit so it is left as an unsigned integer + + + + pattern of particles + + + A representing the maximimum age (in seconds) particle will be displayed + Maximum value is 30 seconds + + + A representing the number of seconds, + from when the particle source comes into view, + or the particle system's creation, that the object will emits particles; + after this time period no more particles are emitted + + + A in radians that specifies where particles will not be created + + + A in radians that specifies where particles will be created + + + A representing the number of seconds between burts. + + + A representing the number of meters + around the center of the source where particles will be created. - - - Adds a list of attachments to our agent - - A List containing the attachments to add - If true, tells simulator to remove existing attachment - first + + A representing in seconds, the minimum speed between bursts of new particles + being emitted - - - Attach an item to our agent at a specific attach point - - A to attach - the on the avatar - to attach the item to + + A representing in seconds the maximum speed of new particles being emitted. - - - Attach an item to our agent specifying attachment details - - The of the item to attach - The attachments owner - The name of the attachment - The description of the attahment - The to apply when attached - The of the attachment - The on the agent - to attach the item to + + A representing the maximum number of particles emitted per burst - - - Detach an item from our agent using an object - - An object + + A which represents the velocity (speed) from the source which particles are emitted - - - Detach an item from our agent - - The inventory itemID of the item to detach + + A which represents the Acceleration from the source which particles are emitted - - - Inform the sim which wearables are part of our current outfit - + + The Key of the texture displayed on the particle - - - Replaces the Wearables collection with a list of new wearable items - - Wearable items to replace the Wearables collection with + + The Key of the specified target object or avatar particles will follow - - - Calculates base color/tint for a specific wearable - based on its params - - All the color info gathered from wearable's VisualParams - passed as list of ColorParamInfo tuples - Base color/tint for the wearable + + Flags of particle from - - - Blocking method to populate the Wearables dictionary - - True on success, otherwise false + + Max Age particle system will emit particles for - - - Blocking method to populate the Textures array with cached bakes - - True on success, otherwise false + + The the particle has at the beginning of its lifecycle - - - Populates textures and visual params from a decoded asset - - Wearable to decode + + The the particle has at the ending of its lifecycle - - - Blocking method to download and parse currently worn wearable assets - - True on success, otherwise false + + A that represents the starting X size of the particle + Minimum value is 0, maximum value is 4 - - - Get a list of all of the textures that need to be downloaded for a - single bake layer - - Bake layer to get texture AssetIDs for - A list of texture AssetIDs to download + + A that represents the starting Y size of the particle + Minimum value is 0, maximum value is 4 - - - Helper method to lookup the TextureID for a single layer and add it - to a list if it is not already present - - - + + A that represents the ending X size of the particle + Minimum value is 0, maximum value is 4 - - - Blocking method to download all of the textures needed for baking - the given bake layers - - A list of layers that need baking - No return value is given because the baking will happen - whether or not all textures are successfully downloaded + + A that represents the ending Y size of the particle + Minimum value is 0, maximum value is 4 - + - Blocking method to create and upload baked textures for all of the - missing bakes + Generate byte[] array from particle data - True on success, otherwise false + Byte array - + - Blocking method to create and upload a baked texture for a single - bake layer + Parameters used to construct a visual representation of a primitive - Layer to bake - True on success, otherwise false - + - Blocking method to upload a baked texture - Five channel JPEG2000 texture data to upload - UUID of the newly created asset on success, otherwise UUID.Zero - + - Creates a dictionary of visual param values from the downloaded wearables - A dictionary of visual param indices mapping to visual param - values for our agent that can be fed to the Baker class - + - Create an AgentSetAppearance packet from Wearables data and the - Textures array and send it - + - Converts a WearableType to a bodypart or clothing WearableType - A WearableType - AssetType.Bodypart or AssetType.Clothing or AssetType.Unknown - + - Converts a BakeType to the corresponding baked texture slot in AvatarTextureIndex - A BakeType - The AvatarTextureIndex slot that holds the given BakeType - + - Gives the layer number that is used for morph mask - >A BakeType - Which layer number as defined in BakeTypeToTextures is used for morph mask - + - Converts a BakeType to a list of the texture slots that make up that bake - A BakeType - A list of texture slots that are inputs for the given bake - - Triggered when an AgentWearablesUpdate packet is received, - telling us what our avatar is currently wearing - request. - - - Raised when an AgentCachedTextureResponse packet is - received, giving a list of cached bakes that were found on the - simulator - request. - - + - Raised when appearance data is sent to the simulator, also indicates - the main appearance thread is finished. - request. - + - Triggered when the simulator requests the agent rebake its appearance. - - + - Returns true if AppearanceManager is busy and trying to set or change appearance will fail - + - Contains information about a wearable inventory item - - Inventory ItemID of the wearable - - - AssetID of the wearable asset - - - WearableType of the wearable - - - AssetType of the wearable - - - Asset data for the wearable - - + - Data collected from visual params for each wearable - needed for the calculation of the color - + - Holds a texture assetID and the data needed to bake this layer into - an outfit texture. Used to keep track of currently worn textures - and baking data - - A texture AssetID - - - Asset data for the texture - - - Collection of alpha masks that needs applying - - - Tint that should be applied to the texture - - - Contains the Event data returned from the data server from an AgentWearablesRequest - - - Construct a new instance of the AgentWearablesReplyEventArgs class - - - Contains the Event data returned from the data server from an AgentCachedTextureResponse - - - Construct a new instance of the AgentCachedBakesReplyEventArgs class - - - Contains the Event data returned from an AppearanceSetRequest - - - - Triggered when appearance data is sent to the sim and - the main appearance thread is done. - Indicates whether appearance setting was successful - - - Indicates whether appearance setting was successful - - - Contains the Event data returned from the data server from an RebakeAvatarTextures - - + - Triggered when the simulator sends a request for this agent to rebake - its appearance - The ID of the Texture Layer to bake - - - The ID of the Texture Layer to bake - + - Registers, unregisters, and fires events generated by incoming packets - - Reference to the GridClient object - - + - Default constructor - - + - Register an event handler - Use PacketType.Default to fire this event on every - incoming packet - Packet type to register the handler for - Callback to be fired - + - Unregister an event handler - Packet type to unregister the handler for - Callback to be unregistered - + - Fire the events registered for this packet type synchronously - Incoming packet type - Incoming packet - Simulator this packet was received from - + - Fire the events registered for this packet type asynchronously - Incoming packet type - Incoming packet - Simulator this packet was received from - + - Object that is passed to worker threads in the ThreadPool for - firing packet callbacks - - Callback to fire for this packet + + Attachment point to an avatar - - Reference to the simulator that this packet came from + + + - - The packet that needs to be processed + + + - + - Registers, unregisters, and fires events generated by the Capabilities - event queue - - Reference to the GridClient object + + + - + + + Information on the flexible properties of a primitive + + + Default constructor - Reference to the GridClient object - + - Register an new event handler for a capabilities event sent via the EventQueue - Use String.Empty to fire this event on every CAPS event - Capability event name to register the - handler for - Callback to fire + + + + - + - Unregister a previously registered capabilities handler - Capability event name unregister the - handler for - Callback to unregister - + - Fire the events registered for this event type synchronously - Capability name - Decoded event body - Reference to the simulator that - generated this event - + - Fire the events registered for this event type asynchronously - Capability name - Decoded event body - Reference to the simulator that - generated this event - + - Object that is passed to worker threads in the ThreadPool for - firing CAPS callbacks - - Callback to fire for this packet + + + - - Name of the CAPS event + + + - - Strongly typed decoded data + + + + + - - Reference to the simulator that generated this event + + + + + - + - Access to the data server which allows searching for land, events, people, etc + Information on the light properties of a primitive - - The event subscribers. null if no subcribers + + + Default constructor + - - Raises the EventInfoReply event - An EventInfoReplyEventArgs object containing the - data returned from the data server + + + + + + + - - Thread sync lock object + + + - - The event subscribers. null if no subcribers + + + - - Raises the DirEventsReply event - An DirEventsReplyEventArgs object containing the - data returned from the data server + + + - - Thread sync lock object + + + - - The event subscribers. null if no subcribers + + + - - Raises the PlacesReply event - A PlacesReplyEventArgs object containing the - data returned from the data server + + + + + - - Thread sync lock object + + + + + - - The event subscribers. null if no subcribers + + + Information on the sculpt properties of a sculpted primitive + - - Raises the DirPlacesReply event - A DirPlacesReplyEventArgs object containing the - data returned from the data server + + + Default constructor + - - Thread sync lock object + + + + + + + - - The event subscribers. null if no subcribers + + + Render inside out (inverts the normals). + - - Raises the DirClassifiedsReply event - A DirClassifiedsReplyEventArgs object containing the - data returned from the data server + + + Render an X axis mirror of the sculpty. + - - Thread sync lock object + + + Extended properties to describe an object + - - The event subscribers. null if no subcribers + + + Default constructor + - - Raises the DirGroupsReply event - A DirGroupsReplyEventArgs object containing the - data returned from the data server + + + - - Thread sync lock object + + + - - The event subscribers. null if no subcribers + + + - - Raises the DirPeopleReply event - A DirPeopleReplyEventArgs object containing the - data returned from the data server + + + - - Thread sync lock object + + + - - The event subscribers. null if no subcribers + + + - - Raises the DirLandReply event - A DirLandReplyEventArgs object containing the - data returned from the data server + + + - - Thread sync lock object + + + - + - Constructs a new instance of the DirectoryManager class - An instance of GridClient - + - Query the data server for a list of classified ads containing the specified string. - Defaults to searching for classified placed in any category, and includes PG, Adult and Mature - results. - - Responses are sent 16 per response packet, there is no way to know how many results a query reply will contain however assuming - the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received - - The event is raised when a response is received from the simulator - A string containing a list of keywords to search for - A UUID to correlate the results when the event is raised - + - Query the data server for a list of classified ads which contain specified keywords (Overload) - - The event is raised when a response is received from the simulator - A string containing a list of keywords to search for - The category to search - A set of flags which can be ORed to modify query options - such as classified maturity rating. - A UUID to correlate the results when the event is raised - - Search classified ads containing the key words "foo" and "bar" in the "Any" category that are either PG or Mature - - UUID searchID = StartClassifiedSearch("foo bar", ClassifiedCategories.Any, ClassifiedQueryFlags.PG | ClassifiedQueryFlags.Mature); - - - - Responses are sent 16 at a time, there is no way to know how many results a query reply will contain however assuming - the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received - - + - Starts search for places (Overloaded) - - The event is raised when a response is received from the simulator - Search text - Each request is limited to 100 places - being returned. To get the first 100 result entries of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - A UUID to correlate the results when the event is raised - + - Queries the dataserver for parcels of land which are flagged to be shown in search - - The event is raised when a response is received from the simulator - A string containing a list of keywords to search for separated by a space character - A set of flags which can be ORed to modify query options - such as classified maturity rating. - The category to search - Each request is limited to 100 places - being returned. To get the first 100 result entries of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - A UUID to correlate the results when the event is raised - - Search places containing the key words "foo" and "bar" in the "Any" category that are either PG or Adult - - UUID searchID = StartDirPlacesSearch("foo bar", DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeAdult, ParcelCategory.Any, 0); - - - - Additional information on the results can be obtained by using the ParcelManager.InfoRequest method - - + - Starts a search for land sales using the directory - - The event is raised when a response is received from the simulator - What type of land to search for. Auction, - estate, mainland, "first land", etc - The OnDirLandReply event handler must be registered before - calling this function. There is no way to determine how many - results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each query. - + - Starts a search for land sales using the directory - - The event is raised when a response is received from the simulator - What type of land to search for. Auction, - estate, mainland, "first land", etc - Maximum price to search for - Maximum area to search for - Each request is limited to 100 parcels - being returned. To get the first 100 parcels of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - The OnDirLandReply event handler must be registered before - calling this function. There is no way to determine how many - results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each query. - + - Send a request to the data server for land sales listings - - Flags sent to specify query options - - Available flags: - Specify the parcel rating with one or more of the following: - IncludePG IncludeMature IncludeAdult - - Specify the field to pre sort the results with ONLY ONE of the following: - PerMeterSort NameSort AreaSort PricesSort - - Specify the order the results are returned in, if not specified the results are pre sorted in a Descending Order - SortAsc - - Specify additional filters to limit the results with one or both of the following: - LimitByPrice LimitByArea - - Flags can be combined by separating them with the | (pipe) character - - Additional details can be found in - - What type of land to search for. Auction, - Estate or Mainland - Maximum price to search for when the - DirFindFlags.LimitByPrice flag is specified in findFlags - Maximum area to search for when the - DirFindFlags.LimitByArea flag is specified in findFlags - Each request is limited to 100 parcels - being returned. To get the first 100 parcels of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - The event will be raised with the response from the simulator - - There is no way to determine how many results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each reply. - - Any land set for sale to either anybody or specific to the connected agent will be included in the - results if the land is included in the query - - - // request all mainland, any maturity rating that is larger than 512 sq.m - StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByArea | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, SearchTypeFlags.Mainland, 0, 512, 0); - - + - Search for Groups - The name or portion of the name of the group you wish to search for - Start from the match number - - + - Search for Groups - The name or portion of the name of the group you wish to search for - Start from the match number - Search flags - - + - Search the People directory for other avatars - The name or portion of the name of the avatar you wish to search for - - - + - Search Places for parcels of land you personally own - + - Searches Places for land owned by the specified group - ID of the group you want to recieve land list for (You must be a member of the group) - Transaction (Query) ID which can be associated with results from your request. - + - Search the Places directory for parcels that are listed in search and contain the specified keywords - A string containing the keywords to search for - Transaction (Query) ID which can be associated with results from your request. - + - Search Places - All Options - One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc. - One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer - A string containing a list of keywords to search for separated by a space character - String Simulator Name to search in - LLUID of group you want to recieve results for - Transaction (Query) ID which can be associated with results from your request. - Transaction (Query) ID which can be associated with results from your request. - + - Search All Events with specifid searchText in all categories, includes PG, Mature and Adult + Set the properties that are set in an ObjectPropertiesFamily packet - A string containing a list of keywords to search for separated by a space character - Each request is limited to 100 entries - being returned. To get the first group of entries of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - UUID of query to correlate results in callback. + + that has + been partially filled by an ObjectPropertiesFamily packet - + - Search Events + Texture animation mode - A string containing a list of keywords to search for separated by a space character - One or more of the following flags: DateEvents, IncludePG, IncludeMature, IncludeAdult - from the Enum - - Multiple flags can be combined by separating the flags with the | (pipe) character - "u" for in-progress and upcoming events, -or- number of days since/until event is scheduled - For example "0" = Today, "1" = tomorrow, "2" = following day, "-1" = yesterday, etc. - Each request is limited to 100 entries - being returned. To get the first group of entries of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - EventCategory event is listed under. - UUID of query to correlate results in callback. - - Requests Event Details - ID of Event returned from the method + + Disable texture animation - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Enable texture animation - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Loop when animating textures - - Process an incoming event message - The Unique Capabilities Key - The event message containing the data - The simulator the message originated from + + Animate in reverse direction - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Animate forward then reverse - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Slide texture smoothly instead of frame-stepping - - Process an incoming event message - The Unique Capabilities Key - The event message containing the data - The simulator the message originated from + + Rotate texture instead of using frames - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Scale texture instead of using frames - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + A single textured face. Don't instantiate this class yourself, use the + methods in TextureEntry + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Contains the definition for individual faces + + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + - - Raised when the data server responds to a request. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - Raised when the data server responds to a request. + + In the future this will specify whether a webpage is + attached to this face - - Raised when the data server responds to a request. + + + - - Raised when the data server responds to a request. + + + + + - - Raised when the data server responds to a request. + + + Represents all of the texturable faces for an object + + Grid objects have infinite faces, with each face + using the properties of the default face unless set otherwise. So if + you have a TextureEntry with a default texture uuid of X, and face 18 + has a texture UUID of Y, every face would be textured with X except for + face 18 that uses Y. In practice however, primitives utilize a maximum + of nine faces - - Raised when the data server responds to a request. + + + Constructor that takes a default texture UUID + + Texture UUID to use as the default texture - - Raised when the data server responds to a request. + + + Constructor that takes a TextureEntryFace for the + default face + + Face to use as the default face - - Raised when the data server responds to a request. + + + Constructor that creates the TextureEntry class from a byte array + + Byte array containing the TextureEntry field + Starting position of the TextureEntry field in + the byte array + Length of the TextureEntry field, in bytes - - Classified Ad categories + + + - - Classified is listed in the Any category + + + - - Classified is shopping related + + + This will either create a new face if a custom face for the given + index is not defined, or return the custom face for that index if + it already exists + + The index number of the face to create or + retrieve + A TextureEntryFace containing all the properties for that + face - - Classified is + + + + + + + - - + + + + + - - + + + + + - - + + + + + - - + + + Controls the texture animation of a particular prim + - - + + + + + + + - - + + + - - + + + - - Event Categories + + + - - + + + - - + + + - - + + + - - + + + - - + + + + + - - + + + Current version of the media data for the prim + - - + + + Array of media entries indexed by face number + - - + + + - - + + + - - + + + - - + + + - - + + + - + - Query Flags used in many of the DirectoryManager methods to specify which query to execute and how to return the results. - - Flags can be combined using the | (pipe) character, not all flags are available in all queries - - Query the People database + + + - - + + Foliage type for this primitive. Only applicable if this + primitive is foliage - - + + Unknown - - Query the Groups database + + + - - Query the Events database + + + - - Query the land holdings database for land owned by the currently connected agent + + + - - + + + - - Query the land holdings database for land which is owned by a Group + + + - - Specifies the query should pre sort the results based upon traffic - when searching the Places database + + + - - + + + - - + + + - - + + + - - + + + - - Specifies the query should pre sort the results in an ascending order when searching the land sales database. - This flag is only used when searching the land sales database + + + - - Specifies the query should pre sort the results using the SalePrice field when searching the land sales database. - This flag is only used when searching the land sales database + + + - - Specifies the query should pre sort the results by calculating the average price/sq.m (SalePrice / Area) when searching the land sales database. - This flag is only used when searching the land sales database + + Identifies the owner if audio or a particle system is + active - - Specifies the query should pre sort the results using the ParcelSize field when searching the land sales database. - This flag is only used when searching the land sales database + + + - - Specifies the query should pre sort the results using the Name field when searching the land sales database. - This flag is only used when searching the land sales database + + + - - When set, only parcels less than the specified Price will be included when searching the land sales database. - This flag is only used when searching the land sales database + + + - - When set, only parcels greater than the specified Size will be included when searching the land sales database. - This flag is only used when searching the land sales database + + + - - + + + - - + + + - - Include PG land in results. This flag is used when searching both the Groups, Events and Land sales databases + + + - - Include Mature land in results. This flag is used when searching both the Groups, Events and Land sales databases + + + - - Include Adult land in results. This flag is used when searching both the Groups, Events and Land sales databases + + + - - + + + - + - Land types to search dataserver for - - Search Auction, Mainland and Estate + + + - - Land which is currently up for auction + + + - - Parcels which are on the mainland (Linden owned) continents + + + - - Parcels which are on privately owned simulators + + Uses basic heuristics to estimate the primitive shape - + - The content rating of the event + Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew + parameters in to signed eight bit values + Floating point parameter to pack + Signed eight bit value containing the packed parameter - - Event is PG + + + Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew + parameters from signed eight bit integers to floating point values + + Signed eight bit value to unpack + Unpacked floating point value - - Event is Mature + + + The type of bump-mapping applied to a face + - - Event is Adult + + + - + - Classified Ad Options - There appear to be two formats the flags are packed in. - This set of flags is for the newer style - - + + + - - + + + - - + + + - - + + + - - + + + - + - Classified ad query options - - Include all ads in results + + + - - Include PG ads in results + + + - - Include Mature ads in results + + + - - Include Adult ads in results + + + - + - The For Sale flag in PlacesReplyData - - Parcel is not listed for sale + + + - - Parcel is For Sale + + + - + - A classified ad on the grid - - UUID for this ad, useful for looking up detailed - information about it + + + - - The title of this classified ad + + + - - Flags that show certain options applied to the classified + + + The level of shininess applied to a face + - - Creation date of the ad + + + - - Expiration date of the ad + + + - - Price that was paid for this ad + + + - - Print the struct data as a string - A string containing the field name, and field value + + + - + - A parcel retrieved from the dataserver such as results from the - "For-Sale" listings or "Places" Search + The texture mapping style used for a face - - The unique dataserver parcel ID - This id is used to obtain additional information from the entry - by using the method + + + - - A string containing the name of the parcel + + + - - The size of the parcel - This field is not returned for Places searches + + + - - The price of the parcel - This field is not returned for Places searches + + + - - If True, this parcel is flagged to be auctioned + + + Flags in the TextureEntry block that describe which properties are + set + - - If true, this parcel is currently set for sale + + + - - Parcel traffic + + + - - Print the struct data as a string - A string containing the field name, and field value + + + - + - An Avatar returned from the dataserver - - Online status of agent - This field appears to be obsolete and always returns false + + + - - The agents first name + + + - - The agents last name + + + - - The agents + + + - - Print the struct data as a string - A string containing the field name, and field value + + + - + - Response to a "Groups" Search - - The Group ID - - - The name of the group + + + - - The current number of members + + + - - Print the struct data as a string - A string containing the field name, and field value + + + Level of Detail mesh + - + - Parcel information returned from a request - - Represents one of the following: - A parcel of land on the grid that has its Show In Search flag set - A parcel of land owned by the agent making the request - A parcel of land owned by a group the agent making the request is a member of - - - In a request for Group Land, the First record will contain an empty record - - Note: This is not the same as searching the land for sale data source + Constructor for default logging settings - - The ID of the Agent of Group that owns the parcel + + Enable logging - - The name + + The folder where any logs will be created - - The description + + This will be prepended to beginning of each log file - - The Size of the parcel + + The suffix or extension to be appended to each log file - - The billable Size of the parcel, for mainland - parcels this will match the ActualArea field. For Group owned land this will be 10 percent smaller - than the ActualArea. For Estate land this will always be 0 + + + 0: NONE - No logging + 1: ERROR - Log errors only + 2: WARNING - Log errors and warnings + 3: INFO - Log errors, warnings and info + 4: DEBUG - Log errors, warnings, info and debug + - - Indicates the ForSale status of the parcel + + Audio Properties Events are sent after audio capture is started. These events are used to display a microphone VU meter + + + Event for most mundane request reposnses. + - - The Gridwide X position + + Response to Connector.Create request - - The Gridwide Y position + + Response to Aux.GetCaptureDevices request - - The Z position of the parcel, or 0 if no landing point set + + Response to Aux.GetRenderDevices request - - The name of the Region the parcel is located in + + Audio Properties Events are sent after audio capture is started. + These events are used to display a microphone VU meter - - The Asset ID of the parcels Snapshot texture + + Response to Account.Login request - - The calculated visitor traffic + + This event message is sent whenever the login state of the + particular Account has transitioned from one value to another - - The billing product SKU - Known values are: - - 023Mainland / Full Region - 024Estate / Full Region - 027Estate / Openspace - 029Estate / Homestead - 129Mainland / Homestead (Linden Owned) - - + + + List of audio input devices + - - No longer used, will always be 0 + + + List of audio output devices + - - Get a SL URL for the parcel - A string, containing a standard SLURL + + + Set audio test mode + - - Print the struct data as a string - A string containing the field name, and field value + + + This is used to login a specific user account(s). It may only be called after + Connector initialization has completed successfully + + Handle returned from successful Connector �create� request + User's account name + User's account password + Values may be �AutoAnswer� or �VerifyAnswer� + "" + This is an integer that specifies how often + the daemon will send participant property events while in a channel. If this is not set + the default will be �on state change�, which means that the events will be sent when + the participant starts talking, stops talking, is muted, is unmuted. + The valid values are: + 0 � Never + 5 � 10 times per second + 10 � 5 times per second + 50 � 1 time per second + 100 � on participant state change (this is the default) + false + + - + - An "Event" Listing summary + This is used to logout a user session. It should only be called with a valid AccountHandle. + Handle returned from successful Connector �login� request + + - - The ID of the event creator + + + This is used to get a list of audio devices that can be used for capture (input) of voice. + + + - - The name of the event + + + This is used to get a list of audio devices that can be used for render (playback) of voice. + - - The events ID + + + This command is used to select the render device. + + The name of the device as returned by the Aux.GetRenderDevices command. - - A string containing the short date/time the event will begin + + + This command is used to select the capture device. + + The name of the device as returned by the Aux.GetCaptureDevices command. - - The event start time in Unixtime (seconds since epoch) + + + This command is used to start the audio capture process which will cause + AuxAudioProperty Events to be raised. These events can be used to display a + microphone VU meter for the currently selected capture device. This command + should not be issued if the user is on a call. + + (unused but required) + + - - The events maturity rating + + + This command is used to stop the audio capture process. + + + - - Print the struct data as a string - A string containing the field name, and field value + + + This command is used to set the mic volume while in the audio tuning process. + Once an acceptable mic level is attained, the application must issue a + connector set mic volume command to have that level be used while on voice + calls. + + the microphone volume (-100 to 100 inclusive) + + - + - The details of an "Event" + This command is used to set the speaker volume while in the audio tuning + process. Once an acceptable speaker level is attained, the application must + issue a connector set speaker volume command to have that level be used while + on voice calls. + the speaker volume (-100 to 100 inclusive) + + - - The events ID + + + This is used to initialize and stop the Connector as a whole. The Connector + Create call must be completed successfully before any other requests are made + (typically during application initialization). The shutdown should be called + when the application is shutting down to gracefully release resources + + A string value indicting the Application name + URL for the management server + LoggingSettings + + + + - - The ID of the event creator + + + Shutdown Connector -- Should be called when the application is shutting down + to gracefully release resources + + Handle returned from successful Connector �create� request - - The name of the event + + + Mute or unmute the microphone + + Handle returned from successful Connector �create� request + true (mute) or false (unmute) - - The category + + + Mute or unmute the speaker + + Handle returned from successful Connector �create� request + true (mute) or false (unmute) - - The events description + + + Set microphone volume + + Handle returned from successful Connector �create� request + The level of the audio, a number between -100 and 100 where + 0 represents �normal� speaking volume - - The short date/time the event will begin + + + Set local speaker volume + + Handle returned from successful Connector �create� request + The level of the audio, a number between -100 and 100 where + 0 represents �normal� speaking volume - - The event start time in Unixtime (seconds since epoch) UTC adjusted + + + Start up the Voice service. + - - The length of the event in minutes + + + Handle miscellaneous request status + + + + + + ///If something goes wrong, we log it. + + + Cleanup oject resources + - - 0 if no cover charge applies + + + Request voice cap when changing regions + - - The cover charge amount in L$ if applicable + + + Handle a change in session state + - - The name of the region where the event is being held + + + Close a voice session + + + - - The gridwide location of the event + + + Locate a Session context from its handle + + Creates the session context if it does not exist. - - The maturity rating + + + Handle completion of main voice cap request. + + + + + + + - - Get a SL URL for the parcel where the event is hosted - A string, containing a standard SLURL + + + Daemon has started so connect to it. + - - Print the struct data as a string - A string containing the field name, and field value + + + The daemon TCP connection is open. + - - Contains the Event data returned from the data server from an EventInfoRequest + + + Handle creation of the Connector. + - - Construct a new instance of the EventInfoReplyEventArgs class - A single EventInfo object containing the details of an event + + + Handle response to audio output device query + - + - A single EventInfo object containing the details of an event + Handle response to audio input device query - - Contains the "Event" detail data returned from the data server + + + Set voice channel for new parcel + - - Construct a new instance of the DirEventsReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing the "Events" returned by the search query + + + Request info from a parcel capability Uri. + + + - - The ID returned by + + + Receive parcel voice cap + + + + + + + - - A list of "Events" returned by the data server + + + Tell Vivox where we are standing + + This has to be called when we move or turn. - - Contains the "Event" list data returned from the data server + + + Start and stop updating out position. + + + - - Construct a new instance of PlacesReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing the "Places" returned by the data server query + + + Starts a thread that keeps the daemon running + + + + + - - The ID returned by + + + Stops the daemon and the thread keeping it running + - - A list of "Places" returned by the data server + + + + + + + + + - - Contains the places data returned from the data server + + + Create a Session + Sessions typically represent a connection to a media session with one or more + participants. This is used to generate an �outbound� call to another user or + channel. The specifics depend on the media types involved. A session handle is + required to control the local user functions within the session (or remote + users if the current account has rights to do so). Currently creating a + session automatically connects to the audio media, there is no need to call + Session.Connect at this time, this is reserved for future use. + + Handle returned from successful Connector �create� request + This is the URI of the terminating point of the session (ie who/what is being called) + This is the display name of the entity being called (user or channel) + Only needs to be supplied when the target URI is password protected + This indicates the format of the password as passed in. This can either be + �ClearText� or �SHA1UserName�. If this element does not exist, it is assumed to be �ClearText�. If it is + �SHA1UserName�, the password as passed in is the SHA1 hash of the password and username concatenated together, + then base64 encoded, with the final �=� character stripped off. + + + + + + - - Construct a new instance of the DirPlacesReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing land data returned by the data server + + + Used to accept a call + + SessionHandle such as received from SessionNewEvent + "default" + + - - The ID returned by + + + This command is used to start the audio render process, which will then play + the passed in file through the selected audio render device. This command + should not be issued if the user is on a call. + + The fully qualified path to the sound file. + True if the file is to be played continuously and false if it is should be played once. + + - - A list containing Places data returned by the data server + + + This command is used to stop the audio render process. + + The fully qualified path to the sound file issued in the start render command. + + - - Contains the classified data returned from the data server + + + This is used to �end� an established session (i.e. hang-up or disconnect). + + Handle returned from successful Session �create� request or a SessionNewEvent + + - - Construct a new instance of the DirClassifiedsReplyEventArgs class - A list of classified ad data returned from the data server + + + Set the combined speaking and listening position in 3D space. + + Handle returned from successful Session �create� request or a SessionNewEvent + Speaking position + Listening position + + - - A list containing Classified Ads returned by the data server + + + Set User Volume for a particular user. Does not affect how other users hear that user. + + Handle returned from successful Session �create� request or a SessionNewEvent + + + The level of the audio, a number between -100 and 100 where 0 represents �normal� speaking volume + + - - Contains the group data returned from the data server + + Positional vector of the users position - - Construct a new instance of the DirGroupsReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list of groups data returned by the data server + + Velocity vector of the position - - The ID returned by + + At Orientation (X axis) of the position - - A list containing Groups data returned by the data server + + Up Orientation (Y axis) of the position - - Contains the people data returned from the data server + + Left Orientation (Z axis) of the position - - Construct a new instance of the DirPeopleReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list of people data returned by the data server + + + Extract the avatar UUID encoded in a SIP URI + + + + + - - The ID returned by + + + Represents a single Voice Session to the Vivox service. + - - A list containing People data returned by the data server + + + Close this session. + - - Contains the land sales data returned from the data server + + + Look up an existing Participants in this session + + + + + - - Construct a new instance of the DirLandReplyEventArgs class - A list of parcels for sale returned by the data server + + + + + + + - - A list containing land forsale data returned by the data server + + + A callback fired to indicate the status or final state of the requested texture. For progressive + downloads this will fire each time new asset data is returned from the simulator. + + The indicating either Progress for textures not fully downloaded, + or the final result of the request after it has been processed through the TexturePipeline + The object containing the Assets ID, raw data + and other information. For progressive rendering the will contain + the data from the beginning of the file. For failed, aborted and timed out requests it will contain + an empty byte array. diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index 59e39bb..b9c73b7 100644 Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ diff --git a/bin/OpenMetaverse.dll.config b/bin/OpenMetaverse.dll.config index 13fdc11..dc36a45 100644 --- a/bin/OpenMetaverse.dll.config +++ b/bin/OpenMetaverse.dll.config @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/bin/OpenMetaverseTypes.XML b/bin/OpenMetaverseTypes.XML index 3903aea..69e5c1b 100644 --- a/bin/OpenMetaverseTypes.XML +++ b/bin/OpenMetaverseTypes.XML @@ -1,234 +1,9 @@ - OpenMetaverseTypes + /home/root/libopenmetaverse/bin/OpenMetaverseTypes - - - A hierarchical token bucket for bandwidth throttling. See - http://en.wikipedia.org/wiki/Token_bucket for more information - - - - Parent bucket to this bucket, or null if this is a root - bucket - - - Size of the bucket in bytes. If zero, the bucket has - infinite capacity - - - Rate that the bucket fills, in bytes per millisecond. If - zero, the bucket always remains full - - - Number of tokens currently in the bucket - - - Time of the last drip, in system ticks - - - - Default constructor - - Parent bucket if this is a child bucket, or - null if this is a root bucket - Maximum size of the bucket in bytes, or - zero if this bucket has no maximum capacity - Rate that the bucket fills, in bytes per - second. If zero, the bucket always remains full - - - - Remove a given number of tokens from the bucket - - Number of tokens to remove from the bucket - True if the requested number of tokens were removed from - the bucket, otherwise false - - - - Remove a given number of tokens from the bucket - - Number of tokens to remove from the bucket - True if tokens were added to the bucket - during this call, otherwise false - True if the requested number of tokens were removed from - the bucket, otherwise false - - - - Add tokens to the bucket over time. The number of tokens added each - call depends on the length of time that has passed since the last - call to Drip - - True if tokens were added to the bucket, otherwise false - - - - The parent bucket of this bucket, or null if this bucket has no - parent. The parent bucket will limit the aggregate bandwidth of all - of its children buckets - - - - - Maximum burst rate in bytes per second. This is the maximum number - of tokens that can accumulate in the bucket at any one time - - - - - The speed limit of this bucket in bytes per second. This is the - number of tokens that are added to the bucket per second - - Tokens are added to the bucket any time - is called, at the granularity of - the system tick interval (typically around 15-22ms) - - - - The number of bytes that can be sent at this moment. This is the - current number of tokens in the bucket - If this bucket has a parent bucket that does not have - enough tokens for a request, will - return false regardless of the content of this bucket - - - - X value - - - Y value - - - Z value - - - W value - - - - Build a quaternion from normalized float values - - X value from -1.0 to 1.0 - Y value from -1.0 to 1.0 - Z value from -1.0 to 1.0 - - - - Constructor, builds a quaternion object from a byte array - - Byte array containing four four-byte floats - Offset in the byte array to start reading at - Whether the source data is normalized or - not. If this is true 12 bytes will be read, otherwise 16 bytes will - be read. - - - - Normalizes the quaternion - - - - - Builds a quaternion object from a byte array - - The source byte array - Offset in the byte array to start reading at - Whether the source data is normalized or - not. If this is true 12 bytes will be read, otherwise 16 bytes will - be read. - - - - Normalize this quaternion and serialize it to a byte array - - A 12 byte array containing normalized X, Y, and Z floating - point values in order using little endian byte ordering - - - - Writes the raw bytes for this quaternion to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 12 bytes before the end of the array - - - - Convert this quaternion to euler angles - - X euler angle - Y euler angle - Z euler angle - - - - Convert this quaternion to an angle around an axis - - Unit vector describing the axis - Angle around the axis, in radians - - - - Returns the conjugate (spatial inverse) of a quaternion - - - - - Build a quaternion from an axis and an angle of rotation around - that axis - - - - - Build a quaternion from an axis and an angle of rotation around - that axis - - Axis of rotation - Angle of rotation - - - - Creates a quaternion from a vector containing roll, pitch, and yaw - in radians - - Vector representation of the euler angles in - radians - Quaternion representation of the euler angles - - - - Creates a quaternion from roll, pitch, and yaw euler angles in - radians - - X angle in radians - Y angle in radians - Z angle in radians - Quaternion representation of the euler angles - - - - Conjugates and renormalizes a vector - - - - - Spherical linear interpolation between two quaternions - - - - - Get a string representation of the quaternion elements with up to three - decimal digits and separated by spaces only - - Raw string representation of the quaternion - - - A quaternion with a value of 0,0,0,1 - Same as Queue except Dequeue function blocks until there is an object to return. @@ -252,6 +27,11 @@ Create new BlockingQueue. + + + Gets flag indicating if queue has been closed. + + BlockingQueue Destructor (Close queue, resume any waiting thread). @@ -298,1533 +78,2419 @@ Open Queue. - + - Gets flag indicating if queue has been closed. + Copy constructor + Circular queue to copy - - Used for converting degrees to radians - - - Used for converting radians to degrees + + + An 8-bit color structure including an alpha channel + - - Provide a single instance of the CultureInfo class to - help parsing in situations where the grid assumes an en-us - culture + + + + + + + + + + + - - UNIX epoch in DateTime format + + + Builds a color from a byte array + + Byte array containing a 16 byte color + Beginning position in the byte array + True if the byte array stores inverted values, + otherwise false. For example the color black (fully opaque) inverted + would be 0xFF 0xFF 0xFF 0x00 - - Provide a single instance of the MD5 class to avoid making - duplicate copies and handle thread safety - - - Provide a single instance of the SHA-1 class to avoid - making duplicate copies and handle thread safety - - - Provide a single instance of a random number generator - to avoid making duplicate copies and handle thread safety - - + - Clamp a given value between a range + Returns the raw bytes for this vector - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper + Byte array containing a 16 byte color + Beginning position in the byte array + True if the byte array stores inverted values, + otherwise false. For example the color black (fully opaque) inverted + would be 0xFF 0xFF 0xFF 0x00 + True if the alpha value is inverted in + addition to whatever the inverted parameter is. Setting inverted true + and alphaInverted true will flip the alpha value back to non-inverted, + but keep the other color bytes inverted + A 16 byte array containing R, G, B, and A - + - Clamp a given value between a range + Copy constructor - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper + Color to copy - - - Clamp a given value between a range - - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper + + Red - - - Round a floating-point value to the nearest integer - - Floating point number to round - Integer + + Green - - - Test if a single precision float is a finite number - + + Blue - - - Test if a double precision float is a finite number - + + Alpha - - - Get the distance between two floating-point values - - First value - Second value - The distance between the two values + + A Color4 with zero RGB values and fully opaque (alpha 1.0) - - - Compute the MD5 hash for a byte array - - Byte array to compute the hash for - MD5 hash of the input data + + A Color4 with full RGB values (1.0) and fully opaque (alpha 1.0) - + - Compute the SHA1 hash for a byte array + IComparable.CompareTo implementation - Byte array to compute the hash for - SHA1 hash of the input data + Sorting ends up like this: |--Grayscale--||--Color--|. + Alpha is only used when the colors are otherwise equivalent - + - Calculate the SHA1 hash of a given string + Builds a color from a byte array - The string to hash - The SHA1 hash as a string + Byte array containing a 16 byte color + Beginning position in the byte array + True if the byte array stores inverted values, + otherwise false. For example the color black (fully opaque) inverted + would be 0xFF 0xFF 0xFF 0x00 + True if the alpha value is inverted in + addition to whatever the inverted parameter is. Setting inverted true + and alphaInverted true will flip the alpha value back to non-inverted, + but keep the other color bytes inverted - + - Compute the SHA256 hash for a byte array + Writes the raw bytes for this color to a byte array - Byte array to compute the hash for - SHA256 hash of the input data + Destination byte array + Position in the destination array to start + writing. Must be at least 16 bytes before the end of the array - + - Calculate the SHA256 hash of a given string + Serializes this color into four bytes in a byte array - The string to hash - The SHA256 hash as a string + Destination byte array + Position in the destination array to start + writing. Must be at least 4 bytes before the end of the array + True to invert the output (1.0 becomes 0 + instead of 255) - + - Calculate the MD5 hash of a given string + Writes the raw bytes for this color to a byte array - The password to hash - An MD5 hash in string format, with $1$ prepended + Destination byte array + Position in the destination array to start + writing. Must be at least 16 bytes before the end of the array - + - Calculate the MD5 hash of a given string + Ensures that values are in range 0-1 - The string to hash - The MD5 hash as a string - + - Generate a random double precision floating point value + Create an RGB color from a hue, saturation, value combination - Random value of type double + Hue + Saturation + Value + An fully opaque RGB color (alpha is 1.0) - + - Get the current running platform + Performs linear interpolation between two colors - Enumeration of the current platform we are running on + Color to start at + Color to end at + Amount to interpolate + The interpolated color - + - Get the current running runtime + Attribute class that allows extra attributes to be attached to ENUMs - Enumeration of the current runtime we are running on - - - Convert the first two bytes starting in the byte array in - little endian ordering to a signed short integer - - An array two bytes or longer - A signed short integer, will be zero if a short can't be - read at the given position + + Default initializer - - - Convert the first two bytes starting at the given position in - little endian ordering to a signed short integer - - An array two bytes or longer - Position in the array to start reading - A signed short integer, will be zero if a short can't be - read at the given position + + Text used when presenting ENUM to user - - - Convert the first four bytes starting at the given position in - little endian ordering to a signed integer - - An array four bytes or longer - Position to start reading the int from - A signed integer, will be zero if an int can't be read - at the given position + + Text used when presenting ENUM to user - + - Convert the first four bytes of the given array in little endian - ordering to a signed integer + The different types of grid assets - An array four bytes or longer - A signed integer, will be zero if the array contains - less than four bytes - - - Convert the first eight bytes of the given array in little endian - ordering to a signed long integer - - An array eight bytes or longer - A signed long integer, will be zero if the array contains - less than eight bytes + + Unknown asset type - - - Convert the first eight bytes starting at the given position in - little endian ordering to a signed long integer - - An array eight bytes or longer - Position to start reading the long from - A signed long integer, will be zero if a long can't be read - at the given position + + Texture asset, stores in JPEG2000 J2C stream format - - - Convert the first two bytes starting at the given position in - little endian ordering to an unsigned short - - Byte array containing the ushort - Position to start reading the ushort from - An unsigned short, will be zero if a ushort can't be read - at the given position + + Sound asset - - - Convert two bytes in little endian ordering to an unsigned short - - Byte array containing the ushort - An unsigned short, will be zero if a ushort can't be - read + + Calling card for another avatar - - - Convert the first four bytes starting at the given position in - little endian ordering to an unsigned integer - - Byte array containing the uint - Position to start reading the uint from - An unsigned integer, will be zero if a uint can't be read - at the given position + + Link to a location in world - - - Convert the first four bytes of the given array in little endian - ordering to an unsigned integer - - An array four bytes or longer - An unsigned integer, will be zero if the array contains - less than four bytes + + Collection of textures and parameters that can be + worn by an avatar - - - Convert the first eight bytes of the given array in little endian - ordering to an unsigned 64-bit integer - - An array eight bytes or longer - An unsigned 64-bit integer, will be zero if the array - contains less than eight bytes + + Primitive that can contain textures, sounds, + scripts and more - - - Convert four bytes in little endian ordering to a floating point - value - - Byte array containing a little ending floating - point value - Starting position of the floating point value in - the byte array - Single precision value + + Notecard asset - - - Convert an integer to a byte array in little endian format - - The integer to convert - A four byte little endian array + + Holds a collection of inventory items - - - Convert an integer to a byte array in big endian format - - The integer to convert - A four byte big endian array + + Root inventory folder - - - Convert a 64-bit integer to a byte array in little endian format - - The value to convert - An 8 byte little endian array + + Linden scripting language script - - - Convert a 64-bit unsigned integer to a byte array in little endian - format - - The value to convert - An 8 byte little endian array + + LSO bytecode for a script - - - Convert a floating point value to four bytes in little endian - ordering - - A floating point value - A four byte array containing the value in little endian - ordering + + Uncompressed TGA texture - - - Converts an unsigned integer to a hexadecimal string - - An unsigned integer to convert to a string - A hexadecimal string 10 characters long - 0x7fffffff + + Collection of textures and shape parameters that can + be worn - - - Convert a variable length UTF8 byte array to a string - - The UTF8 encoded byte array to convert - The decoded string + + Trash folder - - - Converts a byte array to a string containing hexadecimal characters - - The byte array to convert to a string - The name of the field to prepend to each - line of the string - A string containing hexadecimal characters on multiple - lines. Each line is prepended with the field name + + Snapshot folder - - - Converts a byte array to a string containing hexadecimal characters - - The byte array to convert to a string - Number of bytes in the array to parse - A string to prepend to each line of the hex - dump - A string containing hexadecimal characters on multiple - lines. Each line is prepended with the field name + + Lost and found folder - - - Convert a string to a UTF8 encoded byte array - - The string to convert - A null-terminated UTF8 byte array + + Uncompressed sound - - - Converts a string containing hexadecimal characters to a byte array - - String containing hexadecimal characters - If true, gracefully handles null, empty and - uneven strings as well as stripping unconvertable characters - The converted byte array + + Uncompressed TGA non-square image, not to be used as a + texture - + + Compressed JPEG non-square image, not to be used as a + texture + + + Animation + + + Sequence of animations, sounds, chat, and pauses + + + Simstate file + + + Contains landmarks for favorites + + + Asset is a link to another inventory item + + + Asset is a link to another inventory folder + + + Beginning of the range reserved for ensembles + + + End of the range reserved for ensembles + + + Folder containing inventory links to wearables and attachments + that are part of the current outfit + + + Folder containing inventory items or links to + inventory items of wearables and attachments + together make a full outfit + + + Root folder for the folders of type OutfitFolder + + + Linden mesh format + + - Returns true is c is a hexadecimal digit (A-F, a-f, 0-9) + Inventory Item Types, eg Script, Notecard, Folder, etc - Character to test - true if hex digit, false if not - + + Unknown + + + Texture + + + Sound + + + Calling Card + + + Landmark + + + Notecard + + - Converts 1 or 2 character string into equivalant byte value - 1 or 2 character string - byte - + + Folder + + - Convert a float value to a byte given a minimum and maximum range - Value to convert to a byte - Minimum value range - Maximum value range - A single byte representing the original float value - + + an LSL Script + + - Convert a byte to a float value given a minimum and maximum range - Byte array to get the byte from - Position in the byte array the desired byte is at - Minimum value range - Maximum value range - A float value inclusively between lower and upper - + - Convert a byte to a float value given a minimum and maximum range - Byte to convert to a float value - Minimum value range - Maximum value range - A float value inclusively between lower and upper - + - Attempts to parse a floating point value from a string, using an - EN-US number format - String to parse - Resulting floating point number - True if the parse was successful, otherwise false - + - Attempts to parse a floating point value from a string, using an - EN-US number format - String to parse - Resulting floating point number - True if the parse was successful, otherwise false - + - Tries to parse an unsigned 32-bit integer from a hexadecimal string - String to parse - Resulting integer - True if the parse was successful, otherwise false - + - Takes an AssetType and returns the string representation - The source - The string version of the AssetType - + - Translate a string name of an AssetType into the proper Type + Item Sale Status - A string containing the AssetType name - The AssetType which matches the string name, or AssetType.Unknown if no match was found - + + Not for sale + + + The original is for sale + + + Copies are for sale + + + The contents of the object are for sale + + - Convert an InventoryType to a string + Types of wearable assets - The to convert - A string representation of the source - + + Body shape + + + Skin textures and attributes + + + Hair + + + Eyes + + + Shirt + + + Pants + + + Shoes + + + Socks + + + Jacket + + + Gloves + + + Undershirt + + + Underpants + + + Skirt + + + Alpha mask to hide parts of the avatar + + + Tattoo + + + Invalid wearable asset + + - Convert a string into a valid InventoryType + Identifier code for primitive types - A string representation of the InventoryType to convert - A InventoryType object which matched the type - + + None + + + A Primitive + + + A Avatar + + + Linden grass + + + Linden tree + + + A primitive that acts as the source for a particle stream + + + A Linden tree + + - Convert a SaleType to a string + Primary parameters for primitives such as Physics Enabled or Phantom - The to convert - A string representation of the source - + + Deprecated + + + Whether physics are enabled for this object + + - Convert a string into a valid SaleType - A string representation of the SaleType to convert - A SaleType object which matched the type - + - Copy a byte array - Byte array to copy - A copy of the given byte array - + - Packs to 32-bit unsigned integers in to a 64-bit unsigned integer - The left-hand (or X) value - The right-hand (or Y) value - A 64-bit integer containing the two 32-bit input values - + - Unpacks two 32-bit unsigned integers from a 64-bit unsigned integer - The 64-bit input integer - The left-hand (or X) output value - The right-hand (or Y) output value - + - Convert an IP address object to an unsigned 32-bit integer - IP address to convert - 32-bit unsigned integer holding the IP address bits - + - Gets a unix timestamp for the current time - An unsigned integer representing a unix timestamp for now - + + Whether this object contains an active touch script + + - Convert a UNIX timestamp to a native DateTime object - An unsigned integer representing a UNIX - timestamp - A DateTime object containing the same time specified in - the given timestamp - + + Whether this object can receive payments + + + Whether this object is phantom (no collisions) + + - Convert a UNIX timestamp to a native DateTime object - A signed integer representing a UNIX - timestamp - A DateTime object containing the same time specified in - the given timestamp - + - Convert a native DateTime object to a UNIX timestamp - A DateTime object you want to convert to a - timestamp - An unsigned integer representing a UNIX timestamp - + - Swap two values - Type of the values to swap - First value - Second value - + - Try to parse an enumeration value from a string - Enumeration type - String value to parse - Enumeration value on success - True if the parsing succeeded, otherwise false - + + Deprecated + + - Swaps the high and low words in a byte. Converts aaaabbbb to bbbbaaaa - Byte to swap the words in - Byte value with the words swapped - + - Attempts to convert a string representation of a hostname or IP - address to a - Hostname to convert to an IPAddress - Converted IP address object, or null if the conversion - failed - + - Operating system - - Unknown - - - Microsoft Windows + + Deprecated - - Microsoft Windows CE + + + - - Linux + + + - - Apple OSX + + + - + - Runtime platform - - .NET runtime + + Server flag, will not be sent to clients. Specifies that + the object is destroyed when it touches a simulator edge - - Mono runtime: http://www.mono-project.com/ + + Server flag, will not be sent to clients. Specifies that + the object will be returned to the owner's inventory when it + touches a simulator edge - + + Server flag, will not be sent to clients. + + + Server flag, will not be sent to client. Specifies that + the object is hovering/flying + + - Convert this matrix to euler rotations - X euler angle - Y euler angle - Z euler angle - + - Convert this matrix to a quaternion rotation - A quaternion representation of this rotation matrix - + - Construct a matrix from euler rotation values in radians - X euler angle in radians - Y euler angle in radians - Z euler angle in radians - + - Get a formatted string representation of the vector - A string representation of the vector - - A 4x4 matrix containing all zeroes + + + Sound flags for sounds attached to primitives + - - A 4x4 identity matrix + + + - - For thread safety + + + - - For thread safety + + + - + - Purges expired objects from the cache. Called automatically by the purge timer. - - X value + + + - - Y value + + + - - Z value + + + - - W value + + + Material type for a primitive + - + - Constructor, builds a vector from a byte array - Byte array containing four four-byte floats - Beginning position in the byte array - + - Test if this vector is equal to another vector, within a given - tolerance range - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false - + - IComparable.CompareTo implementation - + - Test if this vector is composed of all finite numbers - + - Builds a vector from a byte array - Byte array containing a 16 byte vector - Beginning position in the byte array - + - Returns the raw bytes for this vector - A 16 byte array containing X, Y, Z, and W - + - Writes the raw bytes for this vector to a byte array - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array - + - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only - Raw string representation of the vector - - A vector with a value of 0,0,0,0 - - - A vector with a value of 1,1,1,1 + + + Used in a helper function to roughly determine prim shape + - - A vector with a value of 1,0,0,0 + + + Extra parameters for primitives, these flags are for features that have + been added after the original ObjectFlags that has all eight bits + reserved already + - - A vector with a value of 0,1,0,0 + + Whether this object has flexible parameters - - A vector with a value of 0,0,1,0 + + Whether this object has light parameters - - A vector with a value of 0,0,0,1 + + Whether this object is a sculpted prim - + - Provides helper methods for parallelizing loops - + - Executes a for loop in which iterations may run in parallel - The loop will be started at this index - The loop will be terminated before this index is reached - Method body to run for each iteration of the loop - + - Executes a for loop in which iterations may run in parallel - The number of concurrent execution threads to run - The loop will be started at this index - The loop will be terminated before this index is reached - Method body to run for each iteration of the loop - + - Executes a foreach loop in which iterations may run in parallel - Object type that the collection wraps - An enumerable collection to iterate over - Method body to run for each object in the collection - + - Executes a foreach loop in which iterations may run in parallel - Object type that the collection wraps - The number of concurrent execution threads to run - An enumerable collection to iterate over - Method body to run for each object in the collection - + - Executes a series of tasks in parallel - A series of method bodies to execute - + - Executes a series of tasks in parallel - The number of concurrent execution threads to run - A series of method bodies to execute - + - A three-dimensional vector with floating-point values - - X value - - - Y value - - - Z value - - + - Constructor, builds a vector from a byte array - Byte array containing three four-byte floats - Beginning position in the byte array - + - Test if this vector is equal to another vector, within a given - tolerance range - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false - + - IComparable.CompareTo implementation - + - Test if this vector is composed of all finite numbers - + - Builds a vector from a byte array - Byte array containing a 12 byte vector - Beginning position in the byte array - + - Returns the raw bytes for this vector - A 12 byte array containing X, Y, and Z - + - Writes the raw bytes for this vector to a byte array - Destination byte array - Position in the destination array to start - writing. Must be at least 12 bytes before the end of the array - + - Parse a vector from a string - A string representation of a 3D vector, enclosed - in arrow brackets and separated by commas - + - Calculate the rotation between two vectors - Normalized directional vector (such as 1,0,0 for forward facing) - Normalized target vector - + - Interpolates between two vectors using a cubic equation - + - Get a formatted string representation of the vector - A string representation of the vector - + - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only - Raw string representation of the vector - + - Cross product between two vectors - - A vector with a value of 0,0,0 - - - A vector with a value of 1,1,1 - - - A unit vector facing forward (X axis), value 1,0,0 - - - A unit vector facing left (Y axis), value 0,1,0 - - - A unit vector facing up (Z axis), value 0,0,1 - - + - A 128-bit Universally Unique Identifier, used throughout the Second - Life networking protocol - - The System.Guid object this struct wraps around - - + - Constructor that takes a string UUID representation - A string representation of a UUID, case - insensitive and can either be hyphenated or non-hyphenated - UUID("11f8aa9c-b071-4242-836b-13b7abe0d489") - + - Constructor that takes a System.Guid object - A Guid object that contains the unique identifier - to be represented by this UUID - + - Constructor that takes a byte array containing a UUID - Byte array containing a 16 byte UUID - Beginning offset in the array - + - Constructor that takes an unsigned 64-bit unsigned integer to - convert to a UUID - 64-bit unsigned integer to convert to a UUID - + - Copy constructor - UUID to copy - + - IComparable.CompareTo implementation - + - Assigns this UUID from 16 bytes out of a byte array - Byte array containing the UUID to assign this UUID to - Starting position of the UUID in the byte array - + - Returns a copy of the raw bytes for this UUID - A 16 byte array containing this UUID - + - Writes the raw bytes for this UUID to a byte array - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array - + - Calculate an LLCRC (cyclic redundancy check) for this UUID + Attachment points for objects on avatar bodies - The CRC checksum for this UUID + + Both InventoryObject and InventoryAttachment types can be attached + - + + Right hand if object was not previously attached + + + Chest + + + Skull + + + Left shoulder + + + Right shoulder + + + Left hand + + + Right hand + + + Left foot + + + Right foot + + + Spine + + + Pelvis + + + Mouth + + + Chin + + + Left ear + + + Right ear + + + Left eyeball + + + Right eyeball + + + Nose + + + Right upper arm + + + Right forearm + + + Left upper arm + + + Left forearm + + + Right hip + + + Right upper leg + + + Right lower leg + + + Left hip + + + Left upper leg + + + Left lower leg + + + Stomach + + + Left pectoral + + + Right pectoral + + + HUD Center position 2 + + + HUD Top-right + + + HUD Top + + + HUD Top-left + + + HUD Center + + + HUD Bottom-left + + + HUD Bottom + + + HUD Bottom-right + + - Create a 64-bit integer representation from the second half of this UUID + Tree foliage types - An integer created from the last eight bytes of this UUID - + + Pine1 tree + + + Oak tree + + + Tropical Bush1 + + + Palm1 tree + + + Dogwood tree + + + Tropical Bush2 + + + Palm2 tree + + + Cypress1 tree + + + Cypress2 tree + + + Pine2 tree + + + Plumeria + + + Winter pinetree1 + + + Winter Aspen tree + + + Winter pinetree2 + + + Eucalyptus tree + + + Fern + + + Eelgrass + + + Sea Sword + + + Kelp1 plant + + + Beach grass + + + Kelp2 plant + + - Generate a UUID from a string + Grass foliage types - A string representation of a UUID, case - insensitive and can either be hyphenated or non-hyphenated - UUID.Parse("11f8aa9c-b071-4242-836b-13b7abe0d489") - + - Generate a UUID from a string - A string representation of a UUID, case - insensitive and can either be hyphenated or non-hyphenated - Will contain the parsed UUID if successful, - otherwise null - True if the string was successfully parse, otherwise false - UUID.TryParse("11f8aa9c-b071-4242-836b-13b7abe0d489", result) - + - Combine two UUIDs together by taking the MD5 hash of a byte array - containing both UUIDs - First UUID to combine - Second UUID to combine - The UUID product of the combination - + - - - + - Return a hash code for this UUID, used by .NET for hash tables - An integer composed of all the UUID bytes XORed together - + - Comparison function - An object to compare to this UUID - True if the object is a UUID and both UUIDs are equal - + - Comparison function - UUID to compare to - True if the UUIDs are equal, otherwise false - + - Get a hyphenated string representation of this UUID + Action associated with clicking on an object - A string representation of this UUID, lowercase and - with hyphens - 11f8aa9c-b071-4242-836b-13b7abe0d489 - - - Equals operator - - First UUID for comparison - Second UUID for comparison - True if the UUIDs are byte for byte equal, otherwise false - - - - Not equals operator - - First UUID for comparison - Second UUID for comparison - True if the UUIDs are not equal, otherwise true - - - - XOR operator - - First UUID - Second UUID - A UUID that is a XOR combination of the two input UUIDs + + Touch object - - - String typecasting operator - - A UUID in string form. Case insensitive, - hyphenated or non-hyphenated - A UUID built from the string representation + + Sit on object - - An UUID with a value of all zeroes + + Purchase object or contents - - A cache of UUID.Zero as a string to optimize a common path + + Pay the object - - - A two-dimensional vector with floating-point values - + + Open task inventory - - X value + + Play parcel media - - Y value + + Open parcel media - - - Test if this vector is equal to another vector, within a given - tolerance range - - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false + + For thread safety - - - Test if this vector is composed of all finite numbers - + + For thread safety - + - IComparable.CompareTo implementation + Purges expired objects from the cache. Called automatically by the purge timer. - + - Builds a vector from a byte array + A thread-safe lockless queue that supports multiple readers and + multiple writers - Byte array containing two four-byte floats - Beginning position in the byte array - + - Returns the raw bytes for this vector + Constructor - An eight-byte array containing X and Y - + - Writes the raw bytes for this vector to a byte array + Provides a node container for data in a singly linked list - Destination byte array - Position in the destination array to start - writing. Must be at least 8 bytes before the end of the array - + - Parse a vector from a string + Constructor - A string representation of a 2D vector, enclosed - in arrow brackets and separated by commas - + - Interpolates between two vectors using a cubic equation + Constructor - - - Get a formatted string representation of the vector - - A string representation of the vector + + Pointer to the next node in list - - - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only - - Raw string representation of the vector + + The data contained by the node - - A vector with a value of 0,0 + + Queue head - - A vector with a value of 1,1 + + Queue tail - - A vector with a value of 1,0 + + Queue item count - - A vector with a value of 0,1 + + Gets the current number of items in the queue. Since this + is a lockless collection this value should be treated as a close + estimate - + - An 8-bit color structure including an alpha channel + Enqueue an item + Item to enqeue - - Red - - - Green + + + Try to dequeue an item + + Dequeued item if the dequeue was successful + True if an item was successfully deqeued, otherwise false - - Blue + + A 4x4 matrix containing all zeroes - - Alpha + + A 4x4 identity matrix - + - + Convert this matrix to euler rotations - - - - + X euler angle + Y euler angle + Z euler angle - + - Builds a color from a byte array + Convert this matrix to a quaternion rotation - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 + A quaternion representation of this rotation matrix - + - Returns the raw bytes for this vector + Construct a matrix from euler rotation values in radians - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - True if the alpha value is inverted in - addition to whatever the inverted parameter is. Setting inverted true - and alphaInverted true will flip the alpha value back to non-inverted, - but keep the other color bytes inverted - A 16 byte array containing R, G, B, and A + X euler angle in radians + Y euler angle in radians + Z euler angle in radians - + - Copy constructor + Get a formatted string representation of the vector - Color to copy + A string representation of the vector - + - IComparable.CompareTo implementation + Provides helper methods for parallelizing loops - Sorting ends up like this: |--Grayscale--||--Color--|. - Alpha is only used when the colors are otherwise equivalent - + - Builds a color from a byte array + Executes a for loop in which iterations may run in parallel - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - True if the alpha value is inverted in - addition to whatever the inverted parameter is. Setting inverted true - and alphaInverted true will flip the alpha value back to non-inverted, - but keep the other color bytes inverted + The loop will be started at this index + The loop will be terminated before this index is reached + Method body to run for each iteration of the loop - + - Writes the raw bytes for this color to a byte array + Executes a for loop in which iterations may run in parallel - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array + The number of concurrent execution threads to run + The loop will be started at this index + The loop will be terminated before this index is reached + Method body to run for each iteration of the loop - + - Serializes this color into four bytes in a byte array + Executes a foreach loop in which iterations may run in parallel - Destination byte array - Position in the destination array to start - writing. Must be at least 4 bytes before the end of the array - True to invert the output (1.0 becomes 0 - instead of 255) + Object type that the collection wraps + An enumerable collection to iterate over + Method body to run for each object in the collection - + - Writes the raw bytes for this color to a byte array + Executes a foreach loop in which iterations may run in parallel - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array + Object type that the collection wraps + The number of concurrent execution threads to run + An enumerable collection to iterate over + Method body to run for each object in the collection - + - Ensures that values are in range 0-1 + Executes a series of tasks in parallel + A series of method bodies to execute - + - Create an RGB color from a hue, saturation, value combination + Executes a series of tasks in parallel - Hue - Saturation - Value - An fully opaque RGB color (alpha is 1.0) + The number of concurrent execution threads to run + A series of method bodies to execute - + - Performs linear interpolation between two colors + Build a quaternion from normalized float values - Color to start at - Color to end at - Amount to interpolate - The interpolated color - - - A Color4 with zero RGB values and fully opaque (alpha 1.0) - - - A Color4 with full RGB values (1.0) and fully opaque (alpha 1.0) + X value from -1.0 to 1.0 + Y value from -1.0 to 1.0 + Z value from -1.0 to 1.0 - + - The different types of grid assets + Constructor, builds a quaternion object from a byte array + Byte array containing four four-byte floats + Offset in the byte array to start reading at + Whether the source data is normalized or + not. If this is true 12 bytes will be read, otherwise 16 bytes will + be read. - - Unknown asset type + + X value - - Texture asset, stores in JPEG2000 J2C stream format + + Y value + + + Z value + + + W value + + + A quaternion with a value of 0,0,0,1 + + + + Normalizes the quaternion + + + + + Builds a quaternion object from a byte array + + The source byte array + Offset in the byte array to start reading at + Whether the source data is normalized or + not. If this is true 12 bytes will be read, otherwise 16 bytes will + be read. + + + + Normalize this quaternion and serialize it to a byte array + + A 12 byte array containing normalized X, Y, and Z floating + point values in order using little endian byte ordering + + + + Writes the raw bytes for this quaternion to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 12 bytes before the end of the array + + + + Convert this quaternion to euler angles + + X euler angle + Y euler angle + Z euler angle + + + + Convert this quaternion to an angle around an axis + + Unit vector describing the axis + Angle around the axis, in radians + + + + Returns the conjugate (spatial inverse) of a quaternion + + + + + Build a quaternion from an axis and an angle of rotation around + that axis + + + + + Build a quaternion from an axis and an angle of rotation around + that axis + + Axis of rotation + Angle of rotation + + + + Creates a quaternion from a vector containing roll, pitch, and yaw + in radians + + Vector representation of the euler angles in + radians + Quaternion representation of the euler angles + + + + Creates a quaternion from roll, pitch, and yaw euler angles in + radians + + X angle in radians + Y angle in radians + Z angle in radians + Quaternion representation of the euler angles + + + + Conjugates and renormalizes a vector + + + + + Spherical linear interpolation between two quaternions + + + + + Get a string representation of the quaternion elements with up to three + decimal digits and separated by spaces only + + Raw string representation of the quaternion + + + + Determines the appropriate events to set, leaves the locks, and sets the events. + + + + + A routine for lazily creating a event outside the lock (so if errors + happen they are outside the lock and that we don't do much work + while holding a spin lock). If all goes well, reenter the lock and + set 'waitEvent' + + + + + Waits on 'waitEvent' with a timeout of 'millisceondsTimeout. + Before the wait 'numWaiters' is incremented and is restored before leaving this routine. + + + + + A hierarchical token bucket for bandwidth throttling. See + http://en.wikipedia.org/wiki/Token_bucket for more information + + + + + Default constructor + + Parent bucket if this is a child bucket, or + null if this is a root bucket + Maximum size of the bucket in bytes, or + zero if this bucket has no maximum capacity + Rate that the bucket fills, in bytes per + second. If zero, the bucket always remains full + + + Parent bucket to this bucket, or null if this is a root + bucket + + + Size of the bucket in bytes. If zero, the bucket has + infinite capacity + + + Rate that the bucket fills, in bytes per millisecond. If + zero, the bucket always remains full + + + Number of tokens currently in the bucket + + + Time of the last drip, in system ticks + + + + The parent bucket of this bucket, or null if this bucket has no + parent. The parent bucket will limit the aggregate bandwidth of all + of its children buckets + + + + + Maximum burst rate in bytes per second. This is the maximum number + of tokens that can accumulate in the bucket at any one time + + + + + The speed limit of this bucket in bytes per second. This is the + number of tokens that are added to the bucket per second + + Tokens are added to the bucket any time + is called, at the granularity of + the system tick interval (typically around 15-22ms) + + + + The number of bytes that can be sent at this moment. This is the + current number of tokens in the bucket + If this bucket has a parent bucket that does not have + enough tokens for a request, will + return false regardless of the content of this bucket + + + + Remove a given number of tokens from the bucket + + Number of tokens to remove from the bucket + True if the requested number of tokens were removed from + the bucket, otherwise false + + + + Remove a given number of tokens from the bucket + + Number of tokens to remove from the bucket + True if tokens were added to the bucket + during this call, otherwise false + True if the requested number of tokens were removed from + the bucket, otherwise false + + + + Add tokens to the bucket over time. The number of tokens added each + call depends on the length of time that has passed since the last + call to Drip + + True if tokens were added to the bucket, otherwise false + + + + A 128-bit Universally Unique Identifier, used throughout the Second + Life networking protocol + + + + + Constructor that takes a string UUID representation + + A string representation of a UUID, case + insensitive and can either be hyphenated or non-hyphenated + UUID("11f8aa9c-b071-4242-836b-13b7abe0d489") + + + + Constructor that takes a System.Guid object + + A Guid object that contains the unique identifier + to be represented by this UUID + + + + Constructor that takes a byte array containing a UUID + + Byte array containing a 16 byte UUID + Beginning offset in the array + + + + Constructor that takes an unsigned 64-bit unsigned integer to + convert to a UUID + + 64-bit unsigned integer to convert to a UUID + + + + Copy constructor + + UUID to copy + + + The System.Guid object this struct wraps around + + + An UUID with a value of all zeroes + + + A cache of UUID.Zero as a string to optimize a common path + + + + IComparable.CompareTo implementation + + + + + Assigns this UUID from 16 bytes out of a byte array + + Byte array containing the UUID to assign this UUID to + Starting position of the UUID in the byte array + + + + Returns a copy of the raw bytes for this UUID + + A 16 byte array containing this UUID + + + + Writes the raw bytes for this UUID to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 16 bytes before the end of the array + + + + Calculate an LLCRC (cyclic redundancy check) for this UUID + + The CRC checksum for this UUID + + + + Create a 64-bit integer representation from the second half of this UUID + + An integer created from the last eight bytes of this UUID + + + + Generate a UUID from a string + + A string representation of a UUID, case + insensitive and can either be hyphenated or non-hyphenated + UUID.Parse("11f8aa9c-b071-4242-836b-13b7abe0d489") + + + + Generate a UUID from a string + + A string representation of a UUID, case + insensitive and can either be hyphenated or non-hyphenated + Will contain the parsed UUID if successful, + otherwise null + True if the string was successfully parse, otherwise false + UUID.TryParse("11f8aa9c-b071-4242-836b-13b7abe0d489", result) + + + + Combine two UUIDs together by taking the MD5 hash of a byte array + containing both UUIDs + + First UUID to combine + Second UUID to combine + The UUID product of the combination + + + + + + + + + + Return a hash code for this UUID, used by .NET for hash tables + + An integer composed of all the UUID bytes XORed together + + + + Comparison function + + An object to compare to this UUID + True if the object is a UUID and both UUIDs are equal + + + + Comparison function + + UUID to compare to + True if the UUIDs are equal, otherwise false + + + + Get a hyphenated string representation of this UUID + + A string representation of this UUID, lowercase and + with hyphens + 11f8aa9c-b071-4242-836b-13b7abe0d489 + + + + Equals operator + + First UUID for comparison + Second UUID for comparison + True if the UUIDs are byte for byte equal, otherwise false + + + + Not equals operator + + First UUID for comparison + Second UUID for comparison + True if the UUIDs are not equal, otherwise true + + + + XOR operator + + First UUID + Second UUID + A UUID that is a XOR combination of the two input UUIDs + + + + String typecasting operator + + A UUID in string form. Case insensitive, + hyphenated or non-hyphenated + A UUID built from the string representation + + + + Operating system + + + + Unknown + + + Microsoft Windows + + + Microsoft Windows CE + + + Linux + + + Apple OSX + + + + Runtime platform + + + + .NET runtime + + + Mono runtime: http://www.mono-project.com/ + + + Used for converting degrees to radians + + + Used for converting radians to degrees + + + Provide a single instance of the CultureInfo class to + help parsing in situations where the grid assumes an en-us + culture + + + UNIX epoch in DateTime format + + + Provide a single instance of the MD5 class to avoid making + duplicate copies and handle thread safety + + + Provide a single instance of the SHA-1 class to avoid + making duplicate copies and handle thread safety + + + Provide a single instance of a random number generator + to avoid making duplicate copies and handle thread safety + + + + Clamp a given value between a range + + Value to clamp + Minimum allowable value + Maximum allowable value + A value inclusively between lower and upper + + + + Clamp a given value between a range + + Value to clamp + Minimum allowable value + Maximum allowable value + A value inclusively between lower and upper + + + + Clamp a given value between a range + + Value to clamp + Minimum allowable value + Maximum allowable value + A value inclusively between lower and upper + + + + Round a floating-point value to the nearest integer + + Floating point number to round + Integer + + + + Test if a single precision float is a finite number + + + + + Test if a double precision float is a finite number + + + + + Get the distance between two floating-point values + + First value + Second value + The distance between the two values + + + + Compute the MD5 hash for a byte array + + Byte array to compute the hash for + MD5 hash of the input data + + + + Compute the SHA1 hash for a byte array + + Byte array to compute the hash for + SHA1 hash of the input data + + + + Calculate the SHA1 hash of a given string + + The string to hash + The SHA1 hash as a string + + + + Compute the SHA256 hash for a byte array + + Byte array to compute the hash for + SHA256 hash of the input data + + + + Calculate the SHA256 hash of a given string + + The string to hash + The SHA256 hash as a string + + + + Calculate the MD5 hash of a given string + + The password to hash + An MD5 hash in string format, with $1$ prepended + + + + Calculate the MD5 hash of a given string + + The string to hash + The MD5 hash as a string + + + + Generate a random double precision floating point value + + Random value of type double + + + + Get the current running platform + + Enumeration of the current platform we are running on + + + + Get the current running runtime + + Enumeration of the current runtime we are running on + + + + Convert the first two bytes starting in the byte array in + little endian ordering to a signed short integer + + An array two bytes or longer + A signed short integer, will be zero if a short can't be + read at the given position + + + + Convert the first two bytes starting at the given position in + little endian ordering to a signed short integer + + An array two bytes or longer + Position in the array to start reading + A signed short integer, will be zero if a short can't be + read at the given position + + + + Convert the first four bytes starting at the given position in + little endian ordering to a signed integer + + An array four bytes or longer + Position to start reading the int from + A signed integer, will be zero if an int can't be read + at the given position - - Sound asset + + + Convert the first four bytes of the given array in little endian + ordering to a signed integer + + An array four bytes or longer + A signed integer, will be zero if the array contains + less than four bytes - - Calling card for another avatar + + + Convert the first eight bytes of the given array in little endian + ordering to a signed long integer + + An array eight bytes or longer + A signed long integer, will be zero if the array contains + less than eight bytes - - Link to a location in world + + + Convert the first eight bytes starting at the given position in + little endian ordering to a signed long integer + + An array eight bytes or longer + Position to start reading the long from + A signed long integer, will be zero if a long can't be read + at the given position - - Collection of textures and parameters that can be - worn by an avatar + + + Convert the first two bytes starting at the given position in + little endian ordering to an unsigned short + + Byte array containing the ushort + Position to start reading the ushort from + An unsigned short, will be zero if a ushort can't be read + at the given position - - Primitive that can contain textures, sounds, - scripts and more + + + Convert two bytes in little endian ordering to an unsigned short + + Byte array containing the ushort + An unsigned short, will be zero if a ushort can't be + read - - Notecard asset + + + Convert the first four bytes starting at the given position in + little endian ordering to an unsigned integer + + Byte array containing the uint + Position to start reading the uint from + An unsigned integer, will be zero if a uint can't be read + at the given position - - Holds a collection of inventory items + + + Convert the first four bytes of the given array in little endian + ordering to an unsigned integer + + An array four bytes or longer + An unsigned integer, will be zero if the array contains + less than four bytes - - Root inventory folder + + + Convert the first eight bytes of the given array in little endian + ordering to an unsigned 64-bit integer + + An array eight bytes or longer + An unsigned 64-bit integer, will be zero if the array + contains less than eight bytes - - Linden scripting language script + + + Convert four bytes in little endian ordering to a floating point + value + + Byte array containing a little ending floating + point value + Starting position of the floating point value in + the byte array + Single precision value - - LSO bytecode for a script + + + Convert an integer to a byte array in little endian format + + The integer to convert + A four byte little endian array + + + + Convert an integer to a byte array in big endian format + + The integer to convert + A four byte big endian array + + + + Convert a 64-bit integer to a byte array in little endian format + + The value to convert + An 8 byte little endian array + + + + Convert a 64-bit unsigned integer to a byte array in little endian + format + + The value to convert + An 8 byte little endian array + + + + Convert a floating point value to four bytes in little endian + ordering + + A floating point value + A four byte array containing the value in little endian + ordering + + + + Converts an unsigned integer to a hexadecimal string + + An unsigned integer to convert to a string + A hexadecimal string 10 characters long + 0x7fffffff + + + + Convert a variable length UTF8 byte array to a string + + The UTF8 encoded byte array to convert + The decoded string + + + + Converts a byte array to a string containing hexadecimal characters + + The byte array to convert to a string + The name of the field to prepend to each + line of the string + A string containing hexadecimal characters on multiple + lines. Each line is prepended with the field name + + + + Converts a byte array to a string containing hexadecimal characters + + The byte array to convert to a string + Number of bytes in the array to parse + A string to prepend to each line of the hex + dump + A string containing hexadecimal characters on multiple + lines. Each line is prepended with the field name + + + + Convert a string to a UTF8 encoded byte array + + The string to convert + A null-terminated UTF8 byte array + + + + Converts a string containing hexadecimal characters to a byte array + + String containing hexadecimal characters + If true, gracefully handles null, empty and + uneven strings as well as stripping unconvertable characters + The converted byte array + + + + Returns true is c is a hexadecimal digit (A-F, a-f, 0-9) + + Character to test + true if hex digit, false if not + + + + Converts 1 or 2 character string into equivalant byte value + + 1 or 2 character string + byte + + + + Convert a float value to a byte given a minimum and maximum range + + Value to convert to a byte + Minimum value range + Maximum value range + A single byte representing the original float value + + + + Convert a byte to a float value given a minimum and maximum range + + Byte array to get the byte from + Position in the byte array the desired byte is at + Minimum value range + Maximum value range + A float value inclusively between lower and upper + + + + Convert a byte to a float value given a minimum and maximum range + + Byte to convert to a float value + Minimum value range + Maximum value range + A float value inclusively between lower and upper + + + + Attempts to parse a floating point value from a string, using an + EN-US number format + + String to parse + Resulting floating point number + True if the parse was successful, otherwise false + + + + Attempts to parse a floating point value from a string, using an + EN-US number format + + String to parse + Resulting floating point number + True if the parse was successful, otherwise false + + + + Tries to parse an unsigned 32-bit integer from a hexadecimal string + + String to parse + Resulting integer + True if the parse was successful, otherwise false - - Uncompressed TGA texture + + + Returns text specified in EnumInfo attribute of the enumerator + To add the text use [EnumInfo(Text = "Some nice text here")] before declaration + of enum values + + Enum value + Text representation of the enum - - Collection of textures and shape parameters that can - be worn + + + Takes an AssetType and returns the string representation + + The source + The string version of the AssetType - - Trash folder + + + Translate a string name of an AssetType into the proper Type + + A string containing the AssetType name + The AssetType which matches the string name, or AssetType.Unknown if no match was found - - Snapshot folder + + + Convert an InventoryType to a string + + The to convert + A string representation of the source - - Lost and found folder + + + Convert a string into a valid InventoryType + + A string representation of the InventoryType to convert + A InventoryType object which matched the type - - Uncompressed sound + + + Convert a SaleType to a string + + The to convert + A string representation of the source - - Uncompressed TGA non-square image, not to be used as a - texture + + + Convert a string into a valid SaleType + + A string representation of the SaleType to convert + A SaleType object which matched the type - - Compressed JPEG non-square image, not to be used as a - texture + + + Converts a string used in LLSD to AttachmentPoint type + + String representation of AttachmentPoint to convert + AttachmentPoint enum - - Animation + + + Copy a byte array + + Byte array to copy + A copy of the given byte array - - Sequence of animations, sounds, chat, and pauses + + + Packs to 32-bit unsigned integers in to a 64-bit unsigned integer + + The left-hand (or X) value + The right-hand (or Y) value + A 64-bit integer containing the two 32-bit input values - - Simstate file + + + Unpacks two 32-bit unsigned integers from a 64-bit unsigned integer + + The 64-bit input integer + The left-hand (or X) output value + The right-hand (or Y) output value - - Contains landmarks for favorites + + + Convert an IP address object to an unsigned 32-bit integer + + IP address to convert + 32-bit unsigned integer holding the IP address bits - - Asset is a link to another inventory item + + + Gets a unix timestamp for the current time + + An unsigned integer representing a unix timestamp for now - - Asset is a link to another inventory folder + + + Convert a UNIX timestamp to a native DateTime object + + An unsigned integer representing a UNIX + timestamp + A DateTime object containing the same time specified in + the given timestamp - - Beginning of the range reserved for ensembles + + + Convert a UNIX timestamp to a native DateTime object + + A signed integer representing a UNIX + timestamp + A DateTime object containing the same time specified in + the given timestamp - - End of the range reserved for ensembles + + + Convert a native DateTime object to a UNIX timestamp + + A DateTime object you want to convert to a + timestamp + An unsigned integer representing a UNIX timestamp - - Folder containing inventory links to wearables and attachments - that are part of the current outfit + + + Swap two values + + Type of the values to swap + First value + Second value - - Folder containing inventory items or links to - inventory items of wearables and attachments - together make a full outfit + + + Try to parse an enumeration value from a string + + Enumeration type + String value to parse + Enumeration value on success + True if the parsing succeeded, otherwise false - - Root folder for the folders of type OutfitFolder + + + Swaps the high and low words in a byte. Converts aaaabbbb to bbbbaaaa + + Byte to swap the words in + Byte value with the words swapped - - + + + Attempts to convert a string representation of a hostname or IP + address to a + Hostname to convert to an IPAddress + Converted IP address object, or null if the conversion + failed - + - Inventory Item Types, eg Script, Notecard, Folder, etc + A two-dimensional vector with floating-point values - - Unknown + + X value - - Texture + + Y value - - Sound + + A vector with a value of 0,0 - - Calling Card + + A vector with a value of 1,1 - - Landmark + + A vector with a value of 1,0 - - Notecard + + A vector with a value of 0,1 - - + + + Test if this vector is equal to another vector, within a given + tolerance range + + Vector to test against + The acceptable magnitude of difference + between the two vectors + True if the magnitude of difference between the two vectors + is less than the given tolerance, otherwise false - - Folder + + + Test if this vector is composed of all finite numbers + - - + + + IComparable.CompareTo implementation + - - an LSL Script + + + Builds a vector from a byte array + + Byte array containing two four-byte floats + Beginning position in the byte array - - + + + Returns the raw bytes for this vector + + An eight-byte array containing X and Y - - + + + Writes the raw bytes for this vector to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 8 bytes before the end of the array - - + + + Parse a vector from a string + + A string representation of a 2D vector, enclosed + in arrow brackets and separated by commas - - + + + Interpolates between two vectors using a cubic equation + - - + + + Get a formatted string representation of the vector + + A string representation of the vector + + + + Get a string representation of the vector elements with up to three + decimal digits and separated by spaces only + + Raw string representation of the vector - + - Item Sale Status + A three-dimensional vector with floating-point values - - Not for sale + + + Constructor, builds a vector from a byte array + + Byte array containing three four-byte floats + Beginning position in the byte array - - The original is for sale + + X value - - Copies are for sale + + Y value - - The contents of the object are for sale + + Z value - - - Types of wearable assets - + + A vector with a value of 0,0,0 - - Body shape + + A vector with a value of 1,1,1 - - Skin textures and attributes + + A unit vector facing forward (X axis), value 1,0,0 - - Hair + + A unit vector facing left (Y axis), value 0,1,0 - - Eyes + + A unit vector facing up (Z axis), value 0,0,1 - - Shirt + + + Test if this vector is equal to another vector, within a given + tolerance range + + Vector to test against + The acceptable magnitude of difference + between the two vectors + True if the magnitude of difference between the two vectors + is less than the given tolerance, otherwise false - - Pants + + + IComparable.CompareTo implementation + - - Shoes + + + Test if this vector is composed of all finite numbers + - - Socks + + + Builds a vector from a byte array + + Byte array containing a 12 byte vector + Beginning position in the byte array - - Jacket + + + Returns the raw bytes for this vector + + A 12 byte array containing X, Y, and Z - - Gloves + + + Writes the raw bytes for this vector to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 12 bytes before the end of the array - - Undershirt + + + Parse a vector from a string + + A string representation of a 3D vector, enclosed + in arrow brackets and separated by commas - - Underpants + + + Calculate the rotation between two vectors + + Normalized directional vector (such as 1,0,0 for forward facing) + Normalized target vector - - Skirt + + + Interpolates between two vectors using a cubic equation + - - Alpha mask to hide parts of the avatar + + + Get a formatted string representation of the vector + + A string representation of the vector - - Tattoo + + + Get a string representation of the vector elements with up to three + decimal digits and separated by spaces only + + Raw string representation of the vector - - Invalid wearable asset + + + Cross product between two vectors + A three-dimensional vector with doubleing-point values + + + Constructor, builds a vector from a byte array + + Byte array containing three eight-byte doubles + Beginning position in the byte array + X value @@ -1834,12 +2500,20 @@ Z value - - - Constructor, builds a vector from a byte array - - Byte array containing three eight-byte doubles - Beginning position in the byte array + + A vector with a value of 0,0,0 + + + A vector with a value of 1,1,1 + + + A unit vector facing forward (X axis), value of 1,0,0 + + + A unit vector facing left (Y axis), value of 0,1,0 + + + A unit vector facing up (Z axis), value of 0,0,1 @@ -1887,7 +2561,7 @@ Parse a vector from a string - A string representation of a 3D vector, enclosed + A string representation of a 3D vector, enclosed in arrow brackets and separated by commas @@ -1913,45 +2587,91 @@ Cross product between two vectors - - A vector with a value of 0,0,0 + + + Constructor, builds a vector from a byte array + + Byte array containing four four-byte floats + Beginning position in the byte array - - A vector with a value of 1,1,1 + + X value - - A unit vector facing forward (X axis), value of 1,0,0 + + Y value - - A unit vector facing left (Y axis), value of 0,1,0 + + Z value - - A unit vector facing up (Z axis), value of 0,0,1 + + W value - + + A vector with a value of 0,0,0,0 + + + A vector with a value of 1,1,1,1 + + + A vector with a value of 1,0,0,0 + + + A vector with a value of 0,1,0,0 + + + A vector with a value of 0,0,1,0 + + + A vector with a value of 0,0,0,1 + + - Determines the appropriate events to set, leaves the locks, and sets the events. + Test if this vector is equal to another vector, within a given + tolerance range + Vector to test against + The acceptable magnitude of difference + between the two vectors + True if the magnitude of difference between the two vectors + is less than the given tolerance, otherwise false - + - A routine for lazily creating a event outside the lock (so if errors - happen they are outside the lock and that we don't do much work - while holding a spin lock). If all goes well, reenter the lock and - set 'waitEvent' + IComparable.CompareTo implementation - + - Waits on 'waitEvent' with a timeout of 'millisceondsTimeout. - Before the wait 'numWaiters' is incremented and is restored before leaving this routine. + Test if this vector is composed of all finite numbers - + - Copy constructor + Builds a vector from a byte array - Circular queue to copy + Byte array containing a 16 byte vector + Beginning position in the byte array + + + + Returns the raw bytes for this vector + + A 16 byte array containing X, Y, Z, and W + + + + Writes the raw bytes for this vector to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 16 bytes before the end of the array + + + + Get a string representation of the vector elements with up to three + decimal digits and separated by spaces only + + Raw string representation of the vector diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index 01dc3d8..b989bad 100644 Binary files a/bin/OpenMetaverseTypes.dll and b/bin/OpenMetaverseTypes.dll differ -- cgit v1.1 From 90f9b7b7c41927fed070cbe7a8f6cd2a258c2365 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 4 Oct 2010 00:37:18 +0200 Subject: Fix line endings --- .../LindenUDP/UnackedPacketCollection.cs | 368 ++++++++++----------- 1 file changed, 184 insertions(+), 184 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs index 043e7d3..4cb4aee 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs @@ -1,184 +1,184 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSimulator Project nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -using System; -using System.Collections.Generic; -using System.Net; -using OpenMetaverse; - -namespace OpenSim.Region.ClientStack.LindenUDP -{ - /// - /// Special collection that is optimized for tracking unacknowledged packets - /// - public sealed class UnackedPacketCollection - { - /// - /// Holds information about a pending acknowledgement - /// - private struct PendingAck - { - /// Sequence number of the packet to remove - public uint SequenceNumber; - /// Environment.TickCount value when the remove was queued. - /// This is used to update round-trip times for packets - public int RemoveTime; - /// Whether or not this acknowledgement was attached to a - /// resent packet. If so, round-trip time will not be calculated - public bool FromResend; - - public PendingAck(uint sequenceNumber, int currentTime, bool fromResend) - { - SequenceNumber = sequenceNumber; - RemoveTime = currentTime; - FromResend = fromResend; - } - } - - /// Holds the actual unacked packet data, sorted by sequence number - private Dictionary m_packets = new Dictionary(); - /// Holds packets that need to be added to the unacknowledged list - private LocklessQueue m_pendingAdds = new LocklessQueue(); - /// Holds information about pending acknowledgements - private LocklessQueue m_pendingRemoves = new LocklessQueue(); - - /// - /// Add an unacked packet to the collection - /// - /// Packet that is awaiting acknowledgement - /// True if the packet was successfully added, false if the - /// packet already existed in the collection - /// This does not immediately add the ACK to the collection, - /// it only queues it so it can be added in a thread-safe way later - public void Add(OutgoingPacket packet) - { - m_pendingAdds.Enqueue(packet); - } - - /// - /// Marks a packet as acknowledged - /// - /// Sequence number of the packet to - /// acknowledge - /// Current value of Environment.TickCount - /// This does not immediately acknowledge the packet, it only - /// queues the ack so it can be handled in a thread-safe way later - public void Remove(uint sequenceNumber, int currentTime, bool fromResend) - { - m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); - } - - /// - /// Returns a list of all of the packets with a TickCount older than - /// the specified timeout - /// - /// Number of ticks (milliseconds) before a - /// packet is considered expired - /// A list of all expired packets according to the given - /// expiration timeout - /// This function is not thread safe, and cannot be called - /// multiple times concurrently - public List GetExpiredPackets(int timeoutMS) - { - ProcessQueues(); - - List expiredPackets = null; - - if (m_packets.Count > 0) - { - int now = Environment.TickCount & Int32.MaxValue; - - foreach (OutgoingPacket packet in m_packets.Values) - { - // TickCount of zero means a packet is in the resend queue - // but hasn't actually been sent over the wire yet - if (packet.TickCount == 0) - continue; - - if (now - packet.TickCount >= timeoutMS) - { - if (expiredPackets == null) - expiredPackets = new List(); - - // The TickCount will be set to the current time when the packet - // is actually sent out again - packet.TickCount = 0; - - expiredPackets.Add(packet); - } - } - } - - return expiredPackets; - } - - private void ProcessQueues() - { - // Process all the pending adds - - OutgoingPacket pendingAdd; - if (m_pendingAdds != null) - { - while (m_pendingAdds.TryDequeue(out pendingAdd)) - { - if (pendingAdd != null && m_packets != null) - { - m_packets[pendingAdd.SequenceNumber] = pendingAdd; - } - } - } - - // Process all the pending removes, including updating statistics and round-trip times - PendingAck pendingRemove; - OutgoingPacket ackedPacket; - if (m_pendingRemoves != null) - { - while (m_pendingRemoves.TryDequeue(out pendingRemove)) - { - if (m_pendingRemoves != null && m_packets != null) - { - if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) - { - m_packets.Remove(pendingRemove.SequenceNumber); - - // Update stats - System.Threading.Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); - - if (!pendingRemove.FromResend) - { - // Calculate the round-trip time for this packet and its ACK - int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; - if (rtt > 0) - ackedPacket.Client.UpdateRoundTrip(rtt); - } - } - } - } - } - } - } -} +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Net; +using OpenMetaverse; + +namespace OpenSim.Region.ClientStack.LindenUDP +{ + /// + /// Special collection that is optimized for tracking unacknowledged packets + /// + public sealed class UnackedPacketCollection + { + /// + /// Holds information about a pending acknowledgement + /// + private struct PendingAck + { + /// Sequence number of the packet to remove + public uint SequenceNumber; + /// Environment.TickCount value when the remove was queued. + /// This is used to update round-trip times for packets + public int RemoveTime; + /// Whether or not this acknowledgement was attached to a + /// resent packet. If so, round-trip time will not be calculated + public bool FromResend; + + public PendingAck(uint sequenceNumber, int currentTime, bool fromResend) + { + SequenceNumber = sequenceNumber; + RemoveTime = currentTime; + FromResend = fromResend; + } + } + + /// Holds the actual unacked packet data, sorted by sequence number + private Dictionary m_packets = new Dictionary(); + /// Holds packets that need to be added to the unacknowledged list + private LocklessQueue m_pendingAdds = new LocklessQueue(); + /// Holds information about pending acknowledgements + private LocklessQueue m_pendingRemoves = new LocklessQueue(); + + /// + /// Add an unacked packet to the collection + /// + /// Packet that is awaiting acknowledgement + /// True if the packet was successfully added, false if the + /// packet already existed in the collection + /// This does not immediately add the ACK to the collection, + /// it only queues it so it can be added in a thread-safe way later + public void Add(OutgoingPacket packet) + { + m_pendingAdds.Enqueue(packet); + } + + /// + /// Marks a packet as acknowledged + /// + /// Sequence number of the packet to + /// acknowledge + /// Current value of Environment.TickCount + /// This does not immediately acknowledge the packet, it only + /// queues the ack so it can be handled in a thread-safe way later + public void Remove(uint sequenceNumber, int currentTime, bool fromResend) + { + m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend)); + } + + /// + /// Returns a list of all of the packets with a TickCount older than + /// the specified timeout + /// + /// Number of ticks (milliseconds) before a + /// packet is considered expired + /// A list of all expired packets according to the given + /// expiration timeout + /// This function is not thread safe, and cannot be called + /// multiple times concurrently + public List GetExpiredPackets(int timeoutMS) + { + ProcessQueues(); + + List expiredPackets = null; + + if (m_packets.Count > 0) + { + int now = Environment.TickCount & Int32.MaxValue; + + foreach (OutgoingPacket packet in m_packets.Values) + { + // TickCount of zero means a packet is in the resend queue + // but hasn't actually been sent over the wire yet + if (packet.TickCount == 0) + continue; + + if (now - packet.TickCount >= timeoutMS) + { + if (expiredPackets == null) + expiredPackets = new List(); + + // The TickCount will be set to the current time when the packet + // is actually sent out again + packet.TickCount = 0; + + expiredPackets.Add(packet); + } + } + } + + return expiredPackets; + } + + private void ProcessQueues() + { + // Process all the pending adds + + OutgoingPacket pendingAdd; + if (m_pendingAdds != null) + { + while (m_pendingAdds.TryDequeue(out pendingAdd)) + { + if (pendingAdd != null && m_packets != null) + { + m_packets[pendingAdd.SequenceNumber] = pendingAdd; + } + } + } + + // Process all the pending removes, including updating statistics and round-trip times + PendingAck pendingRemove; + OutgoingPacket ackedPacket; + if (m_pendingRemoves != null) + { + while (m_pendingRemoves.TryDequeue(out pendingRemove)) + { + if (m_pendingRemoves != null && m_packets != null) + { + if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket)) + { + m_packets.Remove(pendingRemove.SequenceNumber); + + // Update stats + System.Threading.Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength); + + if (!pendingRemove.FromResend) + { + // Calculate the round-trip time for this packet and its ACK + int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount; + if (rtt > 0) + ackedPacket.Client.UpdateRoundTrip(rtt); + } + } + } + } + } + } + } +} -- cgit v1.1 From 6ba7ee6b2e25f52d6f63c08e22f90a3990fc28e1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 4 Oct 2010 00:44:27 +0100 Subject: Update libOMV --- bin/OpenMetaverse.StructuredData.XML | 398 +- bin/OpenMetaverse.StructuredData.dll | Bin 95232 -> 102400 bytes bin/OpenMetaverse.XML | 36118 ++++++++++++++++----------------- bin/OpenMetaverse.dll | Bin 1768960 -> 1712128 bytes bin/OpenMetaverse.dll.config | 14 +- bin/OpenMetaverseTypes.XML | 3191 ++- bin/OpenMetaverseTypes.dll | Bin 105984 -> 114688 bytes 7 files changed, 19424 insertions(+), 20297 deletions(-) diff --git a/bin/OpenMetaverse.StructuredData.XML b/bin/OpenMetaverse.StructuredData.XML index 927e960..a8e314f 100644 --- a/bin/OpenMetaverse.StructuredData.XML +++ b/bin/OpenMetaverse.StructuredData.XML @@ -1,363 +1,333 @@ - /home/root/libopenmetaverse/bin/OpenMetaverse.StructuredData + OpenMetaverse.StructuredData - + + - - + - - + - + + + + - + + + + - + + + + - + + + + - + + + - + + + + + - + + + + + - + + + + + - + + + + - + + + + - + + + + - + - Uses reflection to create an SDMap from all of the SD - serializable types in an object + - Class or struct containing serializable types - An SDMap holding the serialized values from the - container object + + - + - Uses reflection to deserialize member variables in an object from - an SDMap + - Reference to an object to fill with deserialized - values - Serialized values to put in the target - object + + - + + + + - + + + + - + + + + - + + + + - + + + + + - + + + + - + + + + - + + + + - + + + + - + + + + - - - - - + + + + + - + + - - - - + + + + - + + - - - - + + + - + + - - - - + + + - + + - - - - - - - - - + + - - - - - - - - - + + - - - - - - - - - + + - - - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - + + + + + + + + - - - - - + + - - - - - + + Uses reflection to create an SDMap from all of the SD + serializable types in an object - - - - - - + Class or struct containing serializable types + An SDMap holding the serialized values from the + container object - + + Uses reflection to deserialize member variables in an object from + an SDMap - - - - - - - - + Reference to an object to fill with deserialized + values + Serialized values to put in the target + object - + + - - - - - - - + + - - - - - - - + + - - - - - + + - - - - - + + - - - - - + + - - - - - + + - - - - - + + - - - - - + + - - - - - - - + + - - - - diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index 27ccfbc..45a72ec 100644 Binary files a/bin/OpenMetaverse.StructuredData.dll and b/bin/OpenMetaverse.StructuredData.dll differ diff --git a/bin/OpenMetaverse.XML b/bin/OpenMetaverse.XML index fa1057a..639bc20 100644 --- a/bin/OpenMetaverse.XML +++ b/bin/OpenMetaverse.XML @@ -1,25794 +1,25026 @@ - /home/root/libopenmetaverse/bin/OpenMetaverse + OpenMetaverse - + - Permission request flags, asked when a script wants to control an Avatar + Represents an LSL Text object containing a string of UTF encoded characters - - Placeholder for empty values, shouldn't ever see this + + + Base class for all Asset types + - - Script wants ability to take money from you + + A byte array containing the raw asset data - - Script wants to take camera controls for you + + True if the asset it only stored on the server temporarily - - Script wants to remap avatars controls + + A unique ID - - Script wants to trigger avatar animations - This function is not implemented on the grid + + + Construct a new Asset object + - - Script wants to attach or detach the prim or primset to your avatar + + + Construct a new Asset object + + A unique specific to this asset + A byte array containing the raw asset data - - Script wants permission to release ownership - This function is not implemented on the grid - The concept of "public" objects does not exist anymore. + + + Regenerates the AssetData byte array from the properties + of the derived class. + - - Script wants ability to link/delink with other prims + + + Decodes the AssetData, placing it in appropriate properties of the derived + class. + + True if the asset decoding succeeded, otherwise false - - Script wants permission to change joints - This function is not implemented on the grid + + The assets unique ID - - Script wants permissions to change permissions - This function is not implemented on the grid + + + The "type" of asset, Notecard, Animation, etc + - - Script wants to track avatars camera position and rotation + + A string of characters represting the script contents - - Script wants to control your camera + + Initializes a new AssetScriptText object - + - Special commands used in Instant Messages + Initializes a new AssetScriptText object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - Indicates a regular IM from another agent - - - Simple notification box with an OK button + + + Encode a string containing the scripts contents into byte encoded AssetData + - - You've been invited to join a group. + + + Decode a byte array containing the scripts contents into a string + + true if decoding is successful - - Inventory offer + + Override the base classes AssetType - - Accepted inventory offer + + + + - - Declined inventory offer + + The event subscribers, null of no subscribers - - Group vote + + Raises the AttachedSound Event + A AttachedSoundEventArgs object containing + the data sent from the simulator - - An object is offering its inventory + + Thread sync lock object - - Accept an inventory offer from an object + + The event subscribers, null of no subscribers - - Decline an inventory offer from an object + + Raises the AttachedSoundGainChange Event + A AttachedSoundGainChangeEventArgs object containing + the data sent from the simulator - - Unknown + + Thread sync lock object - - Start a session, or add users to a session + + The event subscribers, null of no subscribers - - Start a session, but don't prune offline users + + Raises the SoundTrigger Event + A SoundTriggerEventArgs object containing + the data sent from the simulator - - Start a session with your group + + Thread sync lock object - - Start a session without a calling card (finder or objects) + + The event subscribers, null of no subscribers - - Send a message to a session + + Raises the PreloadSound Event + A PreloadSoundEventArgs object containing + the data sent from the simulator - - Leave a session + + Thread sync lock object - - Indicates that the IM is from an object + + + Construct a new instance of the SoundManager class, used for playing and receiving + sound assets + + A reference to the current GridClient instance - - Sent an IM to a busy user, this is the auto response + + + Plays a sound in the current region at full volume from avatar position + + UUID of the sound to be played - - Shows the message in the console and chat history + + + Plays a sound in the current region at full volume + + UUID of the sound to be played. + position for the sound to be played at. Normally the avatar. - - Send a teleport lure + + + Plays a sound in the current region + + UUID of the sound to be played. + position for the sound to be played at. Normally the avatar. + volume of the sound, from 0.0 to 1.0 - - Response sent to the agent which inititiated a teleport invitation + + + Plays a sound in the specified sim + + UUID of the sound to be played. + UUID of the sound to be played. + position for the sound to be played at. Normally the avatar. + volume of the sound, from 0.0 to 1.0 - - Response sent to the agent which inititiated a teleport invitation + + + Play a sound asset + + UUID of the sound to be played. + handle id for the sim to be played in. + position for the sound to be played at. Normally the avatar. + volume of the sound, from 0.0 to 1.0 - - Only useful if you have Linden permissions + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - A placeholder type for future expansion, currently not - used + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - IM to tell the user to go to an URL + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - IM for help + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - IM sent automatically on call for help, sends a lure - to each Helper reached + + Raised when the simulator sends us data containing + sound - - Like an IM but won't go to email + + Raised when the simulator sends us data containing + ... - - IM from a group officer to all group members + + Raised when the simulator sends us data containing + ... - - Unknown + + Raised when the simulator sends us data containing + ... - - Unknown + + Provides data for the event + The event occurs when the simulator sends + the sound data which emits from an agents attachment + + The following code example shows the process to subscribe to the event + and a stub to handle the data passed from the simulator + + // Subscribe to the AttachedSound event + Client.Sound.AttachedSound += Sound_AttachedSound; + + // process the data raised in the event here + private void Sound_AttachedSound(object sender, AttachedSoundEventArgs e) + { + // ... Process AttachedSoundEventArgs here ... + } + + - - Accept a group invitation + + + Construct a new instance of the SoundTriggerEventArgs class + + Simulator where the event originated + The sound asset id + The ID of the owner + The ID of the object + The volume level + The - - Decline a group invitation + + Simulator where the event originated - - Unknown + + Get the sound asset id - - An avatar is offering you friendship + + Get the ID of the owner - - An avatar has accepted your friendship offer + + Get the ID of the Object - - An avatar has declined your friendship offer + + Get the volume level - - Indicates that a user has started typing + + Get the - - Indicates that a user has stopped typing + + Provides data for the event + The event occurs when an attached sound + changes its volume level - + - Flag in Instant Messages, whether the IM should be delivered to - offline avatars as well + Construct a new instance of the AttachedSoundGainChangedEventArgs class + Simulator where the event originated + The ID of the Object + The new volume level - - Only deliver to online avatars + + Simulator where the event originated - - If the avatar is offline the message will be held until - they login next, and possibly forwarded to their e-mail account + + Get the ID of the Object - + + Get the volume level + + + Provides data for the event + The event occurs when the simulator forwards + a request made by yourself or another agent to play either an asset sound or a built in sound + + Requests to play sounds where the is not one of the built-in + will require sending a request to download the sound asset before it can be played + + + The following code example uses the , + and + properties to display some information on a sound request on the window. + + // subscribe to the event + Client.Sound.SoundTrigger += Sound_SoundTrigger; + + // play the pre-defined BELL_TING sound + Client.Sound.SendSoundTrigger(Sounds.BELL_TING); + + // handle the response data + private void Sound_SoundTrigger(object sender, SoundTriggerEventArgs e) + { + Console.WriteLine("{0} played the sound {1} at volume {2}", + e.OwnerID, e.SoundID, e.Gain); + } + + + + - Conversion type to denote Chat Packet types in an easier-to-understand format + Construct a new instance of the SoundTriggerEventArgs class + Simulator where the event originated + The sound asset id + The ID of the owner + The ID of the object + The ID of the objects parent + The volume level + The regionhandle + The source position - - Whisper (5m radius) + + Simulator where the event originated - - Normal chat (10/20m radius), what the official viewer typically sends + + Get the sound asset id - - Shouting! (100m radius) + + Get the ID of the owner - - Event message when an Avatar has begun to type + + Get the ID of the Object - - Event message when an Avatar has stopped typing + + Get the ID of the objects parent - - Send the message to the debug channel + + Get the volume level - - Event message when an object uses llOwnerSay + + Get the regionhandle - - Special value to support llRegionSay, never sent to the client + + Get the source position - + + Provides data for the event + The event occurs when the simulator sends + the appearance data for an avatar + + The following code example uses the and + properties to display the selected shape of an avatar on the window. + + // subscribe to the event + Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; + + // handle the data when the event is raised + void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) + { + Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") + } + + + + - Identifies the source of a chat message + Construct a new instance of the PreloadSoundEventArgs class + Simulator where the event originated + The sound asset id + The ID of the owner + The ID of the object - - Chat from the grid or simulator + + Simulator where the event originated - - Chat from another avatar + + Get the sound asset id - - Chat from an object + + Get the ID of the owner - - - + + Get the ID of the Object - - - + + Sort by name - + + Sort by date + + + Sort folders by name, regardless of whether items are + sorted by name or date + + + Place system folders at the top + + + Possible destinations for DeRezObject request - + + + + + Copy from in-world to agent inventory + + + Derez to TaskInventory + + + + + + Take Object + + + + + + Delete Object + + + Put an avatar attachment into agent inventory + + + + + + Return an object back to the owner's inventory + + + Return a deeded object back to the last owner's inventory + + + Upper half of the Flags field for inventory items - + + Indicates that the NextOwner permission will be set to the + most restrictive set of permissions found in the object set + (including linkset items and object inventory items) on next rez + + + Indicates that the object sale information has been + changed + + + If set, and a slam bit is set, indicates BaseMask will be overwritten on Rez + + + If set, and a slam bit is set, indicates OwnerMask will be overwritten on Rez + + + If set, and a slam bit is set, indicates GroupMask will be overwritten on Rez + + + If set, and a slam bit is set, indicates EveryoneMask will be overwritten on Rez + + + If set, and a slam bit is set, indicates NextOwnerMask will be overwritten on Rez + + + Indicates whether this object is composed of multiple + items or not + + + Indicates that the asset is only referenced by this + inventory item. If this item is deleted or updated to reference a + new assetID, the asset can be deleted + + - Effect type used in ViewerEffect packets + Base Class for Inventory Items - + + of item/folder + + + of parent folder + + + Name of item/folder + + + Item/Folder Owners + + + Constructor, takes an itemID as a parameter + The of the item - + + + - + + + - + + Generates a number corresponding to the value of the object to support the use of a hash table, + suitable for use in hashing algorithms and data structures such as a hash table + A Hashcode of all the combined InventoryBase fields - + + Determine whether the specified object is equal to the current object + InventoryBase object to compare against + true if objects are the same - + + Determine whether the specified object is equal to the current object + InventoryBase object to compare against + true if objects are the same - + + An Item in Inventory - - Project a beam from a source to a destination, such as - the one used when editing an object + + The of this item - - - + + The combined of this item - - - + + The type of item from - - - + + The type of item from the enum - - Create a swirl of particles around an object + + The of the creator of this item - - - + + A Description of this item - - - + + The s this item is set to or owned by - - Cause an avatar to look at an object + + If true, item is owned by a group - - Cause an avatar to point at an object + + The price this item can be purchased for - - - The action an avatar is doing when looking at something, used in - ViewerEffect packets for the LookAt effect - + + The type of sale from the enum - - - + + Combined flags from - - - + + Time and date this inventory item was created, stored as + UTC (Coordinated Universal Time) - + + Used to update the AssetID in requests sent to the server + + + The of the previous owner of the item + + + Construct a new InventoryItem object + The of the item - + + Construct a new InventoryItem object of a specific Type + The type of item from + of the item - + + Indicates inventory item is a link + True if inventory item is a link to another inventory item - + + + - - Deprecated - - + + + - + + Generates a number corresponding to the value of the object to support the use of a hash table. + Suitable for use in hashing algorithms and data structures such as a hash table + A Hashcode of all the combined InventoryItem fields - + + Compares an object + The object to compare + true if comparison object matches - + + Determine whether the specified object is equal to the current object + The object to compare against + true if objects are the same - + - The action an avatar is doing when pointing at something, used in - ViewerEffect packets for the PointAt effect + Determine whether the specified object is equal to the current object + The object to compare against + true if objects are the same - + + InventoryTexture Class representing a graphical image + - + + Construct an InventoryTexture object + A which becomes the + objects AssetUUID - + + Construct an InventoryTexture object from a serialization stream - + + InventorySound Class representing a playable sound - + - Money transaction types + Construct an InventorySound object + A which becomes the + objects AssetUUID - + + Construct an InventorySound object from a serialization stream - + + InventoryCallingCard Class, contains information on another avatar - + + Construct an InventoryCallingCard object + A which becomes the + objects AssetUUID - + + Construct an InventoryCallingCard object from a serialization stream - + + InventoryLandmark Class, contains details on a specific location - + + Construct an InventoryLandmark object + A which becomes the + objects AssetUUID - + + Construct an InventoryLandmark object from a serialization stream - + + Landmarks use the InventoryItemFlags struct and will have a flag of 1 set if they have been visited - + + InventoryObject Class contains details on a primitive or coalesced set of primitives - + + Construct an InventoryObject object + A which becomes the + objects AssetUUID - + + Construct an InventoryObject object from a serialization stream - + + Gets or sets the upper byte of the Flags value - + + Gets or sets the object attachment point, the lower byte of the Flags value - + + InventoryNotecard Class, contains details on an encoded text document - + + Construct an InventoryNotecard object + A which becomes the + objects AssetUUID - + + Construct an InventoryNotecard object from a serialization stream - + + InventoryCategory Class + TODO: Is this even used for anything? - + + Construct an InventoryCategory object + A which becomes the + objects AssetUUID - + + Construct an InventoryCategory object from a serialization stream - + + InventoryLSL Class, represents a Linden Scripting Language object - + + Construct an InventoryLSL object + A which becomes the + objects AssetUUID - + + Construct an InventoryLSL object from a serialization stream - + + InventorySnapshot Class, an image taken with the viewer - + + Construct an InventorySnapshot object + A which becomes the + objects AssetUUID - + + Construct an InventorySnapshot object from a serialization stream - + + InventoryAttachment Class, contains details on an attachable object - + + Construct an InventoryAttachment object + A which becomes the + objects AssetUUID - + + Construct an InventoryAttachment object from a serialization stream - + + Get the last AttachmentPoint this object was attached to - + + InventoryWearable Class, details on a clothing item or body part - + + Construct an InventoryWearable object + A which becomes the + objects AssetUUID - + + Construct an InventoryWearable object from a serialization stream - + + The , Skin, Shape, Skirt, Etc - + + InventoryAnimation Class, A bvh encoded object which animates an avatar - + + Construct an InventoryAnimation object + A which becomes the + objects AssetUUID - + + Construct an InventoryAnimation object from a serialization stream - + + InventoryGesture Class, details on a series of animations, sounds, and actions - + + Construct an InventoryGesture object + A which becomes the + objects AssetUUID - + + Construct an InventoryGesture object from a serialization stream - + + A folder contains s and has certain attributes specific + to itself - + + The Preferred for a folder. + + + The Version of this folder + + + Number of child items this folder contains. + + + Constructor + UUID of the folder - + + + - + + Get Serilization data for this InventoryFolder object - + + Construct an InventoryFolder object from a serialization stream - + + + - + + + + - + + + + - + + + + - + + Tools for dealing with agents inventory - + + Used for converting shadow_id to asset_id + + + The event subscribers, null of no subscribers + + + Raises the ItemReceived Event + A ItemReceivedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the FolderUpdated Event + A FolderUpdatedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the InventoryObjectOffered Event + A InventoryObjectOfferedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the TaskItemReceived Event + A TaskItemReceivedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the FindObjectByPath Event + A FindObjectByPathEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the TaskInventoryReply Event + A TaskInventoryReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the SaveAssetToInventory Event + A SaveAssetToInventoryEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the ScriptRunningReply Event + A ScriptRunningReplyEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + Partial mapping of AssetTypes to folder names + + + Default constructor + Reference to the GridClient object - + + Fetch an inventory item from the dataserver + The items + The item Owners + a integer representing the number of milliseconds to wait for results + An object on success, or null if no item was found + Items will also be sent to the event - + + Request A single inventory item + The items + The item Owners + - + + Request inventory items + Inventory items to request + Owners of the inventory items + - + + Get contents of a folder + The of the folder to search + The of the folders owner + true to retrieve folders + true to retrieve items + sort order to return results in + a integer representing the number of milliseconds to wait for results + A list of inventory items matching search criteria within folder + + InventoryFolder.DescendentCount will only be accurate if both folders and items are + requested - + + Request the contents of an inventory folder + The folder to search + The folder owners + true to return s contained in folder + true to return s containd in folder + the sort order to return items in + - + + Returns the UUID of the folder (category) that defaults to + containing 'type'. The folder is not necessarily only for that + type + This will return the root folder if one does not exist + + The UUID of the desired folder if found, the UUID of the RootFolder + if not found, or UUID.Zero on failure - + + Find an object in inventory using a specific path to search + The folder to begin the search in + The object owners + A string path to search + milliseconds to wait for a reply + Found items or if + timeout occurs or item is not found - + + Find inventory items by path + The folder to begin the search in + The object owners + A string path to search, folders/objects separated by a '/' + Results are sent to the event - + + Search inventory Store object for an item or folder + The folder to begin the search in + An array which creates a path to search + Number of levels below baseFolder to conduct searches + if True, will stop searching after first match is found + A list of inventory items found - + + Move an inventory item or folder to a new location + The item or folder to move + The to move item or folder to - + + Move an inventory item or folder to a new location and change its name + The item or folder to move + The to move item or folder to + The name to change the item or folder to - + + Move and rename a folder + The source folders + The destination folders + The name to change the folder to - + + Update folder properties + of the folder to update + Sets folder's parent to + Folder name + Folder type - + + Move a folder + The source folders + The destination folders - + - Flags sent when a script takes or releases a control + Move multiple folders, the keys in the Dictionary parameter, + to a new parents, the value of that folder's key. - NOTE: (need to verify) These might be a subset of the ControlFlags enum in Movement, - - - No Flags set - - - Forward (W or up Arrow) - - - Back (S or down arrow) - - - Move left (shift+A or left arrow) - - - Move right (shift+D or right arrow) - - - Up (E or PgUp) - - - Down (C or PgDown) - - - Rotate left (A or left arrow) - - - Rotate right (D or right arrow) - - - Left Mouse Button + A Dictionary containing the + of the source as the key, and the + of the destination as the value - - Left Mouse button in MouseLook - - + - Currently only used to hide your group title + Move an inventory item to a new folder + The of the source item to move + The of the destination folder - - No flags set - - - Hide your group title - - + - Action state of the avatar, which can currently be typing and - editing + Move and rename an inventory item + The of the source item to move + The of the destination folder + The name to change the folder to - + + Move multiple inventory items to new locations + A Dictionary containing the + of the source item as the key, and the + of the destination folder as the value - + + Remove descendants of a folder + The of the folder - + + Remove a single item from inventory + The of the inventory item to remove - + - Current teleport status + Remove a folder from inventory + The of the folder to remove - - Unknown status - - - Teleport initialized - - - Teleport in progress - - - Teleport failed - - - Teleport completed - - - Teleport cancelled - - + + Remove multiple items or folders from inventory + A List containing the s of items to remove + A List containing the s of the folders to remove - - No flags set, or teleport failed - - - Set when newbie leaves help island for first time - - + + Empty the Lost and Found folder - - Via Lure - - - Via Landmark - - - Via Location - - - Via Home - - - Via Telehub - - - Via Login - - - Linden Summoned - - - Linden Forced me - - + + Empty the Trash folder - - Agent Teleported Home via Script - - + + + + + + + Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. + + + - + + + + + + + Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. + + + + - + + Creates a new inventory folder + ID of the folder to put this folder in + Name of the folder to create + The UUID of the newly created folder - - forced to new location for example when avatar is banned or ejected - - - Teleport Finished via a Lure - - - Finished, Sim Changed - - - Finished, Same Sim - - + + Creates a new inventory folder + ID of the folder to put this folder in + Name of the folder to create + Sets this folder as the default folder + for new assets of the specified type. Use AssetType.Unknown + to create a normal folder, otherwise it will likely create a + duplicate of an existing folder type + The UUID of the newly created folder + If you specify a preferred type of AsseType.Folder + it will create a new root folder which may likely cause all sorts + of strange problems - + + Create an inventory item and upload asset data + Asset data + Inventory item name + Inventory item description + Asset type + Inventory type + Put newly created inventory in this folder + Delegate that will receive feedback on success or failure - + + Create an inventory item and upload asset data + Asset data + Inventory item name + Inventory item description + Asset type + Inventory type + Put newly created inventory in this folder + Permission of the newly created item + (EveryoneMask, GroupMask, and NextOwnerMask of Permissions struct are supported) + Delegate that will receive feedback on success or failure - + + Creates inventory link to another inventory item or folder + Put newly created link in folder with this UUID + Inventory item or folder + Method to call upon creation of the link - + + Creates inventory link to another inventory item + Put newly created link in folder with this UUID + Original inventory item + Method to call upon creation of the link - + + Creates inventory link to another inventory folder + Put newly created link in folder with this UUID + Original inventory folder + Method to call upon creation of the link - + + Creates inventory link to another inventory item or folder + Put newly created link in folder with this UUID + Original item's UUID + Name + Description + Asset Type + Inventory Type + Transaction UUID + Method to call upon creation of the link - + + + + + + - + + + + + + + - + - Instant Message + + + + + + - - Key of sender - - - Name of sender - - - Key of destination avatar - - - ID of originating estate - - - Key of originating region - - - Coordinates in originating region - - - Instant message type - - - Group IM session toggle - - - Key of IM session, for Group Messages, the groups UUID - - - Timestamp of the instant message - - - Instant message text - - - Whether this message is held for offline avatars - - - Context specific packed data - - - Print the struct data as a string - A string containing the field name, and field value - - + - Manager class for our own avatar + Request a copy of an asset embedded within a notecard + Usually UUID.Zero for copying an asset from a notecard + UUID of the notecard to request an asset from + Target folder for asset to go to in your inventory + UUID of the embedded asset + callback to run when item is copied to inventory - + - Constructor, setup callbacks for packets related to our avatar + - A reference to the Class + - + - Agent movement and camera control - Agent movement is controlled by setting specific - After the control flags are set, An AgentUpdate is required to update the simulator of the specified flags - This is most easily accomplished by setting one or more of the AgentMovement properties - Movement of an avatar is always based on a compass direction, for example AtPos will move the - agent from West to East or forward on the X Axis, AtNeg will of course move agent from - East to West or backward on the X Axis, LeftPos will be South to North or forward on the Y Axis - The Z axis is Up, finer grained control of movements can be done using the Nudge properties + + - - Default constructor - - + - Camera controls for the agent, mostly a thin wrapper around - CoordinateFrame. This class is only responsible for state - tracking and math, it does not send any packets + + + - + - Default constructor + + + + - + + Save changes to notecard embedded in object contents + Encoded notecard asset data + Notecard UUID + Object's UUID + Called upon finish of the upload with status information - - The camera is a local frame of reference inside of - the larger grid space. This is where the math happens - - + + Upload new gesture asset for an inventory gesture item + Encoded gesture asset + Gesture inventory UUID + Callback whick will be called when upload is complete - + + Update an existing script in an agents Inventory + A byte[] array containing the encoded scripts contents + the itemID of the script + if true, sets the script content to run on the mono interpreter + - + + Update an existing script in an task Inventory + A byte[] array containing the encoded scripts contents + the itemID of the script + UUID of the prim containting the script + if true, sets the script content to run on the mono interpreter + if true, sets the script to running + - + + Rez an object from inventory + Simulator to place object in + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details - - Agent camera controls - - - Currently only used for hiding your group title - - - Action state of the avatar, which can currently be - typing and editing - - + + Rez an object from inventory + Simulator to place object in + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details + UUID of group to own the object - + + Rez an object from inventory - - + Simulator to place object in + Rotation of the object when rezzed + Vector of where to place object + InventoryItem object containing item details + UUID of group to own the object + User defined queryID to correlate replies + If set to true, the CreateSelected flag + will be set on the rezzed object + + + DeRez an object from the simulator to the agents Objects folder in the agents Inventory + The simulator Local ID of the object + If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed - + + DeRez an object from the simulator and return to inventory + The simulator Local ID of the object + The type of destination from the enum + The destination inventory folders -or- + if DeRezzing object to a tasks Inventory, the Tasks + The transaction ID for this request which + can be used to correlate this request with other packets + If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed - + + Rez an item from inventory to its previous simulator location + + + + - + + Give an inventory item to another avatar + The of the item to give + The name of the item + The type of the item from the enum + The of the recipient + true to generate a beameffect during transfer - + + Give an inventory Folder with contents to another avatar + The of the Folder to give + The name of the folder + The type of the item from the enum + The of the recipient + true to generate a beameffect during transfer - + + Copy or move an from agent inventory to a task (primitive) inventory + The target object + The item to copy or move from inventory + + For items with copy permissions a copy of the item is placed in the tasks inventory, + for no-copy items the object is moved to the tasks inventory - + + Retrieve a listing of the items contained in a task (Primitive) + The tasks + The tasks simulator local ID + milliseconds to wait for reply from simulator + A list containing the inventory items inside the task or null + if a timeout occurs + This request blocks until the response from the simulator arrives + or timeoutMS is exceeded - - Timer for sending AgentUpdate packets - - - Move agent positive along the X axis + + + Request the contents of a tasks (primitives) inventory from the + current simulator + + The LocalID of the object + - - Move agent negative along the X axis + + + Request the contents of a tasks (primitives) inventory + + The simulator Local ID of the object + A reference to the simulator object that contains the object + - - Move agent positive along the Y axis + + + Move an item from a tasks (Primitive) inventory to the specified folder in the avatars inventory + + LocalID of the object in the simulator + UUID of the task item to move + The ID of the destination folder in this agents inventory + Simulator Object + Raises the event - - Move agent negative along the Y axis + + + Remove an item from an objects (Prim) Inventory + + LocalID of the object in the simulator + UUID of the task item to remove + Simulator Object + You can confirm the removal by comparing the tasks inventory serial before and after the + request with the request combined with + the event - - Move agent positive along the Z axis + + + Copy an InventoryScript item from the Agents Inventory into a primitives task inventory + + An unsigned integer representing a primitive being simulated + An which represents a script object from the agents inventory + true to set the scripts running state to enabled + A Unique Transaction ID + + The following example shows the basic steps necessary to copy a script from the agents inventory into a tasks inventory + and assumes the script exists in the agents inventory. + + uint primID = 95899503; // Fake prim ID + UUID scriptID = UUID.Parse("92a7fe8a-e949-dd39-a8d8-1681d8673232"); // Fake Script UUID in Inventory + + Client.Inventory.FolderContents(Client.Inventory.FindFolderForType(AssetType.LSLText), Client.Self.AgentID, + false, true, InventorySortOrder.ByName, 10000); + + Client.Inventory.RezScript(primID, (InventoryItem)Client.Inventory.Store[scriptID]); + + - - Move agent negative along the Z axis + + + Request the running status of a script contained in a task (primitive) inventory + + The ID of the primitive containing the script + The ID of the script + The event can be used to obtain the results of the + request + - + + Send a request to set the running state of a script contained in a task (primitive) inventory + The ID of the primitive containing the script + The ID of the script + true to set the script running, false to stop a running script + To verify the change you can use the method combined + with the event - + + Create a CRC from an InventoryItem + The source InventoryItem + A uint representing the source InventoryItem as a CRC - + + Reverses a cheesy XORing with a fixed UUID to convert a shadow_id to an asset_id + Obfuscated shadow_id value + Deobfuscated asset_id value - + + Does a cheesy XORing with a fixed UUID to convert an asset_id to a shadow_id + asset_id value to obfuscate + Obfuscated shadow_id value - + + Wrapper for creating a new object + The type of item from the enum + The of the newly created object + An object with the type and id passed - + + Parse the results of a RequestTaskInventory() response + A string which contains the data from the task reply + A List containing the items contained within the tasks inventory - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + UpdateCreateInventoryItem packets are received when a new inventory item + is created. This may occur when an object that's rezzed in world is + taken into inventory, when an item is created using the CreateInventoryItem + packet, or when an object is purchased + The sender + The EventArgs object containing the packet data - - Causes simulator to make agent fly + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Stop movement + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Finish animation + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Stand up from a sit + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Tells simulator to sit agent on ground + + Raised when the simulator sends us data containing + ... - - Place agent into mouselook mode + + Raised when the simulator sends us data containing + ... - - Nudge agent positive along the X axis + + Raised when the simulator sends us data containing + an inventory object sent by another avatar or primitive - - Nudge agent negative along the X axis + + Raised when the simulator sends us data containing + ... - - Nudge agent positive along the Y axis + + Raised when the simulator sends us data containing + ... - - Nudge agent negative along the Y axis + + Raised when the simulator sends us data containing + ... - - Nudge agent positive along the Z axis + + Raised when the simulator sends us data containing + ... - - Nudge agent negative along the Z axis + + Raised when the simulator sends us data containing + ... - + + Get this agents Inventory data - + + Callback for inventory item creation finishing + Whether the request to create an inventory + item succeeded or not + Inventory item being created. If success is + false this will be null - - Tell simulator to mark agent as away + + + Callback for an inventory item being create from an uploaded asset + + true if inventory item creation was successful + + + - + + + - + + Reply received when uploading an inventory asset + Has upload been successful + Error message if upload failed + Inventory asset UUID + New asset UUID - + + Delegate that is invoked when script upload is completed + Has upload succeded (note, there still might be compile errors) + Upload status message + Is compilation successful + If compilation failed, list of error messages, null on compilation success + Script inventory UUID + Script's new asset UUID - + + Set to true to accept offer, false to decline it + + + The folder to accept the inventory into, if null default folder for will be used + + + Callback when an inventory object is accepted and received from a + task inventory. This is the callback in which you actually get + the ItemID, as in ObjectOfferedCallback it is null when received + from a task. - + - Returns "always run" value, or changes it by sending a SetAlwaysRunPacket + Throttles the network traffic for various different traffic types. + Access this class through GridClient.Throttle - - The current value of the agent control flags - - - Gets or sets the interval in milliseconds at which - AgentUpdate packets are sent to the current simulator. Setting - this to a non-zero value will also enable the packet sending if - it was previously off, and setting it to zero will disable - - - Gets or sets whether AgentUpdate packets are sent to - the current simulator - - - Reset movement controls every time we send an update - - - - Send an AgentUpdate with the camera set at the current agent - position and pointing towards the heading specified - - Camera rotation in radians - Whether to send the AgentUpdate reliable - or not - - - - Rotates the avatar body and camera toward a target position. - This will also anchor the camera position on the avatar - - Region coordinates to turn toward - - + - Send new AgentUpdate packet to update our current camera - position and rotation + Default constructor, uses a default high total of 1500 KBps (1536000) - + - Send new AgentUpdate packet to update our current camera - position and rotation + Constructor that decodes an existing AgentThrottle packet in to + individual values - Whether to require server acknowledgement - of this packet + Reference to the throttle data in an AgentThrottle + packet + Offset position to start reading at in the + throttle data + This is generally not needed in clients as the server will + never send a throttle packet to the client - + - Send new AgentUpdate packet to update our current camera - position and rotation + Send an AgentThrottle packet to the current server using the + current values - Whether to require server acknowledgement - of this packet - Simulator to send the update to - + - Builds an AgentUpdate packet entirely from parameters. This - will not touch the state of Self.Movement or - Self.Movement.Camera in any way + Send an AgentThrottle packet to the specified server using the + current values - - - - - - - - - - - - - - - - - - - - - - - + - Used to specify movement actions for your agent + Convert the current throttle values to a byte array that can be put + in an AgentThrottle packet + Byte array containing all the throttle values - - Empty flag - - - Move Forward (SL Keybinding: W/Up Arrow) - - - Move Backward (SL Keybinding: S/Down Arrow) - - - Move Left (SL Keybinding: Shift-(A/Left Arrow)) - - - Move Right (SL Keybinding: Shift-(D/Right Arrow)) - - - Not Flying: Jump/Flying: Move Up (SL Keybinding: E) - - - Not Flying: Croutch/Flying: Move Down (SL Keybinding: C) + + Maximum bits per second for resending unacknowledged packets - - Unused + + Maximum bits per second for LayerData terrain - - Unused + + Maximum bits per second for LayerData wind data - - Unused + + Maximum bits per second for LayerData clouds - - Unused + + Unknown, includes object data - - ORed with AGENT_CONTROL_AT_* if the keyboard is being used + + Maximum bits per second for textures - - ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used + + Maximum bits per second for downloaded assets - - ORed with AGENT_CONTROL_UP_* if the keyboard is being used + + Maximum bits per second the entire connection, divided up + between invidiual streams using default multipliers - - Fly + + + Level of Detail mesh + - + + Sent to the client to indicate a teleport request has completed - - Finish our current animation + + + Interface requirements for Messaging system + - - Stand up from the ground or a prim seat + + The of the agent - - Sit on the ground at our current location + + - - Whether mouselook is currently enabled + + The simulators handle the agent teleported to - - Legacy, used if a key was pressed for less than a certain amount of time + + A Uri which contains a list of Capabilities the simulator supports - - Legacy, used if a key was pressed for less than a certain amount of time + + Indicates the level of access required + to access the simulator, or the content rating, or the simulators + map status - - Legacy, used if a key was pressed for less than a certain amount of time + + The IP Address of the simulator - - Legacy, used if a key was pressed for less than a certain amount of time + + The UDP Port the simulator will listen for UDP traffic on - - Legacy, used if a key was pressed for less than a certain amount of time + + Status flags indicating the state of the Agent upon arrival, Flying, etc. - - Legacy, used if a key was pressed for less than a certain amount of time + + + Serialize the object + + An containing the objects data - + + Deserialize the message + An containing the data - + + Sent to the viewer when a neighboring simulator is requesting the agent make a connection to it. - - Set when the avatar is idled or set to away. Note that the away animation is - activated separately from setting this flag + + + Serialize the object + + An containing the objects data - + + Deserialize the message + An containing the data - + + Serialize the object + An containing the objects data - + + Deserialize the message + An containing the data - + + Serialize the object + An containing the objects data - + - Called once attachment resource usage information has been collected + Deserialize the message - Indicates if operation was successfull - Attachment resource usage information + An containing the data - - The event subscribers. null if no subcribers + + + A message sent to the client which indicates a teleport request has failed + and contains some information on why it failed + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + A string key of the reason the teleport failed e.g. CouldntTPCloser + Which could be used to look up a value in a dictionary or enum - - Thread sync lock object + + The of the Agent - - The event subscribers. null if no subcribers + + A string human readable message containing the reason + An example: Could not teleport closer to destination - - Thread sync lock object + + + Serialize the object + + An containing the objects data - - The event subscribers. null if no subcribers + + + Deserialize the message + + An containing the data - - Thread sync lock object + + + Serialize the object + + An containing the objects data - - The event subscribers. null if no subcribers + + + Deserialize the message + + An containing the data - - Thread sync lock object + + + Contains a list of prim owner information for a specific parcel in a simulator + + + A Simulator will always return at least 1 entry + If agent does not have proper permission the OwnerID will be UUID.Zero + If agent does not have proper permission OR there are no primitives on parcel + the DataBlocksExtended map will not be sent from the simulator + - - The event subscribers. null if no subcribers + + An Array of objects - - Thread sync lock object + + + Serialize the object + + An containing the objects data - - The event subscribers. null if no subcribers + + + Deserialize the message + + An containing the data - - Thread sync lock object + + + Prim ownership information for a specified owner on a single parcel + - - The event subscribers. null if no subcribers + + The of the prim owner, + UUID.Zero if agent has no permission to view prim owner information - - Thread sync lock object + + The total number of prims - - The event subscribers. null if no subcribers + + True if the OwnerID is a - - Thread sync lock object + + True if the owner is online + This is no longer used by the LL Simulators - - The event subscribers. null if no subcribers + + The date the most recent prim was rezzed - - Thread sync lock object + + + The details of a single parcel in a region, also contains some regionwide globals + - - The event subscribers. null if no subcribers + + Simulator-local ID of this parcel - - Thread sync lock object + + Maximum corner of the axis-aligned bounding box for this + parcel - - The event subscribers. null if no subcribers + + Minimum corner of the axis-aligned bounding box for this + parcel - - Thread sync lock object + + Total parcel land area - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + Key of authorized buyer - - The event subscribers. null if no subcribers + + Bitmap describing land layout in 4x4m squares across the + entire region - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + Date land was claimed - - Thread sync lock object + + Appears to always be zero - - The event subscribers. null if no subcribers + + Parcel Description - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + Total number of primitives owned by the parcel group on + this parcel - - The event subscribers. null if no subcribers + + Whether the land is deeded to a group or not - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + Maximum number of primitives this parcel supports - - Thread sync lock object + + The Asset UUID of the Texture which when applied to a + primitive will display the media - - The event subscribers. null if no subcribers + + A URL which points to any Quicktime supported media type - - Thread sync lock object + + A byte, if 0x1 viewer should auto scale media to fit object - - Reference to the GridClient instance + + URL For Music Stream - - Used for movement and camera tracking + + Parcel Name - - Currently playing animations for the agent. Can be used to - check the current movement status such as walking, hovering, aiming, - etc. by checking against system animations found in the Animations class + + Autoreturn value in minutes for others' objects - - Dictionary containing current Group Chat sessions and members + + - - Raised when a scripted object or agent within range sends a public message + + Total number of other primitives on this parcel - - Raised when a scripted object sends a dialog box containing possible - options an agent can respond to + + UUID of the owner of this parcel - - Raised when an object requests a change in the permissions an agent has permitted + + Total number of primitives owned by the parcel owner on + this parcel - - Raised when a script requests an agent open the specified URL + + - - Raised when an agents currency balance is updated + + How long is pass valid for - - Raised when a transaction occurs involving currency such as a land purchase + + Price for a temporary pass - - Raised when an ImprovedInstantMessage packet is recieved from the simulator, this is used for everything from - private messaging to friendship offers. The Dialog field defines what type of message has arrived + + - - Raised when an agent has requested a teleport to another location, or when responding to a lure. Raised multiple times - for each teleport indicating the progress of the request + + - - Raised when a simulator sends agent specific information for our avatar. + + - - Raised when our agents animation playlist changes + + - - Raised when an object or avatar forcefully collides with our agent + + True if the region denies access to age unverified users - - Raised when our agent crosses a region border into another region + + - - Raised when our agent succeeds or fails to join a group chat session + + This field is no longer used - - Raised when a simulator sends an urgent message usually indication the recent failure of - another action we have attempted to take such as an attempt to enter a parcel where we are denied access + + The result of a request for parcel properties - - Raised when a script attempts to take or release specified controls for our agent + + Sale price of the parcel, only useful if ForSale is set + The SalePrice will remain the same after an ownership + transfer (sale), so it can be used to see the purchase price after + a sale if the new owner has not changed it - - Raised when the simulator detects our agent is trying to view something - beyond its limits + + + Number of primitives your avatar is currently + selecting and sitting on in this parcel + - - Raised when a script sensor reply is received from a simulator + + - - Raised in response to a request + + + A number which increments by 1, starting at 0 for each ParcelProperties request. + Can be overriden by specifying the sequenceID with the ParcelPropertiesRequest being sent. + a Negative number indicates the action in has occurred. + - - Raised when an avatar enters a group chat session we are participating in + + Maximum primitives across the entire simulator - - Raised when an agent exits a group chat session we are participating in + + Total primitives across the entire simulator - - Your (client) avatars - "client", "agent", and "avatar" all represent the same thing + + - - Temporary assigned to this session, used for - verifying our identity in packets + + Key of parcel snapshot - - Shared secret that is never sent over the wire + + Parcel ownership status - - Your (client) avatar ID, local to the current region/sim + + Total number of primitives on this parcel - - Where the avatar started at login. Can be "last", "home" - or a login + + - - The access level of this agent, usually M or PG + + - - The CollisionPlane of Agent + + A description of the media - - An representing the velocity of our agent + + An Integer which represents the height of the media - - An representing the acceleration of our agent + + An integer which represents the width of the media - - A which specifies the angular speed, and axis about which an Avatar is rotating. + + A boolean, if true the viewer should loop the media - - Position avatar client will goto when login to 'home' or during - teleport request to 'home' region. + + A string which contains the mime type of the media - - LookAt point saved/restored with HomePosition + + true to obscure (hide) media url - - Avatar First Name (i.e. Philip) + + true to obscure (hide) music url - - Avatar Last Name (i.e. Linden) + + + Serialize the object + + An containing the objects data - - Avatar Full Name (i.e. Philip Linden) + + + Deserialize the message + + An containing the data - - Gets the health of the agent + + A message sent from the viewer to the simulator to updated a specific parcels settings - - Gets the current balance of the agent + + The of the agent authorized to purchase this + parcel of land or a NULL if the sale is authorized to anyone - - Gets the local ID of the prim the agent is sitting on, - zero if the avatar is not currently sitting + + true to enable auto scaling of the parcel media - - Gets the of the agents active group. + + The category of this parcel used when search is enabled to restrict + search results - - Gets the Agents powers in the currently active group + + A string containing the description to set - - Current status message for teleporting + + The of the which allows for additional + powers and restrictions. - - Current position of the agent as a relative offset from - the simulator, or the parent object if we are sitting on something + + The which specifies how avatars which teleport + to this parcel are handled - - Current rotation of the agent as a relative rotation from - the simulator, or the parent object if we are sitting on something + + The LocalID of the parcel to update settings on - - Current position of the agent in the simulator + + A string containing the description of the media which can be played + to visitors - - - A representing the agents current rotation - + + - - Returns the global grid position of the avatar + + - - Raises the ChatFromSimulator event - A ChatEventArgs object containing the - data returned from the data server + + - - Raises the ScriptDialog event - A SctriptDialogEventArgs object containing the - data returned from the data server + + - - Raises the ScriptQuestion event - A ScriptQuestionEventArgs object containing the - data returned from the data server + + - - Raises the LoadURL event - A LoadUrlEventArgs object containing the - data returned from the data server + + - - Raises the MoneyBalance event - A BalanceEventArgs object containing the - data returned from the data server + + - - Raises the MoneyBalanceReply event - A MoneyBalanceReplyEventArgs object containing the - data returned from the data server + + - - Raises the IM event - A InstantMessageEventArgs object containing the - data returned from the data server + + - - Raises the TeleportProgress event - A TeleportEventArgs object containing the - data returned from the data server + + - - Raises the AgentDataReply event - A AgentDataReplyEventArgs object containing the - data returned from the data server + + - - Raises the AnimationsChanged event - A AnimationsChangedEventArgs object containing the - data returned from the data server + + - - Raises the MeanCollision event - A MeanCollisionEventArgs object containing the - data returned from the data server + + - - Raises the RegionCrossed event - A RegionCrossedEventArgs object containing the - data returned from the data server + + - - Raises the GroupChatJoined event - A GroupChatJoinedEventArgs object containing the - data returned from the data server + + - - Raises the AlertMessage event - A AlertMessageEventArgs object containing the - data returned from the data server + + - - Raises the ScriptControlChange event - A ScriptControlEventArgs object containing the - data returned from the data server + + - - Raises the CameraConstraint event - A CameraConstraintEventArgs object containing the - data returned from the data server + + + Deserialize the message + + An containing the data - - Raises the ScriptSensorReply event - A ScriptSensorReplyEventArgs object containing the - data returned from the data server + + + Serialize the object + + An containing the objects data - - Raises the AvatarSitResponse event - A AvatarSitResponseEventArgs object containing the - data returned from the data server + + Base class used for the RemoteParcelRequest message - - Raises the ChatSessionMemberAdded event - A ChatSessionMemberAddedEventArgs object containing the - data returned from the data server + + + A message sent from the viewer to the simulator to request information + on a remote parcel + - - Raises the ChatSessionMemberLeft event - A ChatSessionMemberLeftEventArgs object containing the - data returned from the data server + + Local sim position of the parcel we are looking up - + + Region handle of the parcel we are looking up + + + Region of the parcel we are looking up + + - Send a text message from the Agent to the Simulator + Serialize the object - A containing the message - The channel to send the message on, 0 is the public channel. Channels above 0 - can be used however only scripts listening on the specified channel will see the message - Denotes the type of message being sent, shout, whisper, etc. + An containing the objects data - + - Request any instant messages sent while the client was offline to be resent. + Deserialize the message + An containing the data - + - Send an Instant Message to another Avatar + A message sent from the simulator to the viewer in response to a + which will contain parcel information - The recipients - A containing the message to send - + + The grid-wide unique parcel ID + + - Send an Instant Message to an existing group chat or conference chat + Serialize the object - The recipients - A containing the message to send - IM session ID (to differentiate between IM windows) + An containing the objects data - + - Send an Instant Message + Deserialize the message - The name this IM will show up as being from - Key of Avatar - Text message being sent - IM session ID (to differentiate between IM windows) - IDs of sessions for a conference + An containing the data - + - Send an Instant Message + A message containing a request for a remote parcel from a viewer, or a response + from the simulator to that request - The name this IM will show up as being from - Key of Avatar - Text message being sent - IM session ID (to differentiate between IM windows) - Type of instant message to send - Whether to IM offline avatars as well - Senders Position - RegionID Sender is In - Packed binary data that is specific to - the dialog type - + + The request or response details block + + - Send an Instant Message to a group + Serialize the object - - of the group to send message to - Text Message being sent. + An containing the objects data - + - Send an Instant Message to a group the agent is a member of + Deserialize the message - The name this IM will show up as being from - - of the group to send message to - Text message being sent + An containing the data - + - Send a request to join a group chat session + Serialize the object - - of Group to leave + An containing the objects data - + - Exit a group chat session. This will stop further Group chat messages - from being sent until session is rejoined. + Deserialize the message - - of Group chat session to leave + An containing the data - + - Reply to script dialog questions. + Serialize the object - Channel initial request came on - Index of button you're "clicking" - Label of button you're "clicking" - - of Object that sent the dialog request - + An containing the objects data - + - Accept invite for to a chatterbox session + Deserialize the message - - of session to accept invite to + An containing the data - + - Start a friends conference + A message sent from the simulator to an agent which contains + the groups the agent is in - - List of UUIDs to start a conference with - the temportary session ID returned in the callback> - + + The Agent receiving the message + + + An array containing information + for each the agent is a member of + + + An array containing information + for each the agent is a member of + + - Start a particle stream between an agent and an object + Serialize the object - - Key of the source agent - - Key of the target object - - - The type from the enum - A unique for this effect + An containing the objects data - + - Start a particle stream between an agent and an object + Deserialize the message - - Key of the source agent - - Key of the target object - A representing the beams offset from the source - A which sets the avatars lookat animation - - of the Effect + An containing the data - + + Group Details specific to the agent + + + true of the agent accepts group notices + + + The agents tier contribution to the group + + + The Groups + + + The of the groups insignia + + + The name of the group + + + The aggregate permissions the agent has in the group for all roles the agent + is assigned + + + An optional block containing additional agent specific information + + + true of the agent allows this group to be + listed in their profile + + - Create a particle beam between an avatar and an primitive + A message sent from the viewer to the simulator which + specifies the language and permissions for others to detect + the language specified - The ID of source avatar - The ID of the target primitive - global offset - A object containing the combined red, green, blue and alpha - color values of particle beam - a float representing the duration the parcicle beam will last - A Unique ID for the beam - - + + A string containng the default language + to use for the agent + + + true of others are allowed to + know the language setting + + - Create a particle swirl around a target position using a packet + Serialize the object - global offset - A object containing the combined red, green, blue and alpha - color values of particle beam - a float representing the duration the parcicle beam will last - A Unique ID for the beam + An containing the objects data - + - Sends a request to sit on the specified object + Deserialize the message - - of the object to sit on - Sit at offset + An containing the data - + - Follows a call to to actually sit on the object + An EventQueue message sent from the simulator to an agent when the agent + leaves a group - - Stands up from sitting on a prim or the ground - true of AgentUpdate was sent - - + - Does a "ground sit" at the avatar's current position + An Array containing the AgentID and GroupID - + - Starts or stops flying + Serialize the object - True to start flying, false to stop flying + An containing the objects data - + - Starts or stops crouching + Deserialize the message - True to start crouching, false to stop crouching + An containing the data - + + An object containing the Agents UUID, and the Groups UUID + + + The ID of the Agent leaving the group + + + The GroupID the Agent is leaving + + + Base class for Asset uploads/results via Capabilities + + - Starts a jump (begin holding the jump key) + The request state - + - Use the autopilot sim function to move the avatar to a new - position. Uses double precision to get precise movements + Serialize the object - The z value is currently not handled properly by the simulator - Global X coordinate to move to - Global Y coordinate to move to - Z coordinate to move to + An containing the objects data - + - Use the autopilot sim function to move the avatar to a new position + Deserialize the message - The z value is currently not handled properly by the simulator - Integer value for the global X coordinate to move to - Integer value for the global Y coordinate to move to - Floating-point value for the Z coordinate to move to + An containing the data - + - Use the autopilot sim function to move the avatar to a new position + A message sent from the viewer to the simulator to request a temporary upload capability + which allows an asset to be uploaded - The z value is currently not handled properly by the simulator - Integer value for the local X coordinate to move to - Integer value for the local Y coordinate to move to - Floating-point value for the Z coordinate to move to - - Macro to cancel autopilot sim function - Not certain if this is how it is really done - true if control flags were set and AgentUpdate was sent to the simulator + + The Capability URL sent by the simulator to upload the baked texture to - + - Grabs an object + A message sent from the simulator that will inform the agent the upload is complete, + and the UUID of the uploaded asset - an unsigned integer of the objects ID within the simulator - - - - Overload: Grab a simulated object - - an unsigned integer of the objects ID within the simulator - - - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space + + The uploaded texture asset ID - + - Drag an object + A message sent from the viewer to the simulator to request a temporary + capability URI which is used to upload an agents baked appearance textures - - of the object to drag - Drag target in region coordinates - + + Object containing request or response + + - Overload: Drag an object + Serialize the object - - of the object to drag - Drag target in region coordinates - - - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space + An containing the objects data - + - Release a grabbed object + Deserialize the message - The Objects Simulator Local ID - - - + An containing the data - + - Release a grabbed object + A message sent from the simulator which indicates the minimum version required for + using voice chat - The Objects Simulator Local ID - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - + + Major Version Required + + + Minor version required + + + The name of the region sending the version requrements + + - Touches an object + Serialize the object - an unsigned integer of the objects ID within the simulator - + An containing the objects data - + - Request the current L$ balance + Deserialize the message + An containing the data - + - Give Money to destination Avatar + A message sent from the simulator to the viewer containing the + voice server URI - UUID of the Target Avatar - Amount in L$ - - - Give Money to destination Avatar - - UUID of the Target Avatar - Amount in L$ - Description that will show up in the - recipients transaction history + + The Parcel ID which the voice server URI applies - + + The name of the region + + + A uri containing the server/channel information + which the viewer can utilize to participate in voice conversations + + - Give L$ to an object + Serialize the object - object to give money to - amount of L$ to give - name of object + An containing the objects data - + - Give L$ to a group + Deserialize the message - group to give money to - amount of L$ to give + An containing the data - + - Give L$ to a group + - group to give money to - amount of L$ to give - description of transaction - + + + + + + + - Pay texture/animation upload fee + Serialize the object + An containing the objects data - + - Pay texture/animation upload fee + Deserialize the message - description of the transaction + An containing the data - + - Give Money to destination Object or Avatar + A message sent by the viewer to the simulator to request a temporary + capability for a script contained with in a Tasks inventory to be updated - UUID of the Target Object/Avatar - Amount in L$ - Reason (Optional normally) - The type of transaction - Transaction flags, mostly for identifying group - transactions - + + Object containing request or response + + - Plays a gesture + Serialize the object - Asset of the gesture + An containing the objects data - + - Mark gesture active + Deserialize the message - Inventory of the gesture - Asset of the gesture + An containing the data - + - Mark gesture inactive + A message sent from the simulator to the viewer to indicate + a Tasks scripts status. - Inventory of the gesture - + + The Asset ID of the script + + + True of the script is compiled/ran using the mono interpreter, false indicates it + uses the older less efficient lsl2 interprter + + + The Task containing the scripts + + + true of the script is in a running state + + - Send an AgentAnimation packet that toggles a single animation on + Serialize the object - The of the animation to start playing - Whether to ensure delivery of this packet or not + An containing the objects data - + - Send an AgentAnimation packet that toggles a single animation off + Deserialize the message - The of a - currently playing animation to stop playing - Whether to ensure delivery of this packet or not + An containing the data - + - Send an AgentAnimation packet that will toggle animations on or off + A message containing the request/response used for updating a gesture + contained with an agents inventory - A list of animation s, and whether to - turn that animation on or off - Whether to ensure delivery of this packet or not - + + Object containing request or response + + - Teleports agent to their stored home location + Serialize the object - true on successful teleport to home location + An containing the objects data - + - Teleport agent to a landmark + Deserialize the message - - of the landmark to teleport agent to - true on success, false on failure + An containing the data - + - Attempt to look up a simulator name and teleport to the discovered - destination + A message request/response which is used to update a notecard contained within + a tasks inventory - Region name to look up - Position to teleport to - True if the lookup and teleport were successful, otherwise - false - + + The of the Task containing the notecard asset to update + + + The notecard assets contained in the tasks inventory + + - Attempt to look up a simulator name and teleport to the discovered - destination + Serialize the object - Region name to look up - Position to teleport to - Target to look at - True if the lookup and teleport were successful, otherwise - false + An containing the objects data - + - Teleport agent to another region + Deserialize the message - handle of region to teleport agent to - - position in destination sim to teleport to - true on success, false on failure - This call is blocking + An containing the data - + - Teleport agent to another region + A reusable class containing a message sent from the viewer to the simulator to request a temporary uploader capability + which is used to update an asset in an agents inventory - handle of region to teleport agent to - - position in destination sim to teleport to - - direction in destination sim agent will look at - true on success, false on failure - This call is blocking - + - Request teleport to a another simulator + The Notecard AssetID to replace - handle of region to teleport agent to - - position in destination sim to teleport to - + - Request teleport to a another simulator + Serialize the object - handle of region to teleport agent to - - position in destination sim to teleport to - - direction in destination sim agent will look at + An containing the objects data - + - Teleport agent to a landmark + Deserialize the message - - of the landmark to teleport agent to + An containing the data - + - Send a teleport lure to another avatar with default "Join me in ..." invitation message + A message containing the request/response used for updating a notecard + contained with an agents inventory - target avatars to lure - + + Object containing request or response + + - Send a teleport lure to another avatar with custom invitation message + Serialize the object - target avatars to lure - custom message to send with invitation + An containing the objects data - + - Respond to a teleport lure by either accepting it and initiating - the teleport, or denying it + Deserialize the message - - of the avatar sending the lure - true to accept the lure, false to decline it + An containing the data - + - Update agent profile + Serialize the object - - struct containing updated - profile information + An containing the objects data - + - Update agents profile interests + Deserialize the message - selection of interests from struct + An containing the data - + - Set the height and the width of the client window. This is used - by the server to build a virtual camera frustum for our avatar + A message sent from the simulator to the viewer which indicates + an error occurred while attempting to update a script in an agents or tasks + inventory - New height of the viewer window - New width of the viewer window - + + true of the script was successfully compiled by the simulator + + + A string containing the error which occured while trying + to update the script + + + A new AssetID assigned to the script + + - Request the list of muted objects and avatars for this agent + A message sent from the viewer to the simulator + requesting the update of an existing script contained + within a tasks inventory - + + if true, set the script mode to running + + + The scripts InventoryItem ItemID to update + + + A lowercase string containing either "mono" or "lsl2" which + specifies the script is compiled and ran on the mono runtime, or the older + lsl runtime + + + The tasks which contains the script to update + + - Sets home location to agents current position + Serialize the object - will fire an AlertMessage () with - success or failure message + An containing the objects data - + - Move an agent in to a simulator. This packet is the last packet - needed to complete the transition in to a new simulator + Deserialize the message - - Object + An containing the data - + - Reply to script permissions request + A message containing either the request or response used in updating a script inside + a tasks inventory - - Object - - of the itemID requesting permissions - - of the taskID requesting permissions - - list of permissions to allow - + + Object containing request or response + + - Respond to a group invitation by either accepting or denying it + Serialize the object - UUID of the group (sent in the AgentID field of the invite message) - IM Session ID from the group invitation message - Accept the group invitation or deny it + An containing the objects data - + - Requests script detection of objects and avatars + Deserialize the message - name of the object/avatar to search for - UUID of the object or avatar to search for - Type of search from ScriptSensorTypeFlags - range of scan (96 max?) - the arc in radians to search within - an user generated ID to correlate replies with - Simulator to perform search in + An containing the data - + - Create or update profile pick + Response from the simulator to notify the viewer the upload is completed, and + the UUID of the script asset and its compiled status - UUID of the pick to update, or random UUID to create a new pick - Is this a top pick? (typically false) - UUID of the parcel (UUID.Zero for the current parcel) - Name of the pick - Global position of the pick landmark - UUID of the image displayed with the pick - Long description of the pick - + + The uploaded texture asset ID + + + true of the script was compiled successfully + + - Delete profile pick + A message sent from a viewer to the simulator requesting a temporary uploader capability + used to update a script contained in an agents inventory - UUID of the pick to delete - + + The existing asset if of the script in the agents inventory to replace + + + The language of the script + Defaults to lsl version 2, "mono" might be another possible option + + - Create or update profile Classified + Serialize the object - UUID of the classified to update, or random UUID to create a new classified - Defines what catagory the classified is in - UUID of the image displayed with the classified - Price that the classified will cost to place for a week - Global position of the classified landmark - Name of the classified - Long description of the classified - if true, auto renew classified after expiration + An containing the objects data - + - Create or update profile Classified + Deserialize the message - UUID of the classified to update, or random UUID to create a new classified - Defines what catagory the classified is in - UUID of the image displayed with the classified - Price that the classified will cost to place for a week - Name of the classified - Long description of the classified - if true, auto renew classified after expiration + An containing the data - + - Delete a classified ad + A message containing either the request or response used in updating a script inside + an agents inventory - The classified ads ID - + + Object containing request or response + + - Fetches resource usage by agents attachmetns + Serialize the object - Called when the requested information is collected + An containing the objects data - + - Take an incoming ImprovedInstantMessage packet, auto-parse, and if - OnInstantMessage is defined call that with the appropriate arguments + Deserialize the message - The sender - The EventArgs object containing the packet data + An containing the data - + - Take an incoming Chat packet, auto-parse, and if OnChat is defined call - that with the appropriate arguments. + Serialize the object - The sender - The EventArgs object containing the packet data + An containing the objects data - + - Used for parsing llDialogs + Deserialize the message - The sender - The EventArgs object containing the packet data + An containing the data - + + Base class for Map Layers via Capabilities + + + + + - Used for parsing llRequestPermissions dialogs + Serialize the object - The sender - The EventArgs object containing the packet data + An containing the objects data - + - Handles Script Control changes when Script with permissions releases or takes a control + Deserialize the message - The sender - The EventArgs object containing the packet data + An containing the data - + - Used for parsing llLoadURL Dialogs + Sent by an agent to the capabilities server to request map layers - The sender - The EventArgs object containing the packet data - + - Update client's Position, LookAt and region handle from incoming packet + A message sent from the simulator to the viewer which contains an array of map images and their grid coordinates - The sender - The EventArgs object containing the packet data - This occurs when after an avatar moves into a new sim - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + An array containing LayerData items - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Serialize the object + + An containing the objects data - + - Process TeleportFailed message sent via EventQueue, informs agent its last teleport has failed and why. + Deserialize the message - The Message Key - An IMessage object Deserialized from the recieved message event - The simulator originating the event message + An containing the data - + - Process TeleportFinish from Event Queue and pass it onto our TeleportHandler + An object containing map location details - The message system key for this event - IMessage object containing decoded data from OSD - The simulator originating the event message - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The Asset ID of the regions tile overlay - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The grid location of the southern border of the map tile - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The grid location of the western border of the map tile - - - Crossed region handler for message that comes across the EventQueue. Sent to an agent - when the agent crosses a sim border into a new region. - - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet + + The grid location of the eastern border of the map tile - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - This packet is now being sent via the EventQueue + + The grid location of the northern border of the map tile - + + Object containing request or response + + - Group Chat event handler + Serialize the object - The capability Key - IMessage object containing decoded data from OSD - - + An containing the objects data - + - Response from request to join a group chat + Deserialize the message - - - IMessage object containing decoded data from OSD - - + An containing the data - + - Someone joined or left group chat + New as of 1.23 RC1, no details yet. - - - IMessage object containing decoded data from OSD - - - + - Handle a group chat Invitation + Serialize the object - Caps Key - IMessage object containing decoded data from OSD - Originating Simulator + An containing the objects data - + - Moderate a chat session + Deserialize the message - the of the session to moderate, for group chats this will be the groups UUID - the of the avatar to moderate - Either "voice" to moderate users voice, or "text" to moderate users text session - true to moderate (silence user), false to allow avatar to speak - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + An containing the data - + + Serialize the object + An containing the objects data - + - Construct a new instance of the ChatEventArgs object + Deserialize the message - Sim from which the message originates - The message sent - The audible level of the message - The type of message sent: whisper, shout, etc - The source type of the message sender - The name of the agent or object sending the message - The ID of the agent or object sending the message - The ID of the object owner, or the agent ID sending the message - The position of the agent or object sending the message + An containing the data - - Get the simulator sending the message + + A string containing the method used - - Get the message sent + + + A request sent from an agent to the Simulator to begin a new conference. + Contains a list of Agents which will be included in the conference + - - Get the audible level of the message + + An array containing the of the agents invited to this conference - - Get the type of message sent: whisper, shout, etc + + The conferences Session ID - - Get the source type of the message sender + + + Serialize the object + + An containing the objects data - - Get the name of the agent or object sending the message + + + Deserialize the message + + An containing the data - - Get the ID of the agent or object sending the message + + + A moderation request sent from a conference moderator + Contains an agent and an optional action to take + - - Get the ID of the object owner, or the agent ID sending the message + + The Session ID - - Get the position of the agent or object sending the message + + - - Contains the data sent when a primitive opens a dialog with this agent + + A list containing Key/Value pairs, known valid values: + key: text value: true/false - allow/disallow specified agents ability to use text in session + key: voice value: true/false - allow/disallow specified agents ability to use voice in session + + "text" or "voice" - + + + + - Construct a new instance of the ScriptDialogEventArgs + Serialize the object - The dialog message - The name of the object that sent the dialog request - The ID of the image to be displayed - The ID of the primitive sending the dialog - The first name of the senders owner - The last name of the senders owner - The communication channel the dialog was sent on - The string labels containing the options presented in this dialog + An containing the objects data - - Get the dialog message + + + Deserialize the message + + An containing the data - - Get the name of the object that sent the dialog request + + + A message sent from the agent to the simulator which tells the + simulator we've accepted a conference invitation + - - Get the ID of the image to be displayed + + The conference SessionID - - Get the ID of the primitive sending the dialog + + + Serialize the object + + An containing the objects data - - Get the first name of the senders owner + + + Deserialize the message + + An containing the data - - Get the last name of the senders owner + + + Serialize the object + + An containing the objects data - - Get the communication channel the dialog was sent on, responses - should also send responses on this same channel + + + Deserialize the message + + An containing the data - - Get the string labels containing the options presented in this dialog + + + Serialize the object + + An containing the objects data - - Contains the data sent when a primitive requests debit or other permissions - requesting a YES or NO answer + + + Deserialize the message + + An containing the data - + - Construct a new instance of the ScriptQuestionEventArgs + Serialize the object - The simulator containing the object sending the request - The ID of the script making the request - The ID of the primitive containing the script making the request - The name of the primitive making the request - The name of the owner of the object making the request - The permissions being requested + An containing the objects data - - Get the simulator containing the object sending the request + + + Deserialize the message + + An containing the data - - Get the ID of the script making the request + + Key of sender - - Get the ID of the primitive containing the script making the request + + Name of sender - - Get the name of the primitive making the request + + Key of destination avatar - - Get the name of the owner of the object making the request + + ID of originating estate - - Get the permissions being requested + + Key of originating region - - Contains the data sent when a primitive sends a request - to an agent to open the specified URL + + Coordinates in originating region - - - Construct a new instance of the LoadUrlEventArgs - - The name of the object sending the request - The ID of the object sending the request - The ID of the owner of the object sending the request - True if the object is owned by a group - The message sent with the request - The URL the object sent + + Instant message type - - Get the name of the object sending the request + + Group IM session toggle - - Get the ID of the object sending the request + + Key of IM session, for Group Messages, the groups UUID - - Get the ID of the owner of the object sending the request + + Timestamp of the instant message - - True if the object is owned by a group + + Instant message text - - Get the message sent with the request + + Whether this message is held for offline avatars - - Get the URL the object sent + + Context specific packed data - - The date received from an ImprovedInstantMessage + + Is this invitation for voice group/conference chat - + - Construct a new instance of the InstantMessageEventArgs object + Serialize the object - the InstantMessage object - the simulator where the InstantMessage origniated + An containing the objects data - - Get the InstantMessage object + + + Deserialize the message + + An containing the data - - Get the simulator where the InstantMessage origniated + + + Sent from the simulator to the viewer. + + When an agent initially joins a session the AgentUpdatesBlock object will contain a list of session members including + a boolean indicating they can use voice chat in this session, a boolean indicating they are allowed to moderate + this session, and lastly a string which indicates another agent is entering the session with the Transition set to "ENTER" + + During the session lifetime updates on individuals are sent. During the update the booleans sent during the initial join are + excluded with the exception of the Transition field. This indicates a new user entering or exiting the session with + the string "ENTER" or "LEAVE" respectively. + - - Contains the currency balance + + + Serialize the object + + An containing the objects data - + - Construct a new BalanceEventArgs object + Deserialize the message - The currenct balance + An containing the data - + - Get the currenct balance + An EventQueue message sent when the agent is forcibly removed from a chatterbox session - - Contains the transaction summary when an item is purchased, - money is given, or land is purchased + + + A string containing the reason the agent was removed + - + - Construct a new instance of the MoneyBalanceReplyEventArgs object + The ChatterBoxSession's SessionID - The ID of the transaction - True of the transaction was successful - The current currency balance - The meters credited - The meters comitted - A brief description of the transaction - - - Get the ID of the transaction - - - True of the transaction was successful - - - Get the remaining currency balance - - - Get the meters credited - - - Get the meters comitted - - - Get the description of the transaction - - - Data sent from the simulator containing information about your agent and active group information - + - Construct a new instance of the AgentDataReplyEventArgs object + Serialize the object - The agents first name - The agents last name - The agents active group ID - The group title of the agents active group - The combined group powers the agent has in the active group - The name of the group the agent has currently active - - - Get the agents first name - - - Get the agents last name - - - Get the active group ID of your agent - - - Get the active groups title of your agent + An containing the objects data - - Get the combined group powers of your agent + + + Deserialize the message + + An containing the data - - Get the active group name of your agent + + + Serialize the object + + An containing the objects data - - Data sent by the simulator to indicate the active/changed animations - applied to your agent + + + Deserialize the message + + An containing the data - + - Construct a new instance of the AnimationsChangedEventArgs class + Serialize the object - The dictionary that contains the changed animations + An containing the objects data - - Get the dictionary that contains the changed animations + + + Deserialize the message + + An containing the data - + - Data sent from a simulator indicating a collision with your agent + Serialize the object + An containing the objects data - + - Construct a new instance of the MeanCollisionEventArgs class + Deserialize the message - The type of collision that occurred - The ID of the agent or object that perpetrated the agression - The ID of the Victim - The strength of the collision - The Time the collision occurred + An containing the data - - Get the Type of collision + + + Serialize the object + + An containing the objects data - - Get the ID of the agent or object that collided with your agent + + + Deserialize the message + + An containing the data - - Get the ID of the agent that was attacked + + + + - - A value indicating the strength of the collision + + + Serialize the object + + An containing the objects data - - Get the time the collision occurred + + + Deserialize the message + + An containing the data - - Data sent to your agent when it crosses region boundaries + + + Serialize the object + + An containing the objects data - + - Construct a new instance of the RegionCrossedEventArgs class + Deserialize the message - The simulator your agent just left - The simulator your agent is now in + An containing the data - - Get the simulator your agent just left + + + Serialize the object + + An containing the objects data - - Get the simulator your agent is now in + + + Deserialize the message + + An containing the data - - Data sent from the simulator when your agent joins a group chat session + + + A message sent from the viewer to the simulator which + specifies that the user has changed current URL + of the specific media on a prim face + - + - Construct a new instance of the GroupChatJoinedEventArgs class + New URL - The ID of the session - The name of the session - A temporary session id used for establishing new sessions - True of your agent successfully joined the session - - Get the ID of the group chat session + + + Prim UUID where navigation occured + - - Get the name of the session + + + Face index + - - Get the temporary session ID used for establishing new sessions + + + Serialize the object + + An containing the objects data - - True if your agent successfully joined the session + + + Deserialize the message + + An containing the data - - Data sent by the simulator containing urgent messages + + Base class used for the ObjectMedia message - + - Construct a new instance of the AlertMessageEventArgs class + Message used to retrive prim media data - The alert message - - Get the alert message + + + Prim UUID + - - Data sent by a script requesting to take or release specified controls to your agent + + + Requested operation, either GET or UPDATE + - + - Construct a new instance of the ScriptControlEventArgs class + Serialize object - The controls the script is attempting to take or release to the agent - True if the script is passing controls back to the agent - True if the script is requesting controls be released to the script + Serialized object as OSDMap - - Get the controls the script is attempting to take or release to the agent + + + Deserialize the message + + An containing the data - - True if the script is passing controls back to the agent + + + Message used to update prim media data + - - True if the script is requesting controls be released to the script + + + Prim UUID + - + - Data sent from the simulator to an agent to indicate its view limits + Array of media entries indexed by face number - + - Construct a new instance of the CameraConstraintEventArgs class + Media version string - The collision plane - - Get the collision plane + + + Serialize object + + Serialized object as OSDMap - + - Data containing script sensor requests which allow an agent to know the specific details - of a primitive sending script sensor requests + Deserialize the message + An containing the data - + - Construct a new instance of the ScriptSensorReplyEventArgs + Message used to update prim media data - The ID of the primitive sending the sensor - The ID of the group associated with the primitive - The name of the primitive sending the sensor - The ID of the primitive sending the sensor - The ID of the owner of the primitive sending the sensor - The position of the primitive sending the sensor - The range the primitive specified to scan - The rotation of the primitive sending the sensor - The type of sensor the primitive sent - The velocity of the primitive sending the sensor - - Get the ID of the primitive sending the sensor + + + Prim UUID + - - Get the ID of the group associated with the primitive + + + Array of media entries indexed by face number + - - Get the name of the primitive sending the sensor + + + Requested operation, either GET or UPDATE + - - Get the ID of the primitive sending the sensor + + + Serialize object + + Serialized object as OSDMap - - Get the ID of the owner of the primitive sending the sensor + + + Deserialize the message + + An containing the data - - Get the position of the primitive sending the sensor + + + Message for setting or getting per face MediaEntry + - - Get the range the primitive specified to scan + + The request or response details block - - Get the rotation of the primitive sending the sensor + + + Serialize the object + + An containing the objects data - - Get the type of sensor the primitive sent + + + Deserialize the message + + An containing the data - - Get the velocity of the primitive sending the sensor + + Details about object resource usage - - Contains the response data returned from the simulator in response to a + + Object UUID - - Construct a new instance of the AvatarSitResponseEventArgs object + + Object name - - Get the ID of the primitive the agent will be sitting on + + Indicates if object is group owned - - True if the simulator Autopilot functions were involved + + Locatio of the object - - Get the camera offset of the agent when seated + + Object owner - - Get the camera eye offset of the agent when seated + + Resource usage, keys are resource names, values are resource usage for that specific resource - - True of the agent will be in mouselook mode when seated + + + Deserializes object from OSD + + An containing the data - - Get the position of the agent when seated + + + Makes an instance based on deserialized data + + serialized data + Instance containg deserialized data - - Get the rotation of the agent when seated + + Details about parcel resource usage - - Data sent when an agent joins a chat session your agent is currently participating in + + Parcel UUID - + + Parcel local ID + + + Parcel name + + + Indicates if parcel is group owned + + + Parcel owner + + + Array of containing per object resource usage + + - Construct a new instance of the ChatSessionMemberAddedEventArgs object + Deserializes object from OSD - The ID of the chat session - The ID of the agent joining + An containing the data - - Get the ID of the chat session + + + Makes an instance based on deserialized data + + serialized data + Instance containg deserialized data - - Get the ID of the agent that joined + + Resource usage base class, both agent and parcel resource + usage contains summary information - - Data sent when an agent exits a chat session your agent is currently participating in + + Summary of available resources, keys are resource names, + values are resource usage for that specific resource - + + Summary resource usage, keys are resource names, + values are resource usage for that specific resource + + - Construct a new instance of the ChatSessionMemberLeftEventArgs object + Serializes object - The ID of the chat session - The ID of the Agent that left + serialized data - - Get the ID of the chat session + + + Deserializes object from OSD + + An containing the data - - Get the ID of the agent that left + + Agent resource usage - + + Per attachment point object resource usage + + - Throttles the network traffic for various different traffic types. - Access this class through GridClient.Throttle + Deserializes object from OSD + An containing the data - + - Default constructor, uses a default high total of 1500 KBps (1536000) + Makes an instance based on deserialized data + serialized data + Instance containg deserialized data - + - Constructor that decodes an existing AgentThrottle packet in to - individual values + Detects which class handles deserialization of this message - Reference to the throttle data in an AgentThrottle - packet - Offset position to start reading at in the - throttle data - This is generally not needed in clients as the server will - never send a throttle packet to the client + An containing the data + Object capable of decoding this message - - Maximum bits per second for resending unacknowledged packets + + Request message for parcel resource usage - - Maximum bits per second for LayerData terrain + + UUID of the parel to request resource usage info - - Maximum bits per second for LayerData wind data + + + Serializes object + + serialized data - - Maximum bits per second for LayerData clouds + + + Deserializes object from OSD + + An containing the data - - Unknown, includes object data + + Response message for parcel resource usage - - Maximum bits per second for textures + + URL where parcel resource usage details can be retrieved - - Maximum bits per second for downloaded assets + + URL where parcel resource usage summary can be retrieved - - Maximum bits per second the entire connection, divided up - between invidiual streams using default multipliers + + + Serializes object + + serialized data - + - Send an AgentThrottle packet to the current server using the - current values + Deserializes object from OSD + An containing the data - + - Send an AgentThrottle packet to the specified server using the - current values + Detects which class handles deserialization of this message + An containing the data + Object capable of decoding this message - + + Parcel resource usage + + + Array of containing per percal resource usage + + - Convert the current throttle values to a byte array that can be put - in an AgentThrottle packet + Deserializes object from OSD - Byte array containing all the throttle values + An containing the data - + - Static pre-defined animations available to all agents + Abstract base for rendering plugins - - Agent with afraid expression on face - - - Agent aiming a bazooka (right handed) + + + Generates a basic mesh structure from a primitive + + Primitive to generate the mesh from + Level of detail to generate the mesh at + The generated mesh - - Agent aiming a bow (left handed) + + + Generates a basic mesh structure from a sculpted primitive and + texture + + Sculpted primitive to generate the mesh from + Sculpt texture + Level of detail to generate the mesh at + The generated mesh - - Agent aiming a hand gun (right handed) + + + Generates a series of faces, each face containing a mesh and + metadata + + Primitive to generate the mesh from + Level of detail to generate the mesh at + The generated mesh - - Agent aiming a rifle (right handed) + + + Generates a series of faces for a sculpted prim, each face + containing a mesh and metadata + + Sculpted primitive to generate the mesh from + Sculpt texture + Level of detail to generate the mesh at + The generated mesh - - Agent with angry expression on face + + + Apply texture coordinate modifications from a + to a list of vertices + + Vertex list to modify texture coordinates for + Center-point of the face + Face texture parameters - - Agent hunched over (away) + + + Capability to load TGAs to Bitmap + - - Agent doing a backflip + + + Represents a Wearable Asset, Clothing, Hair, Skin, Etc + - - Agent laughing while holding belly + + A string containing the name of the asset - - Agent blowing a kiss + + A string containing a short description of the asset - - Agent with bored expression on face + + The Assets WearableType - - Agent bowing to audience + + The For-Sale status of the object - - Agent brushing himself/herself off + + An Integer representing the purchase price of the asset - - Agent in busy mode + + The of the assets creator - - Agent clapping hands + + The of the assets current owner - - Agent doing a curtsey bow + + The of the assets prior owner - - Agent crouching + + The of the Group this asset is set to - - Agent crouching while walking + + True if the asset is owned by a - - Agent crying + + The Permissions mask of the asset - - Agent unanimated with arms out (e.g. setting appearance) + + A Dictionary containing Key/Value pairs of the objects parameters - - Agent re-animated after set appearance finished + + A Dictionary containing Key/Value pairs where the Key is the textures Index and the Value is the Textures - - Agent dancing + + Initializes a new instance of an AssetWearable object - - Agent dancing + + Initializes a new instance of an AssetWearable object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - Agent dancing + + + Decode an assets byte encoded data to a string + + true if the asset data was decoded successfully - - Agent dancing + + + Encode the assets string represantion into a format consumable by the asset server + - - Agent dancing + + + The InternalDictionary class is used through the library for storing key/value pairs. + It is intended to be a replacement for the generic Dictionary class and should + be used in its place. It contains several methods for allowing access to the data from + outside the library that are read only and thread safe. + + + Key + Value - - Agent dancing + + Internal dictionary that this class wraps around. Do not + modify or enumerate the contents of this dictionary without locking + on this member - - Agent dancing + + + Initializes a new instance of the Class + with the specified key/value, has the default initial capacity. + + + + // initialize a new InternalDictionary named testDict with a string as the key and an int as the value. + public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(); + + - - Agent dancing + + + Initializes a new instance of the Class + with the specified key/value, has its initial valies copied from the specified + + + + to copy initial values from + + + // initialize a new InternalDictionary named testAvName with a UUID as the key and an string as the value. + // populates with copied values from example KeyNameCache Dictionary. + + // create source dictionary + Dictionary<UUID, string> KeyNameCache = new Dictionary<UUID, string>(); + KeyNameCache.Add("8300f94a-7970-7810-cf2c-fc9aa6cdda24", "Jack Avatar"); + KeyNameCache.Add("27ba1e40-13f7-0708-3e98-5819d780bd62", "Jill Avatar"); + + // Initialize new dictionary. + public InternalDictionary<UUID, string> testAvName = new InternalDictionary<UUID, string>(KeyNameCache); + + - - Agent on ground unanimated + + + Initializes a new instance of the Class + with the specified key/value, With its initial capacity specified. + + Initial size of dictionary + + + // initialize a new InternalDictionary named testDict with a string as the key and an int as the value, + // initially allocated room for 10 entries. + public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(10); + + - - Agent boozing it up + + + Try to get entry from with specified key + + Key to use for lookup + Value returned + if specified key exists, if not found + + + // find your avatar using the Simulator.ObjectsAvatars InternalDictionary: + Avatar av; + if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) + Console.WriteLine("Found Avatar {0}", av.Name); + + + - - Agent with embarassed expression on face + + + Finds the specified match. + + The match. + Matched value + + + // use a delegate to find a prim in the ObjectsPrimitives InternalDictionary + // with the ID 95683496 + uint findID = 95683496; + Primitive findPrim = sim.ObjectsPrimitives.Find( + delegate(Primitive prim) { return prim.ID == findID; }); + + - - Agent with afraid expression on face + + Find All items in an + return matching items. + a containing found items. + + Find All prims within 20 meters and store them in a List + + int radius = 20; + List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( + delegate(Primitive prim) { + Vector3 pos = prim.Position; + return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); + } + ); + + - - Agent with angry expression on face + + Find All items in an + return matching keys. + a containing found keys. + + Find All keys which also exist in another dictionary + + List<UUID> matches = myDict.FindAll( + delegate(UUID id) { + return myOtherDict.ContainsKey(id); + } + ); + + - - Agent with bored expression on face + + Perform an on each entry in an + to perform + + + // Iterates over the ObjectsPrimitives InternalDictionary and prints out some information. + Client.Network.CurrentSim.ObjectsPrimitives.ForEach( + delegate(Primitive prim) + { + if (prim.Text != null) + { + Console.WriteLine("NAME={0} ID = {1} TEXT = '{2}'", + prim.PropertiesFamily.Name, prim.ID, prim.Text); + } + }); + + - - Agent crying + + Perform an on each key of an + to perform - - Agent showing disdain (dislike) for something + + + Perform an on each KeyValuePair of an + + to perform - - Agent with embarassed expression on face + + Check if Key exists in Dictionary + Key to check for + if found, otherwise - - Agent with frowning expression on face + + Check if Value exists in Dictionary + Value to check for + if found, otherwise - - Agent with kissy face + + + Adds the specified key to the dictionary, dictionary locking is not performed, + + + The key + The value - - Agent expressing laughgter - - - Agent with open mouth - - - Agent with repulsed expression on face - - - Agent expressing sadness - - - Agent shrugging shoulders - - - Agent with a smile - - - Agent expressing surprise - - - Agent sticking tongue out + + + Removes the specified key, dictionary locking is not performed + + The key. + if successful, otherwise - - Agent with big toothy smile + + + Gets the number of Key/Value pairs contained in the + - - Agent winking + + + Indexer for the dictionary + + The key + The value - - Agent expressing worry + + + Temporary code to produce a tar archive in tar v7 format + - - Agent falling down + + + Binary writer for the underlying stream + - - Agent walking (feminine version) + + + Write a directory entry to the tar archive. We can only handle one path level right now! + + - - Agent wagging finger (disapproval) + + + Write a file to the tar archive + + + - - I'm not sure I want to know + + + Write a file to the tar archive + + + - - Agent in superman position + + + Finish writing the raw tar archive data to a stream. The stream will be closed on completion. + - - Agent in superman position + + + Write a particular entry + + + + - - Agent greeting another + + + Temporary code to do the bare minimum required to read a tar archive for our purposes + - - Agent holding bazooka (right handed) + + + Binary reader for the underlying stream + - - Agent holding a bow (left handed) + + + Used to trim off null chars + - - Agent holding a handgun (right handed) + + + Used to trim off space chars + - - Agent holding a rifle (right handed) + + + Generate a tar reader which reads from the given stream. + + - - Agent throwing an object (right handed) + + + Read the next entry in the tar file. + + + + the data for the entry. Returns null if there are no more entries - - Agent in static hover + + + Read the next 512 byte chunk of data as a tar header. + + A tar header struct. null if we have reached the end of the archive. - - Agent hovering downward + + + Read data following a header + + + - - Agent hovering upward + + + Convert octal bytes to a decimal representation + + + + + - - Agent being impatient + + + The current status of a texture request as it moves through the pipeline or final result of a texture request. + - - Agent jumping + + The initial state given to a request. Requests in this state + are waiting for an available slot in the pipeline - - Agent jumping with fervor + + A request that has been added to the pipeline and the request packet + has been sent to the simulator - - Agent point to lips then rear end + + A request that has received one or more packets back from the simulator - - Agent landing from jump, finished flight, etc + + A request that has received all packets back from the simulator - - Agent laughing + + A request that has taken longer than + to download OR the initial packet containing the packet information was never received - - Agent landing from jump, finished flight, etc + + The texture request was aborted by request of the agent - - Agent sitting on a motorcycle + + The simulator replied to the request that it was not able to find the requested texture - + + A callback fired to indicate the status or final state of the requested texture. For progressive + downloads this will fire each time new asset data is returned from the simulator. + The indicating either Progress for textures not fully downloaded, + or the final result of the request after it has been processed through the TexturePipeline + The object containing the Assets ID, raw data + and other information. For progressive rendering the will contain + the data from the beginning of the file. For failed, aborted and timed out requests it will contain + an empty byte array. - - Agent moving head side to side - - - Agent moving head side to side with unhappy expression - - - Agent taunting another - - + + Texture request download handler, allows a configurable number of download slots which manage multiple + concurrent texture downloads from the + This class makes full use of the internal + system for full texture downloads. - - Agent giving peace sign - - - Agent pointing at self - - - Agent pointing at another - - - Agent preparing for jump (bending knees) + + A dictionary containing all pending and in-process transfer requests where the Key is both the RequestID + and also the Asset Texture ID, and the value is an object containing the current state of the request and also + the asset data as it is being re-assembled - - Agent punching with left hand + + Holds the reference to the client object - - Agent punching with right hand + + Maximum concurrent texture requests allowed at a time - - Agent acting repulsed + + An array of objects used to manage worker request threads - - Agent trying to be Chuck Norris + + An array of worker slots which shows the availablity status of the slot - - Rocks, Paper, Scissors 1, 2, 3 + + The primary thread which manages the requests. - - Agent with hand flat over other hand + + true if the TexturePipeline is currently running - - Agent with fist over other hand + + A synchronization object used by the primary thread - - Agent with two fingers spread over other hand + + A refresh timer used to increase the priority of stalled requests - - Agent running + + + Default constructor, Instantiates a new copy of the TexturePipeline class + + Reference to the instantiated object - - Agent appearing sad + + + Initialize callbacks required for the TexturePipeline to operate + - - Agent saluting + + + Shutdown the TexturePipeline and cleanup any callbacks or transfers + - - Agent shooting bow (left handed) - - - Agent cupping mouth as if shouting - - - Agent shrugging shoulders - - - Agent in sit position - - - Agent in sit position (feminine) - - - Agent in sit position (generic) - - - Agent sitting on ground - - - Agent sitting on ground - - + + Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + A float indicating the requested priority for the transfer. Higher priority values tell the simulator + to prioritize the request before lower valued requests. An image already being transferred using the can have + its priority changed by resending the request with the new priority value + Number of quality layers to discard. + This controls the end marker of the data sent + The packet number to begin the request at. A value of 0 begins the request + from the start of the asset texture + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + If true, the callback will be fired for each chunk of the downloaded image. + The callback asset parameter will contain all previously received chunks of the texture asset starting + from the beginning of the request - - Agent sleeping on side + + + Sends the actual request packet to the simulator + + The image to download + Type of the image to download, either a baked + avatar texture or a normal texture + Priority level of the download. Default is + 1,013,000.0f + Number of quality layers to discard. + This controls the end marker of the data sent + Packet number to start the download at. + This controls the start marker of the data sent + Sending a priority of 0 and a discardlevel of -1 aborts + download - - Agent smoking + + + Cancel a pending or in process texture request + + The texture assets unique ID - - Agent inhaling smoke + + + Master Download Thread, Queues up downloads in the threadpool + - + + The worker thread that sends the request and handles timeouts + A object containing the request details - - Agent taking a picture + + + Handle responses from the simulator that tell us a texture we have requested is unable to be located + or no longer exists. This will remove the request from the pipeline and free up a slot if one is in use + + The sender + The EventArgs object containing the packet data - - Agent standing + + + Handles the remaining Image data that did not fit in the initial ImageData packet + + The sender + The EventArgs object containing the packet data - - Agent standing up + + + Handle the initial ImageDataPacket sent from the simulator + + The sender + The EventArgs object containing the packet data - - Agent standing + + Current number of pending and in-process transfers - - Agent standing + + + A request task containing information and status of a request as it is processed through the + - - Agent standing + + The current which identifies the current status of the request - - Agent standing + + The Unique Request ID, This is also the Asset ID of the texture being requested - - Agent stretching + + The slot this request is occupying in the threadpoolSlots array - - Agent in stride (fast walk) + + The ImageType of the request. - - Agent surfing + + The callback to fire when the request is complete, will include + the and the + object containing the result data - - Agent acting surprised + + If true, indicates the callback will be fired whenever new data is returned from the simulator. + This is used to progressively render textures as portions of the texture are received. - - Agent striking with a sword + + An object that maintains the data of an request thats in-process. - - Agent talking (lips moving) + + X position of this patch - - Agent throwing a tantrum + + Y position of this patch - - Agent throwing an object (right handed) + + A 16x16 array of floats holding decompressed layer data - - Agent trying on a shirt + + + Creates a LayerData packet for compressed land data given a full + simulator heightmap and an array of indices of patches to compress + + A 256 * 256 array of floating point values + specifying the height at each meter in the simulator + Array of indexes in the 16x16 grid of patches + for this simulator. For example if 1 and 17 are specified, patches + x=1,y=0 and x=1,y=1 are sent + - - Agent turning to the left + + + Add a patch of terrain to a BitPacker + + BitPacker to write the patch to + Heightmap of the simulator, must be a 256 * + 256 float array + X offset of the patch to create, valid values are + from 0 to 15 + Y offset of the patch to create, valid values are + from 0 to 15 - - Agent turning to the right + + + + - - Agent typing + + + + - - Agent walking + + - - Agent whispering + + - - Agent whispering with fingers in mouth + + - - Agent winking + + - - Agent winking + + - - Agent worried + + - - Agent nodding yes + + + + - - Agent nodding yes with happy face + + + + - - Agent floating with legs and arms crossed + + + Initialize the UDP packet handler in server mode + + Port to listening for incoming UDP packets on - + - A dictionary containing all pre-defined animations + Initialize the UDP packet handler in client mode - A dictionary containing the pre-defined animations, - where the key is the animations ID, and the value is a string - containing a name to identify the purpose of the animation + Remote UDP server to connect to - + - Index of TextureEntry slots for avatar appearances + - + - Bake layers for avatar appearance + - + - Default constructor + - A reference to our agent - + - Contains information about a wearable inventory item + Type of return to use when returning objects from a parcel - - Inventory ItemID of the wearable + + - - AssetID of the wearable asset + + Return objects owned by parcel owner - - WearableType of the wearable + + Return objects set to group - - AssetType of the wearable + + Return objects not owned by parcel owner or set to group - - Asset data for the wearable + + Return a specific list of objects on parcel - + + Return objects that are marked for-sale + + - Data collected from visual params for each wearable - needed for the calculation of the color - - - - - Holds a texture assetID and the data needed to bake this layer into - an outfit texture. Used to keep track of currently worn textures - and baking data + Blacklist/Whitelist flags used in parcels Access List - - A texture AssetID - - - Asset data for the texture + + Agent is denied access - - Collection of alpha masks that needs applying + + Agent is granted access - - Tint that should be applied to the texture + + + The result of a request for parcel properties + - - Maximum number of concurrent downloads for wearable assets and textures + + No matches were found for the request - - Maximum number of concurrent uploads for baked textures + + Request matched a single parcel - - Timeout for fetching inventory listings + + Request matched multiple parcels - - Timeout for fetching a single wearable, or receiving a single packet response + + + Flags used in the ParcelAccessListRequest packet to specify whether + we want the access list (whitelist), ban list (blacklist), or both + - - Timeout for fetching a single texture + + Request the access list - - Timeout for uploading a single baked texture + + Request the ban list - - Number of times to retry bake upload + + Request both White and Black lists - - When changing outfit, kick off rebake after - 20 seconds has passed since the last change + + + Sequence ID in ParcelPropertiesReply packets (sent when avatar + tries to cross a parcel border) + - - Total number of wearables for each avatar + + Parcel is currently selected - - Total number of baked textures on each avatar + + Parcel restricted to a group the avatar is not a + member of - - Total number of wearables per bake layer + + Avatar is banned from the parcel - - Total number of textures on an avatar, baked or not + + Parcel is restricted to an access list that the + avatar is not on - - Mapping between BakeType and AvatarTextureIndex + + Response to hovering over a parcel - - Map of what wearables are included in each bake + + + The tool to use when modifying terrain levels + - - Magic values to finalize the cache check hashes for each - bake + + Level the terrain - - Default avatar texture, used to detect when a custom - texture is not set for a face + + Raise the terrain - - The event subscribers. null if no subcribers + + Lower the terrain - - Thread sync lock object + + Smooth the terrain - - The event subscribers. null if no subcribers + + Add random noise to the terrain - - Thread sync lock object + + Revert terrain to simulator default - - The event subscribers. null if no subcribers + + + The tool size to use when changing terrain levels + - - Thread sync lock object + + Small - - The event subscribers. null if no subcribers + + Medium - - Thread sync lock object + + Large - - A cache of wearables currently being worn + + + Reasons agent is denied access to a parcel on the simulator + - - A cache of textures currently being worn + + Agent is not denied, access is granted - - Incrementing serial number for AgentCachedTexture packets + + Agent is not a member of the group set for the parcel, or which owns the parcel - - Incrementing serial number for AgentSetAppearance packets + + Agent is not on the parcels specific allow list - - Indicates whether or not the appearance thread is currently - running, to prevent multiple appearance threads from running - simultaneously + + Agent is on the parcels ban list - - Reference to our agent + + Unknown - - - Timer used for delaying rebake on changing outfit - + + Agent is not age verified and parcel settings deny access to non age verified avatars - + - Main appearance thread + Parcel overlay type. This is used primarily for highlighting and + coloring which is why it is a single integer instead of a set of + flags + These values seem to be poorly thought out. The first three + bits represent a single value, not flags. For example Auction (0x05) is + not a combination of OwnedByOther (0x01) and ForSale(0x04). However, + the BorderWest and BorderSouth values are bit flags that get attached + to the value stored in the first three bits. Bits four, five, and six + are unused - - Triggered when an AgentWearablesUpdate packet is received, - telling us what our avatar is currently wearing - request. + + Public land - - Raised when an AgentCachedTextureResponse packet is - received, giving a list of cached bakes that were found on the - simulator - request. + + Land is owned by another avatar - - - Raised when appearance data is sent to the simulator, also indicates - the main appearance thread is finished. - - request. - - - Triggered when the simulator requests the agent rebake its appearance. - - + + Land is owned by a group - - - Returns true if AppearanceManager is busy and trying to set or change appearance will fail - + + Land is owned by the current avatar - - Raises the AgentWearablesReply event - An AgentWearablesReplyEventArgs object containing the - data returned from the data server + + Land is for sale - - Raises the CachedBakesReply event - An AgentCachedBakesReplyEventArgs object containing the - data returned from the data server AgentCachedTextureResponse + + Land is being auctioned - - Raises the AppearanceSet event - An AppearanceSetEventArgs object indicating if the operatin was successfull + + To the west of this area is a parcel border - - Raises the RebakeAvatarRequested event - An RebakeAvatarTexturesEventArgs object containing the - data returned from the data server + + To the south of this area is a parcel border - + - Obsolete method for setting appearance. This function no longer does anything. - Use RequestSetAppearance() to manually start the appearance thread + Various parcel properties - - - Obsolete method for setting appearance. This function no longer does anything. - Use RequestSetAppearance() to manually start the appearance thread - - Unused parameter + + No flags set - - - Starts the appearance setting thread - + + Allow avatars to fly (a client-side only restriction) - - - Starts the appearance setting thread - - True to force rebaking, otherwise false + + Allow foreign scripts to run - - - Ask the server what textures our agent is currently wearing - + + This parcel is for sale - - - Build hashes out of the texture assetIDs for each baking layer to - ask the simulator whether it has cached copies of each baked texture - + + Allow avatars to create a landmark on this parcel - - - Returns the AssetID of the asset that is currently being worn in a - given WearableType slot - - WearableType slot to get the AssetID for - The UUID of the asset being worn in the given slot, or - UUID.Zero if no wearable is attached to the given slot or wearables - have not been downloaded yet + + Allows all avatars to edit the terrain on this parcel - - - Add a wearable to the current outfit and set appearance - - Wearable to be added to the outfit + + Avatars have health and can take damage on this parcel. + If set, avatars can be killed and sent home here - - - Add a list of wearables to the current outfit and set appearance - - List of wearable inventory items to - be added to the outfit + + Foreign avatars can create objects here - - - Remove a wearable from the current outfit and set appearance - - Wearable to be removed from the outfit + + All objects on this parcel can be purchased - - - Removes a list of wearables from the current outfit and set appearance - - List of wearable inventory items to - be removed from the outfit + + Access is restricted to a group - - - Replace the current outfit with a list of wearables and set appearance - - List of wearable inventory items that - define a new outfit + + Access is restricted to a whitelist - - - Checks if an inventory item is currently being worn - - The inventory item to check against the agent - wearables - The WearableType slot that the item is being worn in, - or WearbleType.Invalid if it is not currently being worn + + Ban blacklist is enabled - - - Returns a copy of the agents currently worn wearables - - A copy of the agents currently worn wearables - Avoid calling this function multiple times as it will make - a copy of all of the wearable data each time + + Unknown - - - Calls either or - depending on the value of - replaceItems - - List of wearable inventory items to add - to the outfit or become a new outfit - True to replace existing items with the - new list of items, false to add these items to the existing outfit + + List this parcel in the search directory - - - Adds a list of attachments to our agent - - A List containing the attachments to add - If true, tells simulator to remove existing attachment - first + + Allow personally owned parcels to be deeded to group - - - Attach an item to our agent at a specific attach point - - A to attach - the on the avatar - to attach the item to + + If Deeded, owner contributes required tier to group parcel is deeded to - - - Attach an item to our agent specifying attachment details - - The of the item to attach - The attachments owner - The name of the attachment - The description of the attahment - The to apply when attached - The of the attachment - The on the agent - to attach the item to + + Restrict sounds originating on this parcel to the + parcel boundaries - - - Detach an item from our agent using an object - - An object + + Objects on this parcel are sold when the land is + purchsaed - - - Detach an item from our agent - - The inventory itemID of the item to detach + + Allow this parcel to be published on the web - - - Inform the sim which wearables are part of our current outfit - + + The information for this parcel is mature content - - - Replaces the Wearables collection with a list of new wearable items - - Wearable items to replace the Wearables collection with + + The media URL is an HTML page - - - Calculates base color/tint for a specific wearable - based on its params - - All the color info gathered from wearable's VisualParams - passed as list of ColorParamInfo tuples - Base color/tint for the wearable + + The media URL is a raw HTML string - - - Blocking method to populate the Wearables dictionary - - True on success, otherwise false + + Restrict foreign object pushes - - - Blocking method to populate the Textures array with cached bakes - - True on success, otherwise false + + Ban all non identified/transacted avatars - - - Populates textures and visual params from a decoded asset - - Wearable to decode + + Allow group-owned scripts to run - - - Blocking method to download and parse currently worn wearable assets - - True on success, otherwise false + + Allow object creation by group members or group + objects - - - Get a list of all of the textures that need to be downloaded for a - single bake layer - - Bake layer to get texture AssetIDs for - A list of texture AssetIDs to download + + Allow all objects to enter this parcel - - - Helper method to lookup the TextureID for a single layer and add it - to a list if it is not already present - - - - - + + Only allow group and owner objects to enter this parcel - - - Blocking method to download all of the textures needed for baking - the given bake layers - - A list of layers that need baking - No return value is given because the baking will happen - whether or not all textures are successfully downloaded + + Voice Enabled on this parcel - - - Blocking method to create and upload baked textures for all of the - missing bakes - - True on success, otherwise false + + Use Estate Voice channel for Voice on this parcel - - - Blocking method to create and upload a baked texture for a single - bake layer - - Layer to bake - True on success, otherwise false + + Deny Age Unverified Users - + - Blocking method to upload a baked texture + Parcel ownership status - Five channel JPEG2000 texture data to upload - UUID of the newly created asset on success, otherwise UUID.Zero - - - Creates a dictionary of visual param values from the downloaded wearables - - A dictionary of visual param indices mapping to visual param - values for our agent that can be fed to the Baker class + + Placeholder - - - Create an AgentSetAppearance packet from Wearables data and the - Textures array and send it - + + Parcel is leased (owned) by an avatar or group - + + Parcel is in process of being leased (purchased) by an avatar or group + + + Parcel has been abandoned back to Governor Linden + + - Converts a WearableType to a bodypart or clothing WearableType + Category parcel is listed in under search - A WearableType - AssetType.Bodypart or AssetType.Clothing or AssetType.Unknown - - - Converts a BakeType to the corresponding baked texture slot in AvatarTextureIndex - - A BakeType - The AvatarTextureIndex slot that holds the given BakeType + + No assigned category - - - Gives the layer number that is used for morph mask - - >A BakeType - Which layer number as defined in BakeTypeToTextures is used for morph mask + + Linden Infohub or public area - - - Converts a BakeType to a list of the texture slots that make up that bake - - A BakeType - A list of texture slots that are inputs for the given bake + + Adult themed area - - Contains the Event data returned from the data server from an AgentWearablesRequest + + Arts and Culture - - Construct a new instance of the AgentWearablesReplyEventArgs class + + Business - - Contains the Event data returned from the data server from an AgentCachedTextureResponse + + Educational - - Construct a new instance of the AgentCachedBakesReplyEventArgs class + + Gaming - - Contains the Event data returned from an AppearanceSetRequest + + Hangout or Club - - - Triggered when appearance data is sent to the sim and - the main appearance thread is done. - Indicates whether appearance setting was successful + + Newcomer friendly - - Indicates whether appearance setting was successful + + Parks and Nature - - Contains the Event data returned from the data server from an RebakeAvatarTextures + + Residential - - - Triggered when the simulator sends a request for this agent to rebake - its appearance - - The ID of the Texture Layer to bake + + Shopping - - The ID of the Texture Layer to bake + + Not Used? - - - Class that handles the local asset cache - + + Other - - - Default constructor - - A reference to the GridClient object + + Not an actual category, only used for queries - + - Helper class for sorting files by their last accessed time + Type of teleport landing for a parcel - - - Allows setting weather to periodicale prune the cache if it grows too big - Default is enabled, when caching is enabled - + + Unset, simulator default - - - How long (in ms) between cache checks (default is 5 min.) - + + Specific landing point set for this parcel - - - Disposes cleanup timer - + + No landing point set, direct teleports enabled for + this parcel - + - Only create timer when needed + Parcel Media Command used in ParcelMediaCommandMessage - - - Return bytes read from the local asset cache, null if it does not exist - - UUID of the asset we want to get - Raw bytes of the asset, or null on failure + + Stop the media stream and go back to the first frame - - - Returns ImageDownload object of the - image from the local image cache, null if it does not exist - - UUID of the image we want to get - ImageDownload object containing the image, or null on failure + + Pause the media stream (stop playing but stay on current frame) - - - Constructs a file name of the cached asset - - UUID of the asset - String with the file name of the cahced asset + + Start the current media stream playing and stop when the end is reached - - - Saves an asset to the local cache - - UUID of the asset - Raw bytes the asset consists of - Weather the operation was successfull + + Start the current media stream playing, + loop to the beginning when the end is reached and continue to play - - - Get the file name of the asset stored with gived UUID - - UUID of the asset - Null if we don't have that UUID cached on disk, file name if found in the cache folder + + Specifies the texture to replace with video + If passing the key of a texture, it must be explicitly typecast as a key, + not just passed within double quotes. - - - Checks if the asset exists in the local cache - - UUID of the asset - True is the asset is stored in the cache, otherwise false + + Specifies the movie URL (254 characters max) - - - Wipes out entire cache - + + Specifies the time index at which to begin playing - - - Brings cache size to the 90% of the max size - + + Specifies a single agent to apply the media command to - - - Asynchronously brings cache size to the 90% of the max size - + + Unloads the stream. While the stop command sets the texture to the first frame of the movie, + unload resets it to the real texture that the movie was replacing. - - - Adds up file sizes passes in a FileInfo array - + + Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties + (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter. - - - Checks whether caching is enabled - + + Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only). + Use "text/html" for HTML. - - - Periodically prune the cache - + + Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only). + This might still not be working - - - Nicely formats file sizes - - Byte size we want to output - String with humanly readable file size + + Sets a description for the media being displayed (1.19.1 RC0 and later only). - + + Some information about a parcel of land returned from a DirectoryManager search - - OK + + Global Key of record - - Transfer completed + + Parcel Owners - - - + + Name field of parcel, limited to 128 characters - - - + + Description field of parcel, limited to 256 characters - - Unknown error occurred + + Total Square meters of parcel - - Equivalent to a 404 error + + Total area billable as Tier, for group owned land this will be 10% less than ActualArea - - Client does not have permission for that resource + + True of parcel is in Mature simulator - - Unknown status + + Grid global X position of parcel - - - + + Grid global Y position of parcel - - - + + Grid global Z position of parcel (not used) - - Unknown + + Name of simulator parcel is located in - - Virtually all asset transfers use this channel + + Texture of parcels display picture - - - + + Float representing calculated traffic based on time spent on parcel by avatars - + + Sale price of parcel (not used) + + + Auction ID of parcel + + + Parcel Media Information - - Asset from the asset server + + A byte, if 0x1 viewer should auto scale media to fit object - - Inventory item + + A boolean, if true the viewer should loop the media - - Estate asset, such as an estate covenant + + The Asset UUID of the Texture which when applied to a + primitive will display the media - - - + + A URL which points to any Quicktime supported media type - - - + + A description of the media - - - + + An Integer which represents the height of the media - - - + + An integer which represents the width of the media - - - + + A string which contains the mime type of the media - + + Parcel of land, a portion of virtual real estate in a simulator - - - + + The total number of contiguous 4x4 meter blocks your agent owns within this parcel - - - Image file format - + + The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own - - - + + Deprecated, Value appears to always be 0 - - Number of milliseconds passed since the last transfer - packet was received + + Simulator-local ID of this parcel - - - + + UUID of the owner of this parcel - - - + + Whether the land is deeded to a group or not - - - + + - - - + + Date land was claimed - - - + + Appears to always be zero - - - - - - - - - - - + + This field is no longer used - - - + + Minimum corner of the axis-aligned bounding box for this + parcel - - - Default constructor - - A reference to the GridClient object + + Maximum corner of the axis-aligned bounding box for this + parcel - - - Callback used for various asset download requests - - Transfer information - Downloaded asset, null on fail + + Bitmap describing land layout in 4x4m squares across the + entire region - - - Callback used upon competition of baked texture upload - - Asset UUID of the newly uploaded baked texture + + Total parcel land area - - Number of milliseconds to wait for a transfer header packet if out of order data was received + + - - The event subscribers. null if no subcribers + + Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used - - Thread sync lock object + + Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel + owned by the agent or group that owns this parcel - - The event subscribers. null if no subcribers + + Maximum number of primitives this parcel supports - - Thread sync lock object + + Total number of primitives on this parcel - - The event subscribers. null if no subcribers + + For group-owned parcels this indicates the total number of prims deeded to the group, + for parcels owned by an individual this inicates the number of prims owned by the individual - - Thread sync lock object + + Total number of primitives owned by the parcel group on + this parcel, or for parcels owned by an individual with a group set the + total number of prims set to that group. - - The event subscribers. null if no subcribers + + Total number of prims owned by other avatars that are not set to group, or not the parcel owner - - Thread sync lock object + + A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect + the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed - - The event subscribers. null if no subcribers + + Autoreturn value in minutes for others' objects - - Thread sync lock object + + - - Texture download cache + + Sale price of the parcel, only useful if ForSale is set + The SalePrice will remain the same after an ownership + transfer (sale), so it can be used to see the purchase price after + a sale if the new owner has not changed it - - Raised when the simulator responds sends + + Parcel Name - - Raised during upload completes + + Parcel Description - - Raised during upload with progres update + + URL For Music Stream - - Fired when the simulator sends an InitiateDownloadPacket, used to download terrain .raw files + + - - Fired when a texture is in the process of being downloaded by the TexturePipeline class + + Price for a temporary pass - - Raises the XferReceived event - A XferReceivedEventArgs object containing the - data returned from the simulator + + How long is pass valid for - - Raises the AssetUploaded event - A AssetUploadedEventArgs object containing the - data returned from the simulator + + - - Raises the UploadProgress event - A UploadProgressEventArgs object containing the - data returned from the simulator + + Key of authorized buyer - - Raises the InitiateDownload event - A InitiateDownloadEventArgs object containing the - data returned from the simulator + + Key of parcel snapshot - - Raises the ImageReceiveProgress event - A ImageReceiveProgressEventArgs object containing the - data returned from the simulator + + The landing point location - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - The callback to fire when the simulator responds with the asset data + + The landing point LookAt - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - The callback to fire when the simulator responds with the asset data + + The type of landing enforced from the enum - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - UUID of the transaction - The callback to fire when the simulator responds with the asset data + + - - - Request an asset download through the almost deprecated Xfer system - - Filename of the asset to request - Whether or not to delete the asset - off the server after it is retrieved - Use large transfer packets or not - UUID of the file to request, if filename is - left empty - Asset type of vFileID, or - AssetType.Unknown if filename is not empty - Sets the FilePath in the request to Cache - (4) if true, otherwise Unknown (0) is used - - + + - - - - Use UUID.Zero if you do not have the - asset ID but have all the necessary permissions - The item ID of this asset in the inventory - Use UUID.Zero if you are not requesting an - asset from an object inventory - The owner of this asset - Asset type - Whether to prioritize this asset download or not - - + + - - - Used to force asset data into the PendingUpload property, ie: for raw terrain uploads - - An AssetUpload object containing the data to upload to the simulator + + Access list of who is whitelisted on this + parcel - - - Request an asset be uploaded to the simulator - - The Object containing the asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired + + Access list of who is blacklisted on this + parcel - - - Request an asset be uploaded to the simulator - - The of the asset being uploaded - A byte array containing the encoded asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired + + TRUE of region denies access to age unverified users - - - Request an asset be uploaded to the simulator - - - - Asset type to upload this data as - A byte array containing the encoded asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired + + true to obscure (hide) media url - - - Initiate an asset upload - - The ID this asset will have if the - upload succeeds - Asset type to upload this data as - Raw asset data to upload - Whether to store this asset on the local - simulator or the grid-wide asset server - The tranaction id for the upload - The transaction ID of this transfer + + true to obscure (hide) music url - - - Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - A float indicating the requested priority for the transfer. Higher priority values tell the simulator - to prioritize the request before lower valued requests. An image already being transferred using the can have - its priority changed by resending the request with the new priority value - Number of quality layers to discard. - This controls the end marker of the data sent. Sending with value -1 combined with priority of 0 cancels an in-progress - transfer. - A bug exists in the Linden Simulator where a -1 will occasionally be sent with a non-zero priority - indicating an off-by-one error. - The packet number to begin the request at. A value of 0 begins the request - from the start of the asset texture - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request - - Request an image and fire a callback when the request is complete - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); - private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", - asset.AssetID, - asset.AssetData.Length); - } - } - - Request an image and use an inline anonymous method to handle the downloaded texture data - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, delegate(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", - asset.AssetID, - asset.AssetData.Length); - } - } - ); - - Request a texture, decode the texture to a bitmap image and apply it to a imagebox - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); - private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - ManagedImage imgData; - Image bitmap; - if (state == TextureRequestState.Finished) - { - OpenJPEG.DecodeToImage(assetTexture.AssetData, out imgData, out bitmap); - picInsignia.Image = bitmap; - } - } - } - + + A struct containing media details - + - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator + Displays a parcel object in string format - The of the texture asset to download - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data + string containing key=value pairs of a parcel object - + - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator + Defalt constructor - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data + Local ID of this parcel - + - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator + Update the simulator with any local changes to this Parcel object - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request + Simulator to send updates to + Whether we want the simulator to confirm + the update with a reply packet or not - + - Cancel a texture request + Set Autoreturn time - The texture assets + Simulator to send the update to - + - Lets TexturePipeline class fire the progress event + Parcel (subdivided simulator lots) subsystem - The texture ID currently being downloaded - the number of bytes transferred - the total number of bytes expected - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The event subscribers. null if no subcribers - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Raises the ParcelDwellReply event + A ParcelDwellReplyEventArgs object containing the + data returned from the simulator - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Thread sync lock object - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The event subscribers. null if no subcribers - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Raises the ParcelInfoReply event + A ParcelInfoReplyEventArgs object containing the + data returned from the simulator - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Thread sync lock object - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The event subscribers. null if no subcribers - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Raises the ParcelProperties event + A ParcelPropertiesEventArgs object containing the + data returned from the simulator - - Xfer data + + Thread sync lock object - - Upload data + + The event subscribers. null if no subcribers - - Filename used on the simulator + + Raises the ParcelAccessListReply event + A ParcelAccessListReplyEventArgs object containing the + data returned from the simulator - - Filename used by the client + + Thread sync lock object - - UUID of the image that is in progress + + The event subscribers. null if no subcribers - - Number of bytes received so far + + Raises the ParcelObjectOwnersReply event + A ParcelObjectOwnersReplyEventArgs object containing the + data returned from the simulator - - Image size in bytes + + Thread sync lock object - - - Avatar profile flags - + + The event subscribers. null if no subcribers - - - Represents an avatar (other than your own) - + + Raises the SimParcelsDownloaded event + A SimParcelsDownloadedEventArgs object containing the + data returned from the simulator - - - Default constructor - + + Thread sync lock object - - - Positive and negative ratings - + + The event subscribers. null if no subcribers - - Positive ratings for Behavior + + Raises the ForceSelectObjectsReply event + A ForceSelectObjectsReplyEventArgs object containing the + data returned from the simulator - - Negative ratings for Behavior + + Thread sync lock object - - Positive ratings for Appearance + + The event subscribers. null if no subcribers - - Negative ratings for Appearance + + Raises the ParcelMediaUpdateReply event + A ParcelMediaUpdateReplyEventArgs object containing the + data returned from the simulator - - Positive ratings for Building + + Thread sync lock object - - Negative ratings for Building + + The event subscribers. null if no subcribers - - Positive ratings given by this avatar + + Raises the ParcelMediaCommand event + A ParcelMediaCommandEventArgs object containing the + data returned from the simulator - - Negative ratings given by this avatar + + Thread sync lock object - + - Avatar properties including about text, profile URL, image IDs and - publishing settings + Default constructor + A reference to the GridClient object - - First Life about text - - - First Life image ID - - + + Request basic information for a single parcel + Simulator-local ID of the parcel - + + Request properties of a single parcel + Simulator containing the parcel + Simulator-local ID of the parcel + An arbitrary integer that will be returned + with the ParcelProperties reply, useful for distinguishing between + multiple simultaneous requests - + + Request the access list for a single parcel + Simulator containing the parcel + Simulator-local ID of the parcel + An arbitrary integer that will be returned + with the ParcelAccessList reply, useful for distinguishing between + multiple simultaneous requests + - + + Request properties of parcels using a bounding box selection + Simulator containing the parcel + Northern boundary of the parcel selection + Eastern boundary of the parcel selection + Southern boundary of the parcel selection + Western boundary of the parcel selection + An arbitrary integer that will be returned + with the ParcelProperties reply, useful for distinguishing between + different types of parcel property requests + A boolean that is returned with the + ParcelProperties reply, useful for snapping focus to a single + parcel - - Profile image ID - - - Flags of the profile - - - Web URL for this profile - - - Should this profile be published on the web - - - Avatar Online Status - - - Is this a mature profile - - + + Request all simulator parcel properties (used for populating the Simulator.Parcels + dictionary) + Simulator to request parcels from (must be connected) - + + Request all simulator parcel properties (used for populating the Simulator.Parcels + dictionary) + Simulator to request parcels from (must be connected) + If TRUE, will force a full refresh + Number of milliseconds to pause in between each request - + - Avatar interests including spoken languages, skills, and "want to" - choices + Request the dwell value for a parcel + Simulator containing the parcel + Simulator-local ID of the parcel - - Languages profile field - - + + Send a request to Purchase a parcel of land + The Simulator the parcel is located in + The parcels region specific local ID + true if this parcel is being purchased by a group + The groups + true to remove tier contribution if purchase is successful + The parcels size + The purchase price of the parcel + - + + Reclaim a parcel of land + The simulator the parcel is in + The parcels region specific local ID - + + Deed a parcel to a group + The simulator the parcel is in + The parcels region specific local ID + The groups - + + Request prim owners of a parcel of land. + Simulator parcel is in + The parcels region specific local ID - - Groups that this avatar is a member of - - - Positive and negative ratings - - - Avatar properties including about text, profile URL, image IDs and - publishing settings - - - Avatar interests including spoken languages, skills, and "want to" - choices - - - Movement control flags for avatars. Typically not set or used by - clients. To move your avatar, use Client.Self.Movement instead - - + - Contains the visual parameters describing the deformation of the avatar + Return objects from a parcel + Simulator parcel is in + The parcels region specific local ID + the type of objects to return, + A list containing object owners s to return - - First name - - - Last name - - - Full name - - - Active group - - + - Holds group information for Avatars such as those you might find in a profile + Subdivide (split) a parcel + + + + + - - true of Avatar accepts group notices - - - Groups Key - - - Texture Key for groups insignia - - - Name of the group - - - Powers avatar has in the group - - - Avatars Currently selected title - - - true of Avatar has chosen to list this in their profile - - + - Contains an animation currently being played by an agent + Join two parcels of land creating a single parcel + + + + + - - The ID of the animation asset - - - A number to indicate start order of currently playing animations - On Linden Grids this number is unique per region, with OpenSim it is per client - - + + Get a parcels LocalID + Simulator parcel is in + Vector3 position in simulator (Z not used) + 0 on failure, or parcel LocalID on success. + A call to Parcels.RequestAllSimParcels is required to populate map and + dictionary. - + - Holds group information on an individual profile pick + Terraform (raise, lower, etc) an area or whole parcel of land + Simulator land area is in. + LocalID of parcel, or -1 if using bounding box + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + true on successful request sent. + Settings.STORE_LAND_PATCHES must be true, + Parcel information must be downloaded using RequestAllSimParcels() - + - Retrieve friend status notifications, and retrieve avatar names and - profiles + Terraform (raise, lower, etc) an area or whole parcel of land + Simulator land area is in. + west border of area to modify + south border of area to modify + east border of area to modify + north border of area to modify + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + true on successful request sent. + Settings.STORE_LAND_PATCHES must be true, + Parcel information must be downloaded using RequestAllSimParcels() - + - Represents other avatars + Terraform (raise, lower, etc) an area or whole parcel of land - - + Simulator land area is in. + LocalID of parcel, or -1 if using bounding box + west border of area to modify + south border of area to modify + east border of area to modify + north border of area to modify + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + How many meters + or - to lower, 1 = 1 meter + true on successful request sent. + Settings.STORE_LAND_PATCHES must be true, + Parcel information must be downloaded using RequestAllSimParcels() - - The event subscribers, null of no subscribers + + + Terraform (raise, lower, etc) an area or whole parcel of land + + Simulator land area is in. + LocalID of parcel, or -1 if using bounding box + west border of area to modify + south border of area to modify + east border of area to modify + north border of area to modify + From Enum, Raise, Lower, Level, Smooth, Etc. + Size of area to modify + How many meters + or - to lower, 1 = 1 meter + Height at which the terraform operation is acting at - - Thread sync lock object + + + Sends a request to the simulator to return a list of objects owned by specific owners + + Simulator local ID of parcel + Owners, Others, Etc + List containing keys of avatars objects to select; + if List is null will return Objects of type selectType + Response data is returned in the event - - The event subscribers, null of no subscribers + + + Eject and optionally ban a user from a parcel + + target key of avatar to eject + true to also ban target - - Thread sync lock object + + + Freeze or unfreeze an avatar over your land + + target key to freeze + true to freeze, false to unfreeze - - The event subscribers, null of no subscribers + + + Abandon a parcel of land + + Simulator parcel is in + Simulator local ID of parcel - - Thread sync lock object + + + Requests the UUID of the parcel in a remote region at a specified location + + Location of the parcel in the remote region + Remote region handle + Remote region UUID + If successful UUID of the remote parcel, UUID.Zero otherwise - - The event subscribers, null of no subscribers + + + Retrieves information on resources used by the parcel + + UUID of the parcel + Should per object resource usage be requested + Callback invoked when the request is complete - - Thread sync lock object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - The event subscribers, null of no subscribers + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - Thread sync lock object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - The event subscribers, null of no subscribers + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - Thread sync lock object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - The event subscribers, null of no subscribers + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Thread sync lock object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + Raises the event - - The event subscribers, null of no subscribers + + Raised when the simulator responds to a request - - Thread sync lock object + + Raised when the simulator responds to a request - - The event subscribers, null of no subscribers + + Raised when the simulator responds to a request - - Thread sync lock object + + Raised when the simulator responds to a request - - The event subscribers, null of no subscribers + + Raised when the simulator responds to a request - - Thread sync lock object + + Raised when the simulator responds to a request - - The event subscribers, null of no subscribers + + Raised when the simulator responds to a request - - Thread sync lock object + + Raised when the simulator responds to a Parcel Update request - - The event subscribers, null of no subscribers + + Raised when the parcel your agent is located sends a ParcelMediaCommand - - Thread sync lock object + + + Parcel Accesslist + - - The event subscribers, null of no subscribers + + Agents - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + Flags for specific entry in white/black lists - - Thread sync lock object + + + Owners of primitives on parcel + - - Raised when the simulator sends us data containing - an agents animation playlist + + Prim Owners - - Raised when the simulator sends us data containing - the appearance information for an agent + + True of owner is group - - Raised when the simulator sends us data containing - agent names/id values + + Total count of prims owned by OwnerID - - Raised when the simulator sends us data containing - the interests listed in an agents profile + + true of OwnerID is currently online and is not a group - - Raised when the simulator sends us data containing - profile property information for an agent + + The date of the most recent prim left by OwnerID - - Raised when the simulator sends us data containing - the group membership an agent is a member of + + + Called once parcel resource usage information has been collected + + Indicates if operation was successfull + Parcel resource usage information - - Raised when the simulator sends us data containing - name/id pair + + Contains a parcels dwell data returned from the simulator in response to an - - Raised when the simulator sends us data containing - the objects and effect when an agent is pointing at + + + Construct a new instance of the ParcelDwellReplyEventArgs class + + The global ID of the parcel + The simulator specific ID of the parcel + The calculated dwell for the parcel - - Raised when the simulator sends us data containing - the objects and effect when an agent is looking at + + Get the global ID of the parcel - - Raised when the simulator sends us data containing - an agents viewer effect information + + Get the simulator specific ID of the parcel - - Raised when the simulator sends us data containing - the top picks from an agents profile + + Get the calculated dwell - - Raised when the simulator sends us data containing - the Pick details + + Contains basic parcel information data returned from the + simulator in response to an request - - Raised when the simulator sends us data containing - the classified ads an agent has placed + + + Construct a new instance of the ParcelInfoReplyEventArgs class + + The object containing basic parcel info - - Raised when the simulator sends us data containing - the details of a classified ad + + Get the object containing basic parcel info - - Raises the AvatarAnimation Event - An AvatarAnimationEventArgs object containing - the data sent from the simulator + + Contains basic parcel information data returned from the simulator in response to an request - - Raises the AvatarAppearance Event - A AvatarAppearanceEventArgs object containing - the data sent from the simulator + + + Construct a new instance of the ParcelPropertiesEventArgs class + + The object containing the details + The object containing the details + The result of the request + The number of primitieves your agent is + currently selecting and or sitting on in this parcel + The user assigned ID used to correlate a request with + these results + TODO: - - Raises the UUIDNameReply Event - A UUIDNameReplyEventArgs object containing - the data sent from the simulator + + Get the simulator the parcel is located in - - Raises the AvatarInterestsReply Event - A AvatarInterestsReplyEventArgs object containing - the data sent from the simulator + + Get the object containing the details + If Result is NoData, this object will not contain valid data - - Raises the AvatarPropertiesReply Event - A AvatarPropertiesReplyEventArgs object containing - the data sent from the simulator + + Get the result of the request - - Raises the AvatarGroupsReply Event - A AvatarGroupsReplyEventArgs object containing - the data sent from the simulator + + Get the number of primitieves your agent is + currently selecting and or sitting on in this parcel - - Raises the AvatarPickerReply Event - A AvatarPickerReplyEventArgs object containing - the data sent from the simulator + + Get the user assigned ID used to correlate a request with + these results - - Raises the ViewerEffectPointAt Event - A ViewerEffectPointAtEventArgs object containing - the data sent from the simulator + + TODO: - - Raises the ViewerEffectLookAt Event - A ViewerEffectLookAtEventArgs object containing - the data sent from the simulator + + Contains blacklist and whitelist data returned from the simulator in response to an request - - Raises the ViewerEffect Event - A ViewerEffectEventArgs object containing - the data sent from the simulator + + + Construct a new instance of the ParcelAccessListReplyEventArgs class + + The simulator the parcel is located in + The user assigned ID used to correlate a request with + these results + The simulator specific ID of the parcel + TODO: + The list containing the white/blacklisted agents for the parcel - - Raises the AvatarPicksReply Event - A AvatarPicksReplyEventArgs object containing - the data sent from the simulator + + Get the simulator the parcel is located in - - Raises the PickInfoReply Event - A PickInfoReplyEventArgs object containing - the data sent from the simulator + + Get the user assigned ID used to correlate a request with + these results - - Raises the AvatarClassifiedReply Event - A AvatarClassifiedReplyEventArgs object containing - the data sent from the simulator + + Get the simulator specific ID of the parcel - - Raises the ClassifiedInfoReply Event - A ClassifiedInfoReplyEventArgs object containing - the data sent from the simulator + + TODO: - - Tracks the specified avatar on your map - Avatar ID to track + + Get the list containing the white/blacklisted agents for the parcel - - - Request a single avatar name - - The avatar key to retrieve a name for + + Contains blacklist and whitelist data returned from the + simulator in response to an request - + - Request a list of avatar names + Construct a new instance of the ParcelObjectOwnersReplyEventArgs class - The avatar keys to retrieve names for + The simulator the parcel is located in + The list containing prim ownership counts - - - Start a request for Avatar Properties - - - + + Get the simulator the parcel is located in - - - Search for an avatar (first name, last name) - - The name to search for - An ID to associate with this query + + Get the list containing prim ownership counts - + + Contains the data returned when all parcel data has been retrieved from a simulator + + - Start a request for Avatar Picks + Construct a new instance of the SimParcelsDownloadedEventArgs class - UUID of the avatar + The simulator the parcel data was retrieved from + The dictionary containing the parcel data + The multidimensional array containing a x,y grid mapped + to each 64x64 parcel's LocalID. - + + Get the simulator the parcel data was retrieved from + + + A dictionary containing the parcel data where the key correlates to the ParcelMap entry + + + Get the multidimensional array containing a x,y grid mapped + to each 64x64 parcel's LocalID. + + + Contains the data returned when a request + + - Start a request for Avatar Classifieds + Construct a new instance of the ForceSelectObjectsReplyEventArgs class - UUID of the avatar + The simulator the parcel data was retrieved from + The list of primitive IDs + true if the list is clean and contains the information + only for a given request - + + Get the simulator the parcel data was retrieved from + + + Get the list of primitive IDs + + + true if the list is clean and contains the information + only for a given request + + + Contains data when the media data for a parcel the avatar is on changes + + - Start a request for details of a specific profile pick + Construct a new instance of the ParcelMediaUpdateReplyEventArgs class - UUID of the avatar - UUID of the profile pick + the simulator the parcel media data was updated in + The updated media information - + + Get the simulator the parcel media data was updated in + + + Get the updated media information + + + Contains the media command for a parcel the agent is currently on + + - Start a request for details of a specific profile classified + Construct a new instance of the ParcelMediaCommandEventArgs class - UUID of the avatar - UUID of the profile classified + The simulator the parcel media command was issued in + + + The media command that was sent + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Get the simulator the parcel media command was issued in - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Get the media command that was sent - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - + - Crossed region handler for message that comes across the EventQueue. Sent to an agent - when the agent crosses a sim border into a new region. + Singleton logging class for the entire library - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + log4net logging engine - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Default constructor + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Send a log message to the logging engine + + The log message + The severity of the log entry - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Send a log message to the logging engine + + The log message + The severity of the log entry + Instance of the client - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Send a log message to the logging engine + + The log message + The severity of the log entry + Exception that was raised - - Provides data for the event - The event occurs when the simulator sends - the animation playlist for an agent - - The following code example uses the and - properties to display the animation playlist of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAnimation += Avatars_AvatarAnimation; - private void Avatars_AvatarAnimation(object sender, AvatarAnimationEventArgs e) - { - // create a dictionary of "known" animations from the Animations class using System.Reflection - Dictionary<UUID, string> systemAnimations = new Dictionary<UUID, string>(); - Type type = typeof(Animations); - System.Reflection.FieldInfo[] fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); - foreach (System.Reflection.FieldInfo field in fields) - { - systemAnimations.Add((UUID)field.GetValue(type), field.Name); - } - // find out which animations being played are known animations and which are assets - foreach (Animation animation in e.Animations) - { - if (systemAnimations.ContainsKey(animation.AnimationID)) - { - Console.WriteLine("{0} is playing {1} ({2}) sequence {3}", e.AvatarID, - systemAnimations[animation.AnimationID], animation.AnimationSequence); - } - else - { - Console.WriteLine("{0} is playing {1} (Asset) sequence {2}", e.AvatarID, - animation.AnimationID, animation.AnimationSequence); - } - } - } - + + + Send a log message to the logging engine + + The log message + The severity of the log entry + Instance of the client + Exception that was raised - + - Construct a new instance of the AvatarAnimationEventArgs class + If the library is compiled with DEBUG defined, an event will be + fired if an OnLogMessage handler is registered and the + message will be sent to the logging engine - The ID of the agent - The list of animations to start + The message to log at the DEBUG level to the + current logging engine - - Get the ID of the agent + + + If the library is compiled with DEBUG defined and + GridClient.Settings.DEBUG is true, an event will be + fired if an OnLogMessage handler is registered and the + message will be sent to the logging engine + + The message to log at the DEBUG level to the + current logging engine + Instance of the client - - Get the list of animations to start + + Triggered whenever a message is logged. If this is left + null, log messages will go to the console - - Provides data for the event - The event occurs when the simulator sends - the appearance data for an avatar - - The following code example uses the and - properties to display the selected shape of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; - // handle the data when the event is raised - void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) - { - Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") - } - + + + Callback used for client apps to receive log messages from + the library + + Data being logged + The severity of the log entry from - + - Construct a new instance of the AvatarAppearanceEventArgs class + Map layer request type - The simulator request was from - The ID of the agent - true of the agent is a trial account - The default agent texture - The agents appearance layer textures - The for the agent - - Get the Simulator this request is from of the agent + + Objects and terrain are shown - - Get the ID of the agent + + Only the terrain is shown, no objects - - true if the agent is a trial account + + Overlay showing land for sale and for auction - - Get the default agent texture + + + Type of grid item, such as telehub, event, populator location, etc. + - - Get the agents appearance layer textures + + Telehub - - Get the for the agent + + PG rated event - - Represents the interests from the profile of an agent + + Mature rated event - - Get the ID of the agent + + Popular location - - The properties of an agent + + Locations of avatar groups in a region - - Get the ID of the agent + + Land for sale - - Get the ID of the agent + + Classified ad - - Get the ID of the agent + + Adult rated event - - Get the ID of the avatar + + Adult land for sale - + - Reads in a byte array of an Animation Asset created by the SecondLife(tm) client. + Information about a region on the grid map - - - Searialize an animation asset into it's joints/keyframes/meta data - - - + + Sim X position on World Map - - - Rotation Keyframe count (used internally) - + + Sim Y position on World Map - - - Position Keyframe count (used internally) - + + Sim Name (NOTE: In lowercase!) - - - Animation Priority - + + - + + Appears to always be zero (None) + + + Sim's defined Water Height + + + + + + UUID of the World Map image + + + Unique identifier for this region, a combination of the X + and Y position + + - The animation length in seconds. + + - + - Expression set in the client. Null if [None] is selected + + - + - The time in seconds to start the animation + + + - + - The time in seconds to end the animation + Visual chunk of the grid map - + - Loop the animation + Base class for Map Items - + + The Global X position of the item + + + The Global Y position of the item + + + Get the Local X position of the item + + + Get the Local Y position of the item + + + Get the Handle of the region + + - Meta data. Ease in Seconds. + Represents an agent or group of agents location - + - Meta data. Ease out seconds. + Represents a Telehub location - + - Meta Data for the Hand Pose + Represents a non-adult parcel of land for sale - + - Number of joints defined in the animation + Represents an Adult parcel of land for sale - + - Contains an array of joints + Represents a PG Event - + - Variable length strings seem to be null terminated in the animation asset.. but.. - use with caution, home grown. - advances the index. + Represents a Mature event - The animation asset byte array - The offset to start reading - a string - + - Read in a Joint from an animation asset byte array - Variable length Joint fields, yay! - Advances the index + Represents an Adult event - animation asset byte array - Byte Offset of the start of the joint - The Joint data serialized into the binBVHJoint structure - + - Read Keyframes of a certain type - advance i + Manages grid-wide tasks such as the world map - Animation Byte array - Offset in the Byte Array. Will be advanced - Number of Keyframes - Scaling Min to pass to the Uint16ToFloat method - Scaling Max to pass to the Uint16ToFloat method - - - - - A Joint and it's associated meta data and keyframes - + + The event subscribers. null if no subcribers - - - Name of the Joint. Matches the avatar_skeleton.xml in client distros - + + Raises the CoarseLocationUpdate event + A CoarseLocationUpdateEventArgs object containing the + data sent by simulator - - - Joint Animation Override? Was the same as the Priority in testing.. - + + Thread sync lock object - - - Array of Rotation Keyframes in order from earliest to latest - + + The event subscribers. null if no subcribers - - - Array of Position Keyframes in order from earliest to latest - This seems to only be for the Pelvis? - + + Raises the GridRegion event + A GridRegionEventArgs object containing the + data sent by simulator - - - A Joint Keyframe. This is either a position or a rotation. - + + Thread sync lock object - - - Either a Vector3 position or a Vector3 Euler rotation - + + The event subscribers. null if no subcribers - - - Poses set in the animation metadata for the hands. - + + Raises the GridLayer event + A GridLayerEventArgs object containing the + data sent by simulator - - - Wrapper around a byte array that allows bit to be packed and unpacked - one at a time or by a variable amount. Useful for very tightly packed - data like LayerData packets - + + Thread sync lock object - - - Default constructor, initialize the bit packer / bit unpacker - with a byte array and starting position - - Byte array to pack bits in to or unpack from - Starting position in the byte array + + The event subscribers. null if no subcribers - - - + + Raises the GridItems event + A GridItemEventArgs object containing the + data sent by simulator - - - + + Thread sync lock object - - - + + The event subscribers. null if no subcribers - - - Pack a floating point value in to the data - - Floating point value to pack + + Raises the RegionHandleReply event + A RegionHandleReplyEventArgs object containing the + data sent by simulator - - - Pack part or all of an integer in to the data - - Integer containing the data to pack - Number of bits of the integer to pack + + Thread sync lock object - - - Pack part or all of an unsigned integer in to the data - - Unsigned integer containing the data to pack - Number of bits of the integer to pack + + A dictionary of all the regions, indexed by region name - - - Pack a single bit in to the data - - Bit to pack + + A dictionary of all the regions, indexed by region handle - + + Constructor - - - - - - - - + Instance of GridClient object to associate with this GridManager instance - + + - - + - + + Request a map layer - - + The name of the region + The type of layer - + - Unpacking a floating point value from the data + - Unpacked floating point value + + + + + + - + - Unpack a variable number of bits from the data in to integer format + - Number of bits to unpack - An integer containing the unpacked bits - This function is only useful up to 32 bits + + + + + - + - Unpack a variable number of bits from the data in to unsigned - integer format + - Number of bits to unpack - An unsigned integer containing the unpacked bits - This function is only useful up to 32 bits + + + - + - Unpack a 16-bit signed integer + Request data for all mainland (Linden managed) simulators - 16-bit signed integer - + - Unpack a 16-bit unsigned integer + Request the region handle for the specified region UUID - 16-bit unsigned integer + UUID of the region to look up - + - Unpack a 32-bit signed integer + Get grid region information using the region name, this function + will block until it can find the region or gives up - 32-bit signed integer + Name of sim you're looking for + Layer that you are requesting + Will contain a GridRegion for the sim you're + looking for if successful, otherwise an empty structure + True if the GridRegion was successfully fetched, otherwise + false - - - Unpack a 32-bit unsigned integer - - 32-bit unsigned integer + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Capabilities is the name of the bi-directional HTTP REST protocol - used to communicate non real-time transactions such as teleporting or - group messaging - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Default constructor - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Triggered when an event is received via the EventQueueGet - capability - - Event name - Decoded event data - The simulator that generated the event + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Reference to the simulator this system is connected to + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Capabilities URI this system was initialized with + + Raised when the simulator sends a + containing the location of agents in the simulator - - Whether the capabilities event queue is connected and - listening for incoming events + + Raised when the simulator sends a Region Data in response to + a Map request - - - Request the URI of a named capability - - Name of the capability to request - The URI of the requested capability, or String.Empty if - the capability does not exist + + Raised when the simulator sends GridLayer object containing + a map tile coordinates and texture information - - - Process any incoming events, check to see if we have a message created for the event, - - - - - + + Raised when the simulator sends GridItems object containing + details on events, land sales at a specific location - - - Attempts to convert an LLSD structure to a known Packet type - - Event name, this must match an actual - packet name for a Packet to be successfully built - LLSD to convert to a Packet - A Packet on success, otherwise null + + Raised in response to a Region lookup - - Origin position of this coordinate frame + + Unknown - - X axis of this coordinate frame, or Forward/At in grid terms + + Current direction of the sun - - Y axis of this coordinate frame, or Left in grid terms + + Current angular velocity of the sun - - Z axis of this coordinate frame, or Up in grid terms + + Current world time - + + Particle system specific enumerators, flags and methods. - Looking direction, must be a normalized vector - Up direction, must be a normalized vector - - - Align the coordinate frame X and Y axis with a given rotation - around the Z axis in radians - - Absolute rotation around the Z axis in - radians + + - - - Access to the data server which allows searching for land, events, people, etc - + + - - - Constructs a new instance of the DirectoryManager class - - An instance of GridClient + + - - Classified Ad categories + + - - Classified is listed in the Any category + + - - Classified is shopping related + + - - Classified is + + Foliage type for this primitive. Only applicable if this + primitive is foliage - - - + + Unknown - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - Event Categories + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + Identifies the owner if audio or a particle system is + active - - - + + - - - + + - - - + + - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + Default constructor - + + Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew + parameters in to signed eight bit values + Floating point parameter to pack + Signed eight bit value containing the packed parameter - + - Query Flags used in many of the DirectoryManager methods to specify which query to execute and how to return the results. - Flags can be combined using the | (pipe) character, not all flags are available in all queries + Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew + parameters from signed eight bit integers to floating point values + Signed eight bit value to unpack + Unpacked floating point value - - Query the People database + + - + + Current version of the media data for the prim - + + Array of media entries indexed by face number - - Query the Groups database + + - - Query the Events database + + - - Query the land holdings database for land owned by the currently connected agent + + Uses basic heuristics to estimate the primitive shape - + + Parameters used to construct a visual representation of a primitive - - Query the land holdings database for land which is owned by a Group + + - - Specifies the query should pre sort the results based upon traffic - when searching the Places database + + - - - + + - - - + + - - - + + - - - + + - - Specifies the query should pre sort the results in an ascending order when searching the land sales database. - This flag is only used when searching the land sales database + + - - Specifies the query should pre sort the results using the SalePrice field when searching the land sales database. - This flag is only used when searching the land sales database + + - - Specifies the query should pre sort the results by calculating the average price/sq.m (SalePrice / Area) when searching the land sales database. - This flag is only used when searching the land sales database + + - - Specifies the query should pre sort the results using the ParcelSize field when searching the land sales database. - This flag is only used when searching the land sales database + + - - Specifies the query should pre sort the results using the Name field when searching the land sales database. - This flag is only used when searching the land sales database + + - - When set, only parcels less than the specified Price will be included when searching the land sales database. - This flag is only used when searching the land sales database + + - - When set, only parcels greater than the specified Size will be included when searching the land sales database. - This flag is only used when searching the land sales database + + - - - + + - - - + + - - Include PG land in results. This flag is used when searching both the Groups, Events and Land sales databases + + - - Include Mature land in results. This flag is used when searching both the Groups, Events and Land sales databases + + - - Include Adult land in results. This flag is used when searching both the Groups, Events and Land sales databases + + - - - + + - - - Land types to search dataserver for - + + - - Search Auction, Mainland and Estate + + - - Land which is currently up for auction + + Attachment point to an avatar - - Parcels which are on the mainland (Linden owned) continents + + - - Parcels which are on privately owned simulators + + - + + + + + + + - The content rating of the event + Information on the flexible properties of a primitive - - Event is PG + + - - Event is Mature + + - - Event is Adult + + - + + + + + + + + + + - Classified Ad Options + Default constructor - There appear to be two formats the flags are packed in. - This set of flags is for the newer style - + + + + - + + + - + + + - + + Information on the light properties of a primitive - + + + + + + + + + + + + + + + + + Default constructor - + - Classified ad query options + + + - - Include all ads in results + + + + + - - Include PG ads in results + + + + + - - Include Mature ads in results + + + Information on the sculpt properties of a sculpted primitive + - - Include Adult ads in results + + + Default constructor + - + - The For Sale flag in PlacesReplyData + + + - - Parcel is not listed for sale + + + Render inside out (inverts the normals). + - - Parcel is For Sale + + + Render an X axis mirror of the sculpty. + - + - A classified ad on the grid + Extended properties to describe an object - - UUID for this ad, useful for looking up detailed - information about it + + - - The title of this classified ad + + - - Flags that show certain options applied to the classified + + - - Creation date of the ad + + - - Expiration date of the ad + + - - Price that was paid for this ad + + - - Print the struct data as a string - A string containing the field name, and field value + + - - - A parcel retrieved from the dataserver such as results from the - "For-Sale" listings or "Places" Search - + + - - The unique dataserver parcel ID - This id is used to obtain additional information from the entry - by using the method + + - - A string containing the name of the parcel + + - - The size of the parcel - This field is not returned for Places searches + + - - The price of the parcel - This field is not returned for Places searches + + - - If True, this parcel is flagged to be auctioned + + - - If true, this parcel is currently set for sale + + - - Parcel traffic + + - - Print the struct data as a string - A string containing the field name, and field value + + - - - An Avatar returned from the dataserver - + + - - Online status of agent - This field appears to be obsolete and always returns false + + - - The agents first name + + - - The agents last name + + - - The agents + + - - Print the struct data as a string - A string containing the field name, and field value + + - + + + + - Response to a "Groups" Search + Default constructor - - The Group ID - - - The name of the group - - - The current number of members - - - Print the struct data as a string - A string containing the field name, and field value + + + Set the properties that are set in an ObjectPropertiesFamily packet + + that has + been partially filled by an ObjectPropertiesFamily packet - + - Parcel information returned from a request - - Represents one of the following: - A parcel of land on the grid that has its Show In Search flag set - A parcel of land owned by the agent making the request - A parcel of land owned by a group the agent making the request is a member of - - In a request for Group Land, the First record will contain an empty record - - Note: This is not the same as searching the land for sale data source + Complete structure for the particle system - - The ID of the Agent of Group that owns the parcel + + Particle Flags + There appears to be more data packed in to this area + for many particle systems. It doesn't appear to be flag values + and serialization breaks unless there is a flag for every + possible bit so it is left as an unsigned integer - - The name + + pattern of particles - - The description + + A representing the maximimum age (in seconds) particle will be displayed + Maximum value is 30 seconds - - The Size of the parcel + + A representing the number of seconds, + from when the particle source comes into view, + or the particle system's creation, that the object will emits particles; + after this time period no more particles are emitted - - The billable Size of the parcel, for mainland - parcels this will match the ActualArea field. For Group owned land this will be 10 percent smaller - than the ActualArea. For Estate land this will always be 0 + + A in radians that specifies where particles will not be created - - Indicates the ForSale status of the parcel + + A in radians that specifies where particles will be created - - The Gridwide X position + + A representing the number of seconds between burts. - - The Gridwide Y position + + A representing the number of meters + around the center of the source where particles will be created. - - The Z position of the parcel, or 0 if no landing point set + + A representing in seconds, the minimum speed between bursts of new particles + being emitted - - The name of the Region the parcel is located in + + A representing in seconds the maximum speed of new particles being emitted. - - The Asset ID of the parcels Snapshot texture + + A representing the maximum number of particles emitted per burst - - The calculated visitor traffic + + A which represents the velocity (speed) from the source which particles are emitted - - The billing product SKU - Known values are: - 023Mainland / Full Region024Estate / Full Region027Estate / Openspace029Estate / Homestead129Mainland / Homestead (Linden Owned) + + A which represents the Acceleration from the source which particles are emitted - - No longer used, will always be 0 + + The Key of the texture displayed on the particle - - Get a SL URL for the parcel - A string, containing a standard SLURL + + The Key of the specified target object or avatar particles will follow - - Print the struct data as a string - A string containing the field name, and field value + + Flags of particle from - - - An "Event" Listing summary - + + Max Age particle system will emit particles for - - The ID of the event creator + + The the particle has at the beginning of its lifecycle - - The name of the event + + The the particle has at the ending of its lifecycle - - The events ID + + A that represents the starting X size of the particle + Minimum value is 0, maximum value is 4 - - A string containing the short date/time the event will begin + + A that represents the starting Y size of the particle + Minimum value is 0, maximum value is 4 - - The event start time in Unixtime (seconds since epoch) + + A that represents the ending X size of the particle + Minimum value is 0, maximum value is 4 - - The events maturity rating + + A that represents the ending Y size of the particle + Minimum value is 0, maximum value is 4 - - Print the struct data as a string - A string containing the field name, and field value + + + Decodes a byte[] array into a ParticleSystem Object + + ParticleSystem object + Start position for BitPacker - + - The details of an "Event" + Generate byte[] array from particle data + Byte array - - The events ID + + + Particle source pattern + - - The ID of the event creator + + None - - The name of the event + + Drop particles from source position with no force - - The category + + "Explode" particles in all directions - - The events description + + Particles shoot across a 2D area - - The short date/time the event will begin + + Particles shoot across a 3D Cone - - The event start time in Unixtime (seconds since epoch) UTC adjusted + + Inverse of AngleCone (shoot particles everywhere except the 3D cone defined - - The length of the event in minutes + + + Particle Data Flags + - - 0 if no cover charge applies + + None - - The cover charge amount in L$ if applicable + + Interpolate color and alpha from start to end - - The name of the region where the event is being held + + Interpolate scale from start to end - - The gridwide location of the event + + Bounce particles off particle sources Z height - - The maturity rating + + velocity of particles is dampened toward the simulators wind - - Get a SL URL for the parcel where the event is hosted - A string, containing a standard SLURL + + Particles follow the source - - Print the struct data as a string - A string containing the field name, and field value + + Particles point towards the direction of source's velocity - - The event subscribers. null if no subcribers + + Target of the particles - - Thread sync lock object + + Particles are sent in a straight line - - The event subscribers. null if no subcribers + + Particles emit a glow - - Thread sync lock object + + used for point/grab/touch - - The event subscribers. null if no subcribers + + + Particle Flags Enum + - - Thread sync lock object + + None - - The event subscribers. null if no subcribers + + Acceleration and velocity for particles are + relative to the object rotation - - Thread sync lock object + + Particles use new 'correct' angle parameters - - The event subscribers. null if no subcribers + + + Texture animation mode + - - Thread sync lock object + + Disable texture animation - - The event subscribers. null if no subcribers + + Enable texture animation - - Thread sync lock object + + Loop when animating textures - - The event subscribers. null if no subcribers + + Animate in reverse direction - - Thread sync lock object + + Animate forward then reverse - - The event subscribers. null if no subcribers + + Slide texture smoothly instead of frame-stepping - - Thread sync lock object + + Rotate texture instead of using frames - - Raised when the data server responds to a request. + + Scale texture instead of using frames - - Raised when the data server responds to a request. + + + A single textured face. Don't instantiate this class yourself, use the + methods in TextureEntry + - - Raised when the data server responds to a request. + + + Contains the definition for individual faces + + - - Raised when the data server responds to a request. + + + + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raised when the data server responds to a request. + + - - Raises the EventInfoReply event - An EventInfoReplyEventArgs object containing the - data returned from the data server + + - - Raises the DirEventsReply event - An DirEventsReplyEventArgs object containing the - data returned from the data server + + - - Raises the PlacesReply event - A PlacesReplyEventArgs object containing the - data returned from the data server + + - - Raises the DirPlacesReply event - A DirPlacesReplyEventArgs object containing the - data returned from the data server + + - - Raises the DirClassifiedsReply event - A DirClassifiedsReplyEventArgs object containing the - data returned from the data server + + - - Raises the DirGroupsReply event - A DirGroupsReplyEventArgs object containing the - data returned from the data server + + - - Raises the DirPeopleReply event - A DirPeopleReplyEventArgs object containing the - data returned from the data server + + In the future this will specify whether a webpage is + attached to this face - - Raises the DirLandReply event - A DirLandReplyEventArgs object containing the - data returned from the data server + + - + - Query the data server for a list of classified ads containing the specified string. - Defaults to searching for classified placed in any category, and includes PG, Adult and Mature - results. - Responses are sent 16 per response packet, there is no way to know how many results a query reply will contain however assuming - the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received - The event is raised when a response is received from the simulator + Represents all of the texturable faces for an object - A string containing a list of keywords to search for - A UUID to correlate the results when the event is raised + Grid objects have infinite faces, with each face + using the properties of the default face unless set otherwise. So if + you have a TextureEntry with a default texture uuid of X, and face 18 + has a texture UUID of Y, every face would be textured with X except for + face 18 that uses Y. In practice however, primitives utilize a maximum + of nine faces - + + + + + + + - Query the data server for a list of classified ads which contain specified keywords (Overload) - The event is raised when a response is received from the simulator + Constructor that takes a default texture UUID - A string containing a list of keywords to search for - The category to search - A set of flags which can be ORed to modify query options - such as classified maturity rating. - A UUID to correlate the results when the event is raised - - Search classified ads containing the key words "foo" and "bar" in the "Any" category that are either PG or Mature - - UUID searchID = StartClassifiedSearch("foo bar", ClassifiedCategories.Any, ClassifiedQueryFlags.PG | ClassifiedQueryFlags.Mature); - - - Responses are sent 16 at a time, there is no way to know how many results a query reply will contain however assuming - the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received - + Texture UUID to use as the default texture - + - Starts search for places (Overloaded) - The event is raised when a response is received from the simulator + Constructor that takes a TextureEntryFace for the + default face - Search text - Each request is limited to 100 places - being returned. To get the first 100 result entries of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - A UUID to correlate the results when the event is raised + Face to use as the default face - + - Queries the dataserver for parcels of land which are flagged to be shown in search - The event is raised when a response is received from the simulator + Constructor that creates the TextureEntry class from a byte array - A string containing a list of keywords to search for separated by a space character - A set of flags which can be ORed to modify query options - such as classified maturity rating. - The category to search - Each request is limited to 100 places - being returned. To get the first 100 result entries of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - A UUID to correlate the results when the event is raised - - Search places containing the key words "foo" and "bar" in the "Any" category that are either PG or Adult - - UUID searchID = StartDirPlacesSearch("foo bar", DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeAdult, ParcelCategory.Any, 0); - - - Additional information on the results can be obtained by using the ParcelManager.InfoRequest method - + Byte array containing the TextureEntry field + Starting position of the TextureEntry field in + the byte array + Length of the TextureEntry field, in bytes - + - Starts a search for land sales using the directory - The event is raised when a response is received from the simulator + This will either create a new face if a custom face for the given + index is not defined, or return the custom face for that index if + it already exists - What type of land to search for. Auction, - estate, mainland, "first land", etc - The OnDirLandReply event handler must be registered before - calling this function. There is no way to determine how many - results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each query. + The index number of the face to create or + retrieve + A TextureEntryFace containing all the properties for that + face - + - Starts a search for land sales using the directory - The event is raised when a response is received from the simulator + - What type of land to search for. Auction, - estate, mainland, "first land", etc - Maximum price to search for - Maximum area to search for - Each request is limited to 100 parcels - being returned. To get the first 100 parcels of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - The OnDirLandReply event handler must be registered before - calling this function. There is no way to determine how many - results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each query. + + - + - Send a request to the data server for land sales listings + - Flags sent to specify query options - Available flags: - Specify the parcel rating with one or more of the following: - IncludePG IncludeMature IncludeAdult - Specify the field to pre sort the results with ONLY ONE of the following: - PerMeterSort NameSort AreaSort PricesSort - Specify the order the results are returned in, if not specified the results are pre sorted in a Descending Order - SortAsc - Specify additional filters to limit the results with one or both of the following: - LimitByPrice LimitByArea - Flags can be combined by separating them with the | (pipe) character - Additional details can be found in - What type of land to search for. Auction, - Estate or Mainland - Maximum price to search for when the - DirFindFlags.LimitByPrice flag is specified in findFlags - Maximum area to search for when the - DirFindFlags.LimitByArea flag is specified in findFlags - Each request is limited to 100 parcels - being returned. To get the first 100 parcels of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - - The event will be raised with the response from the simulator - There is no way to determine how many results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each reply. - Any land set for sale to either anybody or specific to the connected agent will be included in the - results if the land is included in the query - - - - // request all mainland, any maturity rating that is larger than 512 sq.m - StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByArea | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, SearchTypeFlags.Mainland, 0, 512, 0); - - + - + - Search for Groups + - The name or portion of the name of the group you wish to search for - Start from the match number - - + - + - Search for Groups + - The name or portion of the name of the group you wish to search for - Start from the match number - Search flags - - + - + - Search the People directory for other avatars + Controls the texture animation of a particular prim - The name or portion of the name of the avatar you wish to search for - - - - - + + + + + + + + + + + + + + + + + + + + + + - Search Places for parcels of land you personally own + + + - + - Searches Places for land owned by the specified group + - ID of the group you want to recieve land list for (You must be a member of the group) - Transaction (Query) ID which can be associated with results from your request. + - + - Search the Places directory for parcels that are listed in search and contain the specified keywords + Represents a Sound Asset - A string containing the keywords to search for - Transaction (Query) ID which can be associated with results from your request. - + + Initializes a new instance of an AssetSound object + + + Initializes a new instance of an AssetSound object with parameters + A unique specific to this asset + A byte array containing the raw asset data + + - Search Places - All Options + TODO: Encodes a sound file - One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc. - One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer - A string containing a list of keywords to search for separated by a space character - String Simulator Name to search in - LLUID of group you want to recieve results for - Transaction (Query) ID which can be associated with results from your request. - Transaction (Query) ID which can be associated with results from your request. - + - Search All Events with specifid searchText in all categories, includes PG, Mature and Adult + TODO: Decode a sound file - A string containing a list of keywords to search for separated by a space character - Each request is limited to 100 entries - being returned. To get the first group of entries of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - UUID of query to correlate results in callback. + true - + + Override the base classes AssetType + + - Search Events + A linkset asset, containing a parent primitive and zero or more children - A string containing a list of keywords to search for separated by a space character - One or more of the following flags: DateEvents, IncludePG, IncludeMature, IncludeAdult - from the Enum - Multiple flags can be combined by separating the flags with the | (pipe) character - "u" for in-progress and upcoming events, -or- number of days since/until event is scheduled - For example "0" = Today, "1" = tomorrow, "2" = following day, "-1" = yesterday, etc. - Each request is limited to 100 entries - being returned. To get the first group of entries of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - EventCategory event is listed under. - UUID of query to correlate results in callback. - - Requests Event Details - ID of Event returned from the method + + Initializes a new instance of an AssetPrim object - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Initializes a new instance of an AssetPrim object + + A unique specific to this asset + A byte array containing the raw asset data - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + + - - Process an incoming event message - The Unique Capabilities Key - The event message containing the data - The simulator the message originated from + + + + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Override the base classes AssetType - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming event message - The Unique Capabilities Key - The event message containing the data - The simulator the message originated from - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Contains the Event data returned from the data server from an EventInfoRequest - - - Construct a new instance of the EventInfoReplyEventArgs class - A single EventInfo object containing the details of an event + + + Only used internally for XML serialization/deserialization + - + - A single EventInfo object containing the details of an event + The deserialized form of a single primitive in a linkset asset - - Contains the "Event" detail data returned from the data server + + + Operation to apply when applying color to texture + - - Construct a new instance of the DirEventsReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing the "Events" returned by the search query + + + Information needed to translate visual param value to RGBA color + - - The ID returned by + + + Construct VisualColorParam + + Operation to apply when applying color to texture + Colors - - A list of "Events" returned by the data server + + + Represents alpha blending and bump infor for a visual parameter + such as sleive length + - - Contains the "Event" list data returned from the data server + + Stregth of the alpha to apply - - Construct a new instance of PlacesReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing the "Places" returned by the data server query + + File containing the alpha channel - - The ID returned by + + Skip blending if parameter value is 0 - - A list of "Places" returned by the data server + + Use miltiply insted of alpha blending - - Contains the places data returned from the data server + + + Create new alhpa information for a visual param + + Stregth of the alpha to apply + File containing the alpha channel + Skip blending if parameter value is 0 + Use miltiply insted of alpha blending - - Construct a new instance of the DirPlacesReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing land data returned by the data server + + + A single visual characteristic of an avatar mesh, such as eyebrow height + - - The ID returned by + + Index of this visual param - - A list containing Places data returned by the data server + + Internal name - - Contains the classified data returned from the data server + + Group ID this parameter belongs to - - Construct a new instance of the DirClassifiedsReplyEventArgs class - A list of classified ad data returned from the data server + + Name of the wearable this parameter belongs to - - A list containing Classified Ads returned by the data server + + Displayable label of this characteristic - - Contains the group data returned from the data server + + Displayable label for the minimum value of this characteristic - - Construct a new instance of the DirGroupsReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list of groups data returned by the data server + + Displayable label for the maximum value of this characteristic - - The ID returned by + + Default value - - A list containing Groups data returned by the data server + + Minimum value - - Contains the people data returned from the data server + + Maximum value - - Construct a new instance of the DirPeopleReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list of people data returned by the data server + + Is this param used for creation of bump layer? - - The ID returned by + + Alpha blending/bump info - - A list containing People data returned by the data server + + Color information - - Contains the land sales data returned from the data server + + Array of param IDs that are drivers for this parameter - - Construct a new instance of the DirLandReplyEventArgs class - A list of parcels for sale returned by the data server + + + Set all the values through the constructor + + Index of this visual param + Internal name + + + Displayable label of this characteristic + Displayable label for the minimum value of this characteristic + Displayable label for the maximum value of this characteristic + Default value + Minimum value + Maximum value + Is this param used for creation of bump layer? + Array of param IDs that are drivers for this parameter + Alpha blending/bump info + Color information - - A list containing land forsale data returned by the data server + + + Holds the Params array of all the avatar appearance parameters + - + - Represends individual HTTP Download request + NetworkManager is responsible for managing the network layer of + OpenMetaverse. It tracks all the server connections, serializes + outgoing traffic and deserializes incoming traffic, and provides + instances of delegates for network-related events. + + + Login Routines - - Default constructor + + The event subscribers, null of no subscribers - - Constructor + + Raises the PacketSent Event + A PacketSentEventArgs object containing + the data sent from the simulator - - URI of the item to fetch + + Thread sync lock object - - Timout specified in milliseconds + + The event subscribers, null of no subscribers - - Download progress callback + + Raises the LoggedOut Event + A LoggedOutEventArgs object containing + the data sent from the simulator - - Download completed callback + + Thread sync lock object - - Accept the following content type + + The event subscribers, null of no subscribers - - - Manages async HTTP downloads with a limit on maximum - concurrent downloads - + + Raises the SimConnecting Event + A SimConnectingEventArgs object containing + the data sent from the simulator - - Default constructor + + Thread sync lock object - - Maximum number of parallel downloads from a single endpoint + + The event subscribers, null of no subscribers - - Client certificate + + Raises the SimConnected Event + A SimConnectedEventArgs object containing + the data sent from the simulator - - Cleanup method + + Thread sync lock object - - Setup http download request + + The event subscribers, null of no subscribers - - Check the queue for pending work + + Raises the SimDisconnected Event + A SimDisconnectedEventArgs object containing + the data sent from the simulator - - Enqueue a new HTPP download + + Thread sync lock object - - Describes tasks returned in LandStatReply + + The event subscribers, null of no subscribers - - - Estate level administration and utilities - - - - - Constructor for EstateTools class - - - - - - Used in the ReportType field of a LandStatRequest - - - Used by EstateOwnerMessage packets - - - Used by EstateOwnerMessage packets - - - - - - - No flags set - - - Only return targets scripted objects - - - Only return targets objects if on others land - - - Returns target's scripted objects and objects on other parcels - - - Ground texture settings for each corner of the region - - - Used by GroundTextureHeightSettings - - - The high and low texture thresholds for each corner of the sim - - - Textures for each of the four terrain height levels - - - Upper/lower texture boundaries for each corner of the sim - - - The event subscribers. null if no subcribers - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Thread sync lock object - - - The event subscribers. null if no subcribers - - - Thread sync lock object - - - The event subscribers. null if no subcribers + + Raises the Disconnected Event + A DisconnectedEventArgs object containing + the data sent from the simulator - + Thread sync lock object - - The event subscribers. null if no subcribers - - - Thread sync lock object + + The event subscribers, null of no subscribers - - The event subscribers. null if no subcribers + + Raises the SimChanged Event + A SimChangedEventArgs object containing + the data sent from the simulator - + Thread sync lock object - - The event subscribers. null if no subcribers - - - Thread sync lock object + + The event subscribers, null of no subscribers - - The event subscribers. null if no subcribers + + Raises the EventQueueRunning Event + A EventQueueRunningEventArgs object containing + the data sent from the simulator - + Thread sync lock object - - Raised when the data server responds to a request. - - - Raised when the data server responds to a request. - - - Raised when the data server responds to a request. - - - Raised when the data server responds to a request. - - - Raised when the data server responds to a request. - - - Raised when the data server responds to a request. - - - Raised when the data server responds to a request. - - - Raised when the data server responds to a request. - - - Raises the TopCollidersReply event - A TopCollidersReplyEventArgs object containing the - data returned from the data server - - - Raises the TopScriptsReply event - A TopScriptsReplyEventArgs object containing the - data returned from the data server - - - Raises the EstateUsersReply event - A EstateUsersReplyEventArgs object containing the - data returned from the data server - - - Raises the EstateGroupsReply event - A EstateGroupsReplyEventArgs object containing the - data returned from the data server + + All of the simulators we are currently connected to - - Raises the EstateManagersReply event - A EstateManagersReplyEventArgs object containing the - data returned from the data server + + Handlers for incoming capability events - - Raises the EstateBansReply event - A EstateBansReplyEventArgs object containing the - data returned from the data server + + Handlers for incoming packets - - Raises the EstateCovenantReply event - A EstateCovenantReplyEventArgs object containing the - data returned from the data server + + Incoming packets that are awaiting handling - - Raises the EstateUpdateInfoReply event - A EstateUpdateInfoReplyEventArgs object containing the - data returned from the data server + + Outgoing packets that are awaiting handling - + - Requests estate information such as top scripts and colliders + Default constructor - - - - - - - - - - - Requests estate settings, including estate manager and access/ban lists - - - Requests the "Top Scripts" list for the current region - - - Requests the "Top Colliders" list for the current region + Reference to the GridClient object - + - Set several estate specific configuration variables + Register an event handler for a packet. This is a low level event + interface and should only be used if you are doing something not + supported in the library - The Height of the waterlevel over the entire estate. Defaults to 20 - The maximum height change allowed above the baked terrain. Defaults to 4 - The minimum height change allowed below the baked terrain. Defaults to -4 - true to use - if True forces the sun position to the position in SunPosition - The current position of the sun on the estate, or when FixedSun is true the static position - the sun will remain. 6.0 = Sunrise, 30.0 = Sunset + Packet type to trigger events for + Callback to fire when a packet of this type + is received - + - Request return of objects owned by specified avatar + Register an event handler for a packet. This is a low level event + interface and should only be used if you are doing something not + supported in the library - The Agents owning the primitives to return - specify the coverage and type of objects to be included in the return - true to perform return on entire estate + Packet type to trigger events for + Callback to fire when a packet of this type + is received + True if the callback should be ran + asynchronously. Only set this to false (synchronous for callbacks + that will always complete quickly) + If any callback for a packet type is marked as + asynchronous, all callbacks for that packet type will be fired + asynchronously - + + Unregister an event handler for a packet. This is a low level event + interface and should only be used if you are doing something not + supported in the library - - - - + Packet type this callback is registered with + Callback to stop firing events for - + - Used for setting and retrieving various estate panel settings + Register a CAPS event handler. This is a low level event interface + and should only be used if you are doing something not supported in + the library - EstateOwnerMessage Method field - List of parameters to include + Name of the CAPS event to register a handler for + Callback to fire when a CAPS event is received - + - Kick an avatar from an estate + Unregister a CAPS event handler. This is a low level event interface + and should only be used if you are doing something not supported in + the library - Key of Agent to remove - - - - Ban an avatar from an estate - Key of Agent to remove - Ban user from this estate and all others owned by the estate owner + Name of the CAPS event this callback is + registered with + Callback to stop firing events for - - Unban an avatar from an estate - Key of Agent to remove - /// Unban user from this estate and all others owned by the estate owner - + - Send a message dialog to everyone in an entire estate + Send a packet to the simulator the avatar is currently occupying - Message to send all users in the estate + Packet to send - + - Send a message dialog to everyone in a simulator + Send a packet to a specified simulator - Message to send all users in the simulator + Packet to send + Simulator to send the packet to - + - Send an avatar back to their home location + Connect to a simulator - Key of avatar to send home + IP address to connect to + Port to connect to + Handle for this simulator, to identify its + location in the grid + Whether to set CurrentSim to this new + connection, use this if the avatar is moving in to this simulator + URL of the capabilities server to use for + this sim connection + A Simulator object on success, otherwise null - + - Begin the region restart process + Connect to a simulator + IP address and port to connect to + Handle for this simulator, to identify its + location in the grid + Whether to set CurrentSim to this new + connection, use this if the avatar is moving in to this simulator + URL of the capabilities server to use for + this sim connection + A Simulator object on success, otherwise null - + - Cancels a region restart + Initiate a blocking logout request. This will return when the logout + handshake has completed or when Settings.LOGOUT_TIMEOUT + has expired and the network layer is manually shut down - - Estate panel "Region" tab settings - - - Estate panel "Debug" tab settings - - - Used for setting the region's terrain textures for its four height levels - - - - - - - - - - - Used for setting sim terrain texture heights - - - Requests the estate covenant - - + - Upload a terrain RAW file + Initiate the logout process. Check if logout succeeded with the + OnLogoutReply event, and if this does not fire the + Shutdown() function needs to be manually called - A byte array containing the encoded terrain data - The name of the file being uploaded - The Id of the transfer request - + - Teleports all users home in current Estate + Close a connection to the given simulator + + - + - Remove estate manager - Key of Agent to Remove - removes manager to this estate and all others owned by the estate owner + Shutdown will disconnect all the sims except for the current sim + first, and then kill the connection to CurrentSim. This should only + be called if the logout process times out on RequestLogout + + Type of shutdown - + - Add estate manager - Key of Agent to Add - Add agent as manager to this estate and all others owned by the estate owner + Shutdown will disconnect all the sims except for the current sim + first, and then kill the connection to CurrentSim. This should only + be called if the logout process times out on RequestLogout + + Type of shutdown + Shutdown message - + - Add's an agent to the estate Allowed list - Key of Agent to Add - Add agent as an allowed reisdent to All estates if true + Searches through the list of currently connected simulators to find + one attached to the given IPEndPoint + + IPEndPoint of the Simulator to search for + A Simulator reference on success, otherwise null - + - Removes an agent from the estate Allowed list - Key of Agent to Remove - Removes agent as an allowed reisdent from All estates if true + Fire an event when an event queue connects for capabilities + + Simulator the event queue is attached to - - - Add's a group to the estate Allowed list - Key of Group to Add - Add Group as an allowed group to All estates if true + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Removes a group from the estate Allowed list - Key of Group to Remove - Removes Group as an allowed Group from All estates if true + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - - Raised on LandStatReply when the report type is for "top colliders" + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Construct a new instance of the TopCollidersReplyEventArgs class - The number of returned items in LandStatReply - Dictionary of Object UUIDs to tasks returned in LandStatReply + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - The number of returned items in LandStatReply - + + The event subscribers, null of no subscribers - - - A Dictionary of Object UUIDs to tasks returned in LandStatReply - + + Raises the LoginProgress Event + A LoginProgressEventArgs object containing + the data sent from the simulator - - Raised on LandStatReply when the report type is for "top Scripts" + + Thread sync lock object - - Construct a new instance of the TopScriptsReplyEventArgs class - The number of returned items in LandStatReply - Dictionary of Object UUIDs to tasks returned in LandStatReply + + Seed CAPS URL returned from the login server - + + A list of packets obtained during the login process which + networkmanager will log but not process + + - The number of scripts returned in LandStatReply + Generate sane default values for a login request + Account first name + Account last name + Account password + Client application name + Client application version + A populated struct containing + sane defaults - + - A Dictionary of Object UUIDs to tasks returned in LandStatReply + Simplified login that takes the most common and required fields + Account first name + Account last name + Account password + Client application name + Client application version + Whether the login was successful or not. On failure the + LoginErrorKey string will contain the error code and LoginMessage + will contain a description of the error - - Returned, along with other info, upon a successful .RequestInfo() - - - Construct a new instance of the EstateBansReplyEventArgs class - The estate's identifier on the grid - The number of returned items in LandStatReply - User UUIDs banned - - + - The identifier of the estate + Simplified login that takes the most common fields along with a + starting location URI, and can accept an MD5 string instead of a + plaintext password + Account first name + Account last name + Account password or MD5 hash of the password + such as $1$1682a1e45e9f957dcdf0bb56eb43319c + Client application name + Starting location URI that can be built with + StartLocation() + Client application version + Whether the login was successful or not. On failure the + LoginErrorKey string will contain the error code and LoginMessage + will contain a description of the error - + - The number of returned itmes + Login that takes a struct of all the values that will be passed to + the login server + The values that will be passed to the login + server, all fields must be set even if they are String.Empty + Whether the login was successful or not. On failure the + LoginErrorKey string will contain the error code and LoginMessage + will contain a description of the error - + - List of UUIDs of Banned Users + Build a start location URI for passing to the Login function + Name of the simulator to start in + X coordinate to start at + Y coordinate to start at + Z coordinate to start at + String with a URI that can be used to login to a specified + location - - Returned, along with other info, upon a successful .RequestInfo() - - - Construct a new instance of the EstateUsersReplyEventArgs class - The estate's identifier on the grid - The number of users - Allowed users UUIDs + + + Handles response from XML-RPC login replies + - + - The identifier of the estate + Handle response from LLSD login replies + + + - + - The number of returned items + Get current OS + Either "Win" or "Linux" - + - List of UUIDs of Allowed Users + Get clients default Mac Address + A string containing the first found Mac Address - - Returned, along with other info, upon a successful .RequestInfo() + + Raised when the simulator sends us data containing + ... - - Construct a new instance of the EstateGroupsReplyEventArgs class - The estate's identifier on the grid - The number of Groups - Allowed Groups UUIDs + + Raised when the simulator sends us data containing + ... - - - The identifier of the estate - + + Raised when the simulator sends us data containing + ... - - - The number of returned items - + + Raised when the simulator sends us data containing + ... - - - List of UUIDs of Allowed Groups - + + Raised when the simulator sends us data containing + ... - - Returned, along with other info, upon a successful .RequestInfo() + + Raised when the simulator sends us data containing + ... - - Construct a new instance of the EstateManagersReplyEventArgs class - The estate's identifier on the grid - The number of Managers - Managers UUIDs + + Raised when the simulator sends us data containing + ... - - - The identifier of the estate - + + Raised when the simulator sends us data containing + ... - - - The number of returned items - + + Unique identifier associated with our connections to + simulators - - - List of UUIDs of the Estate's Managers - + + The simulator that the logged in avatar is currently + occupying - - Returned, along with other info, upon a successful .RequestInfo() + + Shows whether the network layer is logged in to the + grid or not - - Construct a new instance of the EstateCovenantReplyEventArgs class - The Covenant ID - The timestamp - The estate's name - The Estate Owner's ID (can be a GroupID) + + Number of packets in the incoming queue - - - The Covenant - + + Number of packets in the outgoing queue - - - The timestamp - + + Raised when the simulator sends us data containing + ... - - - The Estate name - + + Called when a reply is received from the login server, the + login sequence will block until this event returns - - - The Estate Owner's ID (can be a GroupID) - + + Current state of logging in - - Returned, along with other info, upon a successful .RequestInfo() + + Upon login failure, contains a short string key for the + type of login error that occurred - - Construct a new instance of the EstateUpdateInfoReplyEventArgs class - The estate's name - The Estate Owners ID (can be a GroupID) - The estate's identifier on the grid - - + + The raw XML-RPC reply from the login server, exactly as it + was received (minus the HTTP header) - - - The estate's name - + + During login this contains a descriptive version of + LoginStatusCode. After a successful login this will contain the + message of the day, and after a failed login a descriptive error + message will be returned - + - The Estate Owner's ID (can be a GroupID) + Explains why a simulator or the grid disconnected from us - - - The identifier of the estate on the grid - + + The client requested the logout or simulator disconnect - - - + + The server notified us that it is disconnecting - - - Registers, unregisters, and fires events generated by incoming packets - + + Either a socket was closed or network traffic timed out - - - Default constructor - - - + + The last active simulator shut down - + - Object that is passed to worker threads in the ThreadPool for - firing packet callbacks + Holds a simulator reference and a decoded packet, these structs are put in + the packet inbox for event handling - - Callback to fire for this packet - - + Reference to the simulator that this packet came from - - The packet that needs to be processed - - - Reference to the GridClient object + + Packet that needs to be processed - + - Register an event handler + Holds a simulator reference and a serialized packet, these structs are put in + the packet outbox for sending - Use PacketType.Default to fire this event on every - incoming packet - Packet type to register the handler for - Callback to be fired - True if this callback should be ran - asynchronously, false to run it synchronous - - - Unregister an event handler - - Packet type to unregister the handler for - Callback to be unregistered + + Reference to the simulator this packet is destined for - - - Fire the events registered for this packet type - - Incoming packet type - Incoming packet - Simulator this packet was received from + + Packet that needs to be sent - - - Registers, unregisters, and fires events generated by the Capabilities - event queue - + + Sequence number of the wrapped packet - + + Number of times this packet has been resent + + + Environment.TickCount when this packet was last sent over the wire + + - Default constructor + - Reference to the GridClient object + + + + + - + - Object that is passed to worker threads in the ThreadPool for - firing CAPS callbacks + Static helper functions and global variables - - Callback to fire for this packet - - - Name of the CAPS event + + This header flag signals that ACKs are appended to the packet - - Strongly typed decoded data + + This header flag signals that this packet has been sent before - - Reference to the simulator that generated this event + + This header flags signals that an ACK is expected for this packet - - Reference to the GridClient object + + This header flag signals that the message is compressed using zerocoding - + - Register an new event handler for a capabilities event sent via the EventQueue + - Use String.Empty to fire this event on every CAPS event - Capability event name to register the - handler for - Callback to fire + + - + - Unregister a previously registered capabilities handler + - Capability event name unregister the - handler for - Callback to unregister + + + - + - Fire the events registered for this event type synchronously + - Capability name - Decoded event body - Reference to the simulator that - generated this event + + - + - Fire the events registered for this event type asynchronously + - Capability name - Decoded event body - Reference to the simulator that - generated this event + + + - + + Given an X/Y location in absolute (grid-relative) terms, a region + handle is returned along with the local X/Y location in that region + The absolute X location, a number such as + 255360.35 + The absolute Y location, a number such as + 255360.35 + The sim-local X position of the global X + position, a value from 0.0 to 256.0 + The sim-local Y position of the global Y + position, a value from 0.0 to 256.0 + A 64-bit region handle that can be used to teleport to - - The avatar has no rights - - - The avatar can see the online status of the target avatar - - - The avatar can see the location of the target avatar on the map - - - The avatar can modify the ojects of the target avatar - - + - This class holds information about an avatar in the friends list. There are two ways - to interface to this class. The first is through the set of boolean properties. This is the typical - way clients of this class will use it. The second interface is through two bitflag properties, - TheirFriendsRights and MyFriendsRights + Converts a floating point number to a terse string format used for + transmitting numbers in wearable asset files + Floating point number to convert to a string + A terse string representation of the input number - + - Used internally when building the initial list of friends at login time + Convert a variable length field (byte array) to a string, with a + field name prepended to each line of the output - System ID of the avatar being prepesented - Rights the friend has to see you online and to modify your objects - Rights you have to see your friend online and to modify their objects + If the byte array has unprintable characters in it, a + hex dump will be written instead + The StringBuilder object to write to + The byte array to convert to a string + A field name to prepend to each line of output - + - System ID of the avatar + Decode a zerocoded byte array, used to decompress packets marked + with the zerocoded flag + Any time a zero is encountered, the next byte is a count + of how many zeroes to expand. One zero is encoded with 0x00 0x01, + two zeroes is 0x00 0x02, three zeroes is 0x00 0x03, etc. The + first four bytes are copied directly to the output buffer. + + The byte array to decode + The length of the byte array to decode. This + would be the length of the packet up to (but not including) any + appended ACKs + The output byte array to decode to + The length of the output buffer - + - full name of the avatar + Encode a byte array with zerocoding. Used to compress packets marked + with the zerocoded flag. Any zeroes in the array are compressed down + to a single zero byte followed by a count of how many zeroes to expand + out. A single zero becomes 0x00 0x01, two zeroes becomes 0x00 0x02, + three zeroes becomes 0x00 0x03, etc. The first four bytes are copied + directly to the output buffer. + The byte array to encode + The length of the byte array to encode + The output byte array to encode to + The length of the output buffer - + - True if the avatar is online + Calculates the CRC (cyclic redundancy check) needed to upload inventory. + Creation date + Sale type + Inventory type + Type + Asset ID + Group ID + Sale price + Owner ID + Creator ID + Item ID + Folder ID + Everyone mask (permissions) + Flags + Next owner mask (permissions) + Group mask (permissions) + Owner mask (permissions) + The calculated CRC - + - True if the friend can see if I am online + Attempts to load a file embedded in the assembly + The filename of the resource to load + A Stream for the requested file, or null if the resource + was not successfully loaded - + - True if the friend can see me on the map + Attempts to load a file either embedded in the assembly or found in + a given search path + The filename of the resource to load + An optional path that will be searched if + the asset is not found embedded in the assembly + A Stream for the requested file, or null if the resource + was not successfully loaded - + - True if the freind can modify my objects + Converts a list of primitives to an object that can be serialized + with the LLSD system + Primitives to convert to a serializable object + An object that can be serialized with LLSD - + - True if I can see if my friend is online + Deserializes OSD in to a list of primitives + Structure holding the serialized primitive list, + must be of the SDMap type + A list of deserialized primitives - - - True if I can see if my friend is on the map - + + + Converts a struct or class object containing fields only into a key value separated string + + The struct object + A string containing the struct fields as the keys, and the field value as the value separated + + + // Add the following code to any struct or class containing only fields to override the ToString() + // method to display the values of the passed object + + /// Print the struct data as a string + ///A string containing the field name, and field value + public override string ToString() + { + return Helpers.StructToString(this); + } + + - + - True if I can modify my friend's objects + Passed to Logger.Log() to identify the severity of a log entry - - - My friend's rights represented as bitmapped flags - + + No logging information will be output - - - My rights represented as bitmapped flags - + + Non-noisy useful information, may be helpful in + debugging a problem - - - FriendInfo represented as a string - - A string reprentation of both my rights and my friends rights + + A non-critical error occurred. A warning will not + prevent the rest of the library from operating as usual, + although it may be indicative of an underlying issue - - - This class is used to add and remove avatars from your friends list and to manage their permission. + + A critical error has occurred. Generally this will + be followed by the network layer shutting down, although the + stability of the library after an error is uncertain + + + Used for internal testing, this logging level can + generate very noisy (long and/or repetitive) messages. Don't + pass this to the Log() function, use DebugLog() instead. - + - Internal constructor + Access to the data server which allows searching for land, events, people, etc - A reference to the GridClient Object - + The event subscribers. null if no subcribers - + + Raises the EventInfoReply event + An EventInfoReplyEventArgs object containing the + data returned from the data server + + Thread sync lock object - + The event subscribers. null if no subcribers - + + Raises the DirEventsReply event + An DirEventsReplyEventArgs object containing the + data returned from the data server + + Thread sync lock object - + The event subscribers. null if no subcribers - + + Raises the PlacesReply event + A PlacesReplyEventArgs object containing the + data returned from the data server + + Thread sync lock object - + The event subscribers. null if no subcribers - + + Raises the DirPlacesReply event + A DirPlacesReplyEventArgs object containing the + data returned from the data server + + Thread sync lock object - + The event subscribers. null if no subcribers - + + Raises the DirClassifiedsReply event + A DirClassifiedsReplyEventArgs object containing the + data returned from the data server + + Thread sync lock object - + The event subscribers. null if no subcribers - + + Raises the DirGroupsReply event + A DirGroupsReplyEventArgs object containing the + data returned from the data server + + Thread sync lock object - + The event subscribers. null if no subcribers - + + Raises the DirPeopleReply event + A DirPeopleReplyEventArgs object containing the + data returned from the data server + + Thread sync lock object - + The event subscribers. null if no subcribers - + + Raises the DirLandReply event + A DirLandReplyEventArgs object containing the + data returned from the data server + + Thread sync lock object - + - A dictionary of key/value pairs containing known friends of this avatar. - The Key is the of the friend, the value is a - object that contains detailed information including permissions you have and have given to the friend + Constructs a new instance of the DirectoryManager class + An instance of GridClient - + - A Dictionary of key/value pairs containing current pending frienship offers. - The key is the of the avatar making the request, - the value is the of the request which is used to accept - or decline the friendship offer + Query the data server for a list of classified ads containing the specified string. + Defaults to searching for classified placed in any category, and includes PG, Adult and Mature + results. + + Responses are sent 16 per response packet, there is no way to know how many results a query reply will contain however assuming + the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received + + The event is raised when a response is received from the simulator + A string containing a list of keywords to search for + A UUID to correlate the results when the event is raised - - Raised when the simulator sends notification one of the members in our friends list comes online - - - Raised when the simulator sends notification one of the members in our friends list goes offline - - - Raised when the simulator sends notification one of the members in our friends list grants or revokes permissions - - - Raised when the simulator sends us the names on our friends list - - - Raised when the simulator sends notification another agent is offering us friendship - - - Raised when a request we sent to friend another agent is accepted or declined - - - Raised when the simulator sends notification one of the members in our friends list has terminated - our friendship - - - Raised when the simulator sends the location of a friend we have - requested map location info for - - - Raises the FriendOnline event - A FriendInfoEventArgs object containing the - data returned from the data server - - - Raises the FriendOffline event - A FriendInfoEventArgs object containing the - data returned from the data server - - - Raises the FriendRightsUpdate event - A FriendInfoEventArgs object containing the - data returned from the data server - - - Raises the FriendNames event - A FriendNamesEventArgs object containing the - data returned from the data server - - - Raises the FriendshipOffered event - A FriendshipOfferedEventArgs object containing the - data returned from the data server + + + Query the data server for a list of classified ads which contain specified keywords (Overload) + + The event is raised when a response is received from the simulator + + A string containing a list of keywords to search for + The category to search + A set of flags which can be ORed to modify query options + such as classified maturity rating. + A UUID to correlate the results when the event is raised + + Search classified ads containing the key words "foo" and "bar" in the "Any" category that are either PG or Mature + + UUID searchID = StartClassifiedSearch("foo bar", ClassifiedCategories.Any, ClassifiedQueryFlags.PG | ClassifiedQueryFlags.Mature); + + + + Responses are sent 16 at a time, there is no way to know how many results a query reply will contain however assuming + the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received + - - Raises the FriendshipResponse event - A FriendshipResponseEventArgs object containing the - data returned from the data server + + + Starts search for places (Overloaded) + + The event is raised when a response is received from the simulator + + Search text + Each request is limited to 100 places + being returned. To get the first 100 result entries of a request use 0, + from 100-199 use 1, 200-299 use 2, etc. + A UUID to correlate the results when the event is raised - - Raises the FriendshipTerminated event - A FriendshipTerminatedEventArgs object containing the - data returned from the data server + + + Queries the dataserver for parcels of land which are flagged to be shown in search + + The event is raised when a response is received from the simulator + + A string containing a list of keywords to search for separated by a space character + A set of flags which can be ORed to modify query options + such as classified maturity rating. + The category to search + Each request is limited to 100 places + being returned. To get the first 100 result entries of a request use 0, + from 100-199 use 1, 200-299 use 2, etc. + A UUID to correlate the results when the event is raised + + Search places containing the key words "foo" and "bar" in the "Any" category that are either PG or Adult + + UUID searchID = StartDirPlacesSearch("foo bar", DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeAdult, ParcelCategory.Any, 0); + + + + Additional information on the results can be obtained by using the ParcelManager.InfoRequest method + - - Raises the FriendFoundReply event - A FriendFoundReplyEventArgs object containing the - data returned from the data server + + + Starts a search for land sales using the directory + + The event is raised when a response is received from the simulator + + What type of land to search for. Auction, + estate, mainland, "first land", etc + The OnDirLandReply event handler must be registered before + calling this function. There is no way to determine how many + results will be returned, or how many times the callback will be + fired other than you won't get more than 100 total parcels from + each query. - + - Accept a friendship request + Starts a search for land sales using the directory + + The event is raised when a response is received from the simulator - agentID of avatatar to form friendship with - imSessionID of the friendship request message + What type of land to search for. Auction, + estate, mainland, "first land", etc + Maximum price to search for + Maximum area to search for + Each request is limited to 100 parcels + being returned. To get the first 100 parcels of a request use 0, + from 100-199 use 1, 200-299 use 2, etc. + The OnDirLandReply event handler must be registered before + calling this function. There is no way to determine how many + results will be returned, or how many times the callback will be + fired other than you won't get more than 100 total parcels from + each query. - + - Decline a friendship request + Send a request to the data server for land sales listings - - of friend - imSessionID of the friendship request message + + Flags sent to specify query options + + Available flags: + Specify the parcel rating with one or more of the following: + IncludePG IncludeMature IncludeAdult + + Specify the field to pre sort the results with ONLY ONE of the following: + PerMeterSort NameSort AreaSort PricesSort + + Specify the order the results are returned in, if not specified the results are pre sorted in a Descending Order + SortAsc + + Specify additional filters to limit the results with one or both of the following: + LimitByPrice LimitByArea + + Flags can be combined by separating them with the | (pipe) character + + Additional details can be found in + + What type of land to search for. Auction, + Estate or Mainland + Maximum price to search for when the + DirFindFlags.LimitByPrice flag is specified in findFlags + Maximum area to search for when the + DirFindFlags.LimitByArea flag is specified in findFlags + Each request is limited to 100 parcels + being returned. To get the first 100 parcels of a request use 0, + from 100-199 use 100, 200-299 use 200, etc. + The event will be raised with the response from the simulator + + There is no way to determine how many results will be returned, or how many times the callback will be + fired other than you won't get more than 100 total parcels from + each reply. + + Any land set for sale to either anybody or specific to the connected agent will be included in the + results if the land is included in the query + + + // request all mainland, any maturity rating that is larger than 512 sq.m + StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByArea | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, SearchTypeFlags.Mainland, 0, 512, 0); + - + - Overload: Offer friendship to an avatar. + Search for Groups - System ID of the avatar you are offering friendship to + The name or portion of the name of the group you wish to search for + Start from the match number + - + - Offer friendship to an avatar. + Search for Groups - System ID of the avatar you are offering friendship to - A message to send with the request + The name or portion of the name of the group you wish to search for + Start from the match number + Search flags + - + - Terminate a friendship with an avatar + Search the People directory for other avatars - System ID of the avatar you are terminating the friendship with + The name or portion of the name of the avatar you wish to search for + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Search Places for parcels of land you personally own + - + - Change the rights of a friend avatar. + Searches Places for land owned by the specified group - the of the friend - the new rights to give the friend - This method will implicitly set the rights to those passed in the rights parameter. + ID of the group you want to recieve land list for (You must be a member of the group) + Transaction (Query) ID which can be associated with results from your request. - + - Use to map a friends location on the grid. + Search the Places directory for parcels that are listed in search and contain the specified keywords - Friends UUID to find - - - + A string containing the keywords to search for + Transaction (Query) ID which can be associated with results from your request. - + - Use to track a friends movement on the grid + Search Places - All Options - Friends Key + One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc. + One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer + A string containing a list of keywords to search for separated by a space character + String Simulator Name to search in + LLUID of group you want to recieve results for + Transaction (Query) ID which can be associated with results from your request. + Transaction (Query) ID which can be associated with results from your request. - + - Ask for a notification of friend's online status + Search All Events with specifid searchText in all categories, includes PG, Mature and Adult - Friend's UUID + A string containing a list of keywords to search for separated by a space character + Each request is limited to 100 entries + being returned. To get the first group of entries of a request use 0, + from 100-199 use 100, 200-299 use 200, etc. + UUID of query to correlate results in callback. - + - This handles the asynchronous response of a RequestAvatarNames call. + Search Events - - - names cooresponding to the the list of IDs sent the the RequestAvatarNames call. + A string containing a list of keywords to search for separated by a space character + One or more of the following flags: DateEvents, IncludePG, IncludeMature, IncludeAdult + from the Enum + + Multiple flags can be combined by separating the flags with the | (pipe) character + "u" for in-progress and upcoming events, -or- number of days since/until event is scheduled + For example "0" = Today, "1" = tomorrow, "2" = following day, "-1" = yesterday, etc. + Each request is limited to 100 entries + being returned. To get the first group of entries of a request use 0, + from 100-199 use 100, 200-299 use 200, etc. + EventCategory event is listed under. + UUID of query to correlate results in callback. - + + Requests Event Details + ID of Event returned from the method + + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + + Process an incoming event message + The Unique Capabilities Key + The event message containing the data + The simulator the message originated from + + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - + Process an incoming packet and raise the appropriate events The sender The EventArgs object containing the packet data - - - Populate FriendList with data from the login reply - - true if login was successful - true if login request is requiring a redirect - A string containing the response to the login request - A string containing the reason for the request - A object containing the decoded - reply from the login server - - - Contains information on a member of our friends list + + Process an incoming event message + The Unique Capabilities Key + The event message containing the data + The simulator the message originated from - - - Construct a new instance of the FriendInfoEventArgs class - - The FriendInfo - - - Get the FriendInfo + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Contains Friend Names + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Construct a new instance of the FriendNamesEventArgs class - - A dictionary where the Key is the ID of the Agent, - and the Value is a string containing their name + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - A dictionary where the Key is the ID of the Agent, - and the Value is a string containing their name + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Sent when another agent requests a friendship with our agent + + Raised when the data server responds to a request. - - - Construct a new instance of the FriendshipOfferedEventArgs class - - The ID of the agent requesting friendship - The name of the agent requesting friendship - The ID of the session, used in accepting or declining the - friendship offer + + Raised when the data server responds to a request. - - Get the ID of the agent requesting friendship + + Raised when the data server responds to a request. - - Get the name of the agent requesting friendship + + Raised when the data server responds to a request. - - Get the ID of the session, used in accepting or declining the - friendship offer + + Raised when the data server responds to a request. - - A response containing the results of our request to form a friendship with another agent + + Raised when the data server responds to a request. - - - Construct a new instance of the FriendShipResponseEventArgs class - - The ID of the agent we requested a friendship with - The name of the agent we requested a friendship with - true if the agent accepted our friendship offer + + Raised when the data server responds to a request. - - Get the ID of the agent we requested a friendship with + + Raised when the data server responds to a request. - - Get the name of the agent we requested a friendship with + + Classified Ad categories - - true if the agent accepted our friendship offer + + Classified is listed in the Any category - - Contains data sent when a friend terminates a friendship with us + + Classified is shopping related - - - Construct a new instance of the FrindshipTerminatedEventArgs class - - The ID of the friend who terminated the friendship with us - The name of the friend who terminated the friendship with us + + Classified is - - Get the ID of the agent that terminated the friendship with us + + - - Get the name of the agent that terminated the friendship with us + + - - - Data sent in response to a request which contains the information to allow us to map the friends location - + + - - - Construct a new instance of the FriendFoundReplyEventArgs class - - The ID of the agent we have requested location information for - The region handle where our friend is located - The simulator local position our friend is located + + - - Get the ID of the agent we have received location information for + + - - Get the region handle where our mapped friend is located + + - - Get the simulator local position where our friend is located + + - - - Main class to expose grid functionality to clients. All of the - classes needed for sending and receiving data are accessible through - this class. - - - - // Example minimum code required to instantiate class and - // connect to a simulator. - using System; - using System.Collections.Generic; - using System.Text; - using OpenMetaverse; - namespace FirstBot - { - class Bot - { - public static GridClient Client; - static void Main(string[] args) - { - Client = new GridClient(); // instantiates the GridClient class - // to the global Client object - // Login to Simulator - Client.Network.Login("FirstName", "LastName", "Password", "FirstBot", "1.0"); - // Wait for a Keypress - Console.ReadLine(); - // Logout of simulator - Client.Network.Logout(); - } - } - } - - + + Event Categories - - - Default constructor - + + - - Networking subsystem + + - - Settings class including constant values and changeable - parameters for everything + + - - Parcel (subdivided simulator lots) subsystem + + - - Our own avatars subsystem + + - - Other avatars subsystem + + - - Estate subsystem + + - - Friends list subsystem + + - - Grid (aka simulator group) subsystem + + - - Object subsystem + + - - Group subsystem + + - - Asset subsystem + + - - Appearance subsystem + + + Query Flags used in many of the DirectoryManager methods to specify which query to execute and how to return the results. + + Flags can be combined using the | (pipe) character, not all flags are available in all queries + - - Inventory subsystem + + Query the People database - - Directory searches including classifieds, people, land - sales, etc + + - - Handles land, wind, and cloud heightmaps + + - - Handles sound-related networking + + Query the Groups database - - Throttling total bandwidth usage, or allocating bandwidth - for specific data stream types + + Query the Events database - - - Return the full name of this instance - - Client avatars full name + + Query the land holdings database for land owned by the currently connected agent - - - Map layer request type - + + - - Objects and terrain are shown + + Query the land holdings database for land which is owned by a Group - - Only the terrain is shown, no objects + + Specifies the query should pre sort the results based upon traffic + when searching the Places database - - Overlay showing land for sale and for auction + + - - - Type of grid item, such as telehub, event, populator location, etc. - + + - - Telehub + + - - PG rated event + + - - Mature rated event + + Specifies the query should pre sort the results in an ascending order when searching the land sales database. + This flag is only used when searching the land sales database - - Popular location + + Specifies the query should pre sort the results using the SalePrice field when searching the land sales database. + This flag is only used when searching the land sales database - - Locations of avatar groups in a region + + Specifies the query should pre sort the results by calculating the average price/sq.m (SalePrice / Area) when searching the land sales database. + This flag is only used when searching the land sales database - - Land for sale + + Specifies the query should pre sort the results using the ParcelSize field when searching the land sales database. + This flag is only used when searching the land sales database - - Classified ad + + Specifies the query should pre sort the results using the Name field when searching the land sales database. + This flag is only used when searching the land sales database - - Adult rated event - - - Adult land for sale + + When set, only parcels less than the specified Price will be included when searching the land sales database. + This flag is only used when searching the land sales database - - - Information about a region on the grid map - + + When set, only parcels greater than the specified Size will be included when searching the land sales database. + This flag is only used when searching the land sales database - - Sim X position on World Map + + - - Sim Y position on World Map + + - - Sim Name (NOTE: In lowercase!) + + Include PG land in results. This flag is used when searching both the Groups, Events and Land sales databases - - - + + Include Mature land in results. This flag is used when searching both the Groups, Events and Land sales databases - - Appears to always be zero (None) + + Include Adult land in results. This flag is used when searching both the Groups, Events and Land sales databases - - Sim's defined Water Height + + - + + Land types to search dataserver for - - UUID of the World Map image + + Search Auction, Mainland and Estate - - Unique identifier for this region, a combination of the X - and Y position + + Land which is currently up for auction - - - - - + + Parcels which are on the mainland (Linden owned) continents - - - - - + + Parcels which are on privately owned simulators - + + The content rating of the event - - - - - - - Visual chunk of the grid map - + + Event is PG - + + Event is Mature + + + Event is Adult + + - Base class for Map Items + Classified Ad Options + There appear to be two formats the flags are packed in. + This set of flags is for the newer style - - The Global X position of the item + + - - The Global Y position of the item + + - - Get the Local X position of the item + + - - Get the Local Y position of the item + + - - Get the Handle of the region + + - + - Represents an agent or group of agents location + Classified ad query options - - - Represents a Telehub location - + + Include all ads in results - - - Represents a non-adult parcel of land for sale - + + Include PG ads in results - - - Represents an Adult parcel of land for sale - + + Include Mature ads in results - - - Represents a PG Event - + + Include Adult ads in results - + - Represents a Mature event + The For Sale flag in PlacesReplyData - - - Represents an Adult event - + + Parcel is not listed for sale - - - Manages grid-wide tasks such as the world map - + + Parcel is For Sale - + - Constructor + A classified ad on the grid - Instance of GridClient object to associate with this GridManager instance - - The event subscribers. null if no subcribers + + UUID for this ad, useful for looking up detailed + information about it - - Thread sync lock object + + The title of this classified ad - - The event subscribers. null if no subcribers + + Flags that show certain options applied to the classified - - Thread sync lock object + + Creation date of the ad - - The event subscribers. null if no subcribers + + Expiration date of the ad - - Thread sync lock object + + Price that was paid for this ad - - The event subscribers. null if no subcribers + + Print the struct data as a string + A string containing the field name, and field value - - Thread sync lock object + + + A parcel retrieved from the dataserver such as results from the + "For-Sale" listings or "Places" Search + - - The event subscribers. null if no subcribers + + The unique dataserver parcel ID + This id is used to obtain additional information from the entry + by using the method - - Thread sync lock object + + A string containing the name of the parcel - - A dictionary of all the regions, indexed by region name + + The size of the parcel + This field is not returned for Places searches - - A dictionary of all the regions, indexed by region handle + + The price of the parcel + This field is not returned for Places searches - - Raised when the simulator sends a - containing the location of agents in the simulator + + If True, this parcel is flagged to be auctioned - - Raised when the simulator sends a Region Data in response to - a Map request + + If true, this parcel is currently set for sale - - Raised when the simulator sends GridLayer object containing - a map tile coordinates and texture information + + Parcel traffic - - Raised when the simulator sends GridItems object containing - details on events, land sales at a specific location + + Print the struct data as a string + A string containing the field name, and field value - - Raised in response to a Region lookup + + + An Avatar returned from the dataserver + - - Unknown + + Online status of agent + This field appears to be obsolete and always returns false - - Current direction of the sun + + The agents first name - - Current angular velocity of the sun + + The agents last name - - Current world time + + The agents - - Raises the CoarseLocationUpdate event - A CoarseLocationUpdateEventArgs object containing the - data sent by simulator + + Print the struct data as a string + A string containing the field name, and field value - - Raises the GridRegion event - A GridRegionEventArgs object containing the - data sent by simulator + + + Response to a "Groups" Search + - - Raises the GridLayer event - A GridLayerEventArgs object containing the - data sent by simulator - - - Raises the GridItems event - A GridItemEventArgs object containing the - data sent by simulator - - - Raises the RegionHandleReply event - A RegionHandleReplyEventArgs object containing the - data sent by simulator + + The Group ID - - - - - + + The name of the group - - - Request a map layer - - The name of the region - The type of layer + + The current number of members - - - - - - - - - - - - - - - + + Print the struct data as a string + A string containing the field name, and field value - + + Parcel information returned from a request + + Represents one of the following: + A parcel of land on the grid that has its Show In Search flag set + A parcel of land owned by the agent making the request + A parcel of land owned by a group the agent making the request is a member of + + + In a request for Group Land, the First record will contain an empty record + + Note: This is not the same as searching the land for sale data source - - - - - - - - - - - - - - - - - - - + + The ID of the Agent of Group that owns the parcel - - - Request data for all mainland (Linden managed) simulators - + + The name - - - Request the region handle for the specified region UUID - - UUID of the region to look up + + The description - - - Get grid region information using the region name, this function - will block until it can find the region or gives up - - Name of sim you're looking for - Layer that you are requesting - Will contain a GridRegion for the sim you're - looking for if successful, otherwise an empty structure - True if the GridRegion was successfully fetched, otherwise - false + + The Size of the parcel - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The billable Size of the parcel, for mainland + parcels this will match the ActualArea field. For Group owned land this will be 10 percent smaller + than the ActualArea. For Estate land this will always be 0 - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Indicates the ForSale status of the parcel - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The Gridwide X position - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The Gridwide Y position - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + The Z position of the parcel, or 0 if no landing point set - - - Avatar group management - + + The name of the Region the parcel is located in - - Key of Group Member + + The Asset ID of the parcels Snapshot texture - - Total land contribution + + The calculated visitor traffic - - Online status information + + The billing product SKU + Known values are: + + 023Mainland / Full Region + 024Estate / Full Region + 027Estate / Openspace + 029Estate / Homestead + 129Mainland / Homestead (Linden Owned) + + - - Abilities that the Group Member has + + No longer used, will always be 0 - - Current group title + + Get a SL URL for the parcel + A string, containing a standard SLURL - - Is a group owner + + Print the struct data as a string + A string containing the field name, and field value - + - Role manager for a group + An "Event" Listing summary - - Key of the group + + The ID of the event creator - - Key of Role + + The name of the event - - Name of Role + + The events ID - - Group Title associated with Role + + A string containing the short date/time the event will begin - - Description of Role + + The event start time in Unixtime (seconds since epoch) - - Abilities Associated with Role + + The events maturity rating - - Returns the role's title - The role's title + + Print the struct data as a string + A string containing the field name, and field value - + - Class to represent Group Title + The details of an "Event" - - Key of the group - - - ID of the role title belongs to + + The events ID - - Group Title + + The ID of the event creator - - Whether title is Active + + The name of the event - - Returns group title + + The category - - - Represents a group on the grid - + + The events description - - Key of Group + + The short date/time the event will begin - - Key of Group Insignia + + The event start time in Unixtime (seconds since epoch) UTC adjusted - - Key of Group Founder + + The length of the event in minutes - - Key of Group Role for Owners + + 0 if no cover charge applies - - Name of Group + + The cover charge amount in L$ if applicable - - Text of Group Charter + + The name of the region where the event is being held - - Title of "everyone" role + + The gridwide location of the event - - Is the group open for enrolement to everyone + + The maturity rating - - Will group show up in search + + Get a SL URL for the parcel where the event is hosted + A string, containing a standard SLURL - - - - - - - - - - - + + Print the struct data as a string + A string containing the field name, and field value - - Is the group Mature + + Contains the Event data returned from the data server from an EventInfoRequest - - Cost of group membership + + Construct a new instance of the EventInfoReplyEventArgs class + A single EventInfo object containing the details of an event - + + A single EventInfo object containing the details of an event - - - + + Contains the "Event" detail data returned from the data server - - The total number of current members this group has + + Construct a new instance of the DirEventsReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list containing the "Events" returned by the search query - - The number of roles this group has configured + + The ID returned by - - Show this group in agent's profile + + A list of "Events" returned by the data server - - Returns the name of the group - A string containing the name of the group + + Contains the "Event" list data returned from the data server - - - A group Vote - + + Construct a new instance of PlacesReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list containing the "Places" returned by the data server query - - Key of Avatar who created Vote + + The ID returned by - - Text of the Vote proposal + + A list of "Places" returned by the data server - - Total number of votes + + Contains the places data returned from the data server - - - A group proposal - + + Construct a new instance of the DirPlacesReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list containing land data returned by the data server - - The Text of the proposal + + The ID returned by - - The minimum number of members that must vote before proposal passes or failes + + A list containing Places data returned by the data server - - The required ration of yes/no votes required for vote to pass - The three options are Simple Majority, 2/3 Majority, and Unanimous - TODO: this should be an enum - - The duration in days votes are accepted + + Contains the classified data returned from the data server - - - + + Construct a new instance of the DirClassifiedsReplyEventArgs class + A list of classified ad data returned from the data server - - - + + A list containing Classified Ads returned by the data server - - - + + Contains the group data returned from the data server - - - + + Construct a new instance of the DirGroupsReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list of groups data returned by the data server - - - + + The ID returned by - - - + + A list containing Groups data returned by the data server - - - + + Contains the people data returned from the data server - - - + + Construct a new instance of the DirPeopleReplyEventArgs class + The ID of the query returned by the data server. + This will correlate to the ID returned by the method + A list of people data returned by the data server - - - + + The ID returned by - - - + + A list containing People data returned by the data server - - - + + Contains the land sales data returned from the data server - - - + + Construct a new instance of the DirLandReplyEventArgs class + A list of parcels for sale returned by the data server - - - + + A list containing land forsale data returned by the data server - + + Capabilities is the name of the bi-directional HTTP REST protocol + used to communicate non real-time transactions such as teleporting or + group messaging - - - + + Reference to the simulator this system is connected to - + + Default constructor + + - + + Request the URI of a named capability + Name of the capability to request + The URI of the requested capability, or String.Empty if + the capability does not exist - + + Process any incoming events, check to see if we have a message created for the event, + + - - - + + Capabilities URI this system was initialized with - - - + + Whether the capabilities event queue is connected and + listening for incoming events - + - Struct representing a group notice + Triggered when an event is received via the EventQueueGet + capability + Event name + Decoded event data + The simulator that generated the event - + + Permission request flags, asked when a script wants to control an Avatar - - - + + Placeholder for empty values, shouldn't ever see this - - - + + Script wants ability to take money from you - - - + + Script wants to take camera controls for you - - - - - + + Script wants to remap avatars controls - - - Struct representing a group notice list entry - + + Script wants to trigger avatar animations + This function is not implemented on the grid - - Notice ID + + Script wants to attach or detach the prim or primset to your avatar - - Creation timestamp of notice + + Script wants permission to release ownership + This function is not implemented on the grid + The concept of "public" objects does not exist anymore. - - Agent name who created notice + + Script wants ability to link/delink with other prims - - Notice subject + + Script wants permission to change joints + This function is not implemented on the grid - - Is there an attachment? + + Script wants permissions to change permissions + This function is not implemented on the grid - - Attachment Type + + Script wants to track avatars camera position and rotation - + + Script wants to control your camera + + - Struct representing a member of a group chat session and their settings + Special commands used in Instant Messages - - The of the Avatar + + Indicates a regular IM from another agent - - True if user has voice chat enabled + + Simple notification box with an OK button - - True of Avatar has moderator abilities + + You've been invited to join a group. - - True if a moderator has muted this avatars chat + + Inventory offer - - True if a moderator has muted this avatars voice + + Accepted inventory offer - - - Role update flags - + + Declined inventory offer - - - + + Group vote - - - + + An object is offering its inventory - - - + + Accept an inventory offer from an object - - - + + Decline an inventory offer from an object - - - + + Unknown - - - + + Start a session, or add users to a session - - - + + Start a session, but don't prune offline users - - Can send invitations to groups default role + + Start a session with your group - - Can eject members from group + + Start a session without a calling card (finder or objects) - - Can toggle 'Open Enrollment' and change 'Signup fee' + + Send a message to a session - - Member is visible in the public member list + + Leave a session - - Can create new roles + + Indicates that the IM is from an object - - Can delete existing roles + + Sent an IM to a busy user, this is the auto response - - Can change Role names, titles and descriptions + + Shows the message in the console and chat history - - Can assign other members to assigners role + + Send a teleport lure - - Can assign other members to any role + + Response sent to the agent which inititiated a teleport invitation - - Can remove members from roles + + Response sent to the agent which inititiated a teleport invitation - - Can assign and remove abilities in roles + + Only useful if you have Linden permissions - - Can change group Charter, Insignia, 'Publish on the web' and which - members are publicly visible in group member listings + + A placeholder type for future expansion, currently not + used - - Can buy land or deed land to group + + IM to tell the user to go to an URL - - Can abandon group owned land to Governor Linden on mainland, or Estate owner for - private estates + + IM for help - - Can set land for-sale information on group owned parcels + + IM sent automatically on call for help, sends a lure + to each Helper reached - - Can subdivide and join parcels + + Like an IM but won't go to email - - Can join group chat sessions + + IM from a group officer to all group members - - Can use voice chat in Group Chat sessions + + Unknown - - Can moderate group chat sessions + + Unknown - - Can toggle "Show in Find Places" and set search category + + Accept a group invitation - - Can change parcel name, description, and 'Publish on web' settings + + Decline a group invitation - - Can set the landing point and teleport routing on group land + + Unknown - - Can change music and media settings + + An avatar is offering you friendship - - Can toggle 'Edit Terrain' option in Land settings + + An avatar has accepted your friendship offer - - Can toggle various About Land > Options settings + + An avatar has declined your friendship offer - - Can always terraform land, even if parcel settings have it turned off + + Indicates that a user has started typing - - Can always fly while over group owned land + + Indicates that a user has stopped typing - - Can always rez objects on group owned land + + + Flag in Instant Messages, whether the IM should be delivered to + offline avatars as well + - - Can always create landmarks for group owned parcels + + Only deliver to online avatars - - Can set home location on any group owned parcel + + If the avatar is offline the message will be held until + they login next, and possibly forwarded to their e-mail account - - Can modify public access settings for group owned parcels + + + Conversion type to denote Chat Packet types in an easier-to-understand format + - - Can manager parcel ban lists on group owned land + + Whisper (5m radius) - - Can manage pass list sales information + + Normal chat (10/20m radius), what the official viewer typically sends - - Can eject and freeze other avatars on group owned land + + Shouting! (100m radius) - - Can return objects set to group + + Event message when an Avatar has begun to type - - Can return non-group owned/set objects + + Event message when an Avatar has stopped typing - - Can return group owned objects + + Send the message to the debug channel - - Can landscape using Linden plants + + Event message when an object uses llOwnerSay - - Can deed objects to group + + Special value to support llRegionSay, never sent to the client - - Can move group owned objects + + + Identifies the source of a chat message + - - Can set group owned objects for-sale + + Chat from the grid or simulator - - Pay group liabilities and receive group dividends + + Chat from another avatar - - Can send group notices + + Chat from an object - - Can receive group notices + + + + - - Can create group proposals + + - - Can vote on group proposals + + - - - Handles all network traffic related to reading and writing group - information - + + - + - Construct a new instance of the GroupManager class + Effect type used in ViewerEffect packets - A reference to the current instance - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + Project a beam from a source to a destination, such as + the one used when editing an object - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + Create a swirl of particles around an object - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + Cause an avatar to look at an object - - Thread sync lock object + + Cause an avatar to point at an object - - The event subscribers. null if no subcribers + + + The action an avatar is doing when looking at something, used in + ViewerEffect packets for the LookAt effect + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + Deprecated - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + + The action an avatar is doing when pointing at something, used in + ViewerEffect packets for the PointAt effect + - - Thread sync lock object + + - - A reference to the current instance + + - - Currently-active group members requests + + - - Currently-active group roles requests + + - - Currently-active group role-member requests + + + Money transaction types + - - Dictionary keeping group members while request is in progress + + - - Dictionary keeping mebmer/role mapping while request is in progress + + - - Dictionary keeping GroupRole information while request is in progress + + - - Caches group name lookups + + - - Raised when the simulator sends us data containing - our current group membership + + - - Raised when the simulator responds to a RequestGroupName - or RequestGroupNames request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when a response to a RequestGroupAccountSummary is returned - by the simulator + + - - Raised when a request to create a group is successful + + - - Raised when a request to join a group either - fails or succeeds + + - - Raised when a request to leave a group either - fails or succeeds + + - - Raised when A group is removed from the group server + + - - Raised when a request to eject a member from a group either - fails or succeeds + + - - Raised when the simulator sends us group notices - + + - - Raised when another agent invites our avatar to join a group + + - - Raises the CurrentGroups event - A CurrentGroupsEventArgs object containing the - data sent from the simulator + + - - Raises the GroupNamesReply event - A GroupNamesEventArgs object containing the - data response from the simulator + + - - Raises the GroupProfile event - An GroupProfileEventArgs object containing the - data returned from the simulator + + - - Raises the GroupMembers event - A GroupMembersEventArgs object containing the - data returned from the simulator + + - - Raises the GroupRolesDataReply event - A GroupRolesDataReplyEventArgs object containing the - data returned from the simulator + + - - Raises the GroupRoleMembersReply event - A GroupRolesRoleMembersReplyEventArgs object containing the - data returned from the simulator + + - - Raises the GroupTitlesReply event - A GroupTitlesReplyEventArgs object containing the - data returned from the simulator + + - - Raises the GroupAccountSummary event - A GroupAccountSummaryReplyEventArgs object containing the - data returned from the simulator + + - - Raises the GroupCreated event - An GroupCreatedEventArgs object containing the - data returned from the simulator + + - - Raises the GroupJoined event - A GroupOperationEventArgs object containing the - result of the operation returned from the simulator + + - - Raises the GroupLeft event - A GroupOperationEventArgs object containing the - result of the operation returned from the simulator + + - - Raises the GroupDropped event - An GroupDroppedEventArgs object containing the - the group your agent left + + - - Raises the GroupMemberEjected event - An GroupMemberEjectedEventArgs object containing the - data returned from the simulator + + - - Raises the GroupNoticesListReply event - An GroupNoticesListReplyEventArgs object containing the - data returned from the simulator + + - - Raises the GroupInvitation event - An GroupInvitationEventArgs object containing the - data returned from the simulator + + - - - Request a current list of groups the avatar is a member of. - - CAPS Event Queue must be running for this to work since the results - come across CAPS. + + - - - Lookup name of group based on groupID - - groupID of group to lookup name for. + + - - - Request lookup of multiple group names - - List of group IDs to request. + + - - Lookup group profile data such as name, enrollment, founder, logo, etc - Subscribe to OnGroupProfile event to receive the results. - group ID (UUID) + + - - Request a list of group members. - Subscribe to OnGroupMembers event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + - - Request group roles - Subscribe to OnGroupRoles event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + - - Request members (members,role) role mapping for a group. - Subscribe to OnGroupRolesMembers event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + - - Request a groups Titles - Subscribe to OnGroupTitles event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache + + - - Begin to get the group account summary - Subscribe to the OnGroupAccountSummary event to receive the results. - group ID (UUID) - How long of an interval - Which interval (0 for current, 1 for last) + + - - Invites a user to a group - The group to invite to - A list of roles to invite a person to - Key of person to invite + + - - Set a group as the current active group - group ID (UUID) + + - - Change the role that determines your active title - Group ID to use - Role ID to change to + + - - Set this avatar's tier contribution - Group ID to change tier in - amount of tier to donate + + - - - Save wheather agent wants to accept group notices and list this group in their profile - - Group - Accept notices from this group - List this group in the profile + + - - Request to join a group - Subscribe to OnGroupJoined event for confirmation. - group ID (UUID) to join. + + - + + + + - Request to create a new group. If the group is successfully - created, L$100 will automatically be deducted + - Subscribe to OnGroupCreated event to receive confirmation. - Group struct containing the new group info - - Update a group's profile and other information - Groups ID (UUID) to update. - Group struct to update. + + - - Eject a user from a group - Group ID to eject the user from - Avatar's key to eject + + - - Update role information - Modified role to be updated + + - - Create a new group role - Group ID to update - Role to create + + - - Delete a group role - Group ID to update - Role to delete + + - - Remove an avatar from a role - Group ID to update - Role ID to be removed from - Avatar's Key to remove + + - - Assign an avatar to a role - Group ID to update - Role ID to assign to - Avatar's ID to assign to role + + + + - - Request the group notices list - Group ID to fetch notices for + + - - Request a group notice by key - ID of group notice + + - - Send out a group notice - Group ID to update - - GroupNotice structure containing notice data + + - - Start a group proposal (vote) - The Group ID to send proposal to - - GroupProposal structure containing the proposal + + - - Request to leave a group - Subscribe to OnGroupLeft event to receive confirmation - The group to leave + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Flags sent when a script takes or releases a control + + NOTE: (need to verify) These might be a subset of the ControlFlags enum in Movement, - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + No Flags set - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Forward (W or up Arrow) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Back (S or down arrow) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Move left (shift+A or left arrow) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Move right (shift+D or right arrow) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Up (E or PgUp) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Down (C or PgDown) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Rotate left (A or left arrow) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Rotate right (D or right arrow) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Left Mouse Button - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Left Mouse button in MouseLook - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + Currently only used to hide your group title + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + No flags set - - Contains the current groups your agent is a member of + + Hide your group title - - Construct a new instance of the CurrentGroupsEventArgs class - The current groups your agent is a member of - - - Get the current groups your agent is a member of - - - A Dictionary of group names, where the Key is the groups ID and the value is the groups name - - - Construct a new instance of the GroupNamesEventArgs class - The Group names dictionary - - - Get the Group Names dictionary - - - Represents the members of a group - - + - Construct a new instance of the GroupMembersReplyEventArgs class + Action state of the avatar, which can currently be typing and + editing - The ID of the request - The ID of the group - The membership list of the group - - - Get the ID as returned by the request to correlate - this result set and the request - - Get the ID of the group + + - - Get the dictionary of members + + - - Represents the roles associated with a group + + - - Construct a new instance of the GroupRolesDataReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The dictionary containing the roles + + + Current teleport status + - - Get the ID as returned by the request to correlate - this result set and the request + + Unknown status - - Get the ID of the group + + Teleport initialized - - Get the dictionary containing the roles + + Teleport in progress - - Represents the Role to Member mappings for a group + + Teleport failed - - Construct a new instance of the GroupRolesMembersReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The member to roles map + + Teleport completed - - Get the ID as returned by the request to correlate - this result set and the request + + Teleport cancelled - - Get the ID of the group + + + + - - Get the member to roles map + + No flags set, or teleport failed - - Represents the titles for a group + + Set when newbie leaves help island for first time - - Construct a new instance of the GroupTitlesReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The titles + + - - Get the ID as returned by the request to correlate - this result set and the request + + Via Lure - - Get the ID of the group + + Via Landmark - - Get the titles + + Via Location - - Represents the summary data for a group + + Via Home - - Construct a new instance of the GroupAccountSummaryReplyEventArgs class - The ID of the group - The summary data + + Via Telehub - - Get the ID of the group + + Via Login - - Get the summary data + + Linden Summoned - - A response to a group create request + + Linden Forced me - - Construct a new instance of the GroupCreatedReplyEventArgs class - The ID of the group - the success or faulure of the request - A string containing additional information + + - - Get the ID of the group + + Agent Teleported Home via Script - - true of the group was created successfully + + - - A string containing the message + + - - Represents a response to a request + + - - Construct a new instance of the GroupOperationEventArgs class - The ID of the group - true of the request was successful + + forced to new location for example when avatar is banned or ejected - - Get the ID of the group + + Teleport Finished via a Lure - - true of the request was successful + + Finished, Sim Changed - - Represents your agent leaving a group + + Finished, Same Sim - - Construct a new instance of the GroupDroppedEventArgs class - The ID of the group + + + + - - Get the ID of the group + + - - Represents a list of active group notices + + - - Construct a new instance of the GroupNoticesListReplyEventArgs class - The ID of the group - The list containing active notices + + - - Get the ID of the group + + + + - - Get the notices list + + - - Represents the profile of a group + + - - Construct a new instance of the GroupProfileEventArgs class - The group profile + + - - Get the group profile + + - + - Provides notification of a group invitation request sent by another Avatar + Instant Message - The invitation is raised when another avatar makes an offer for our avatar - to join a group. - - The ID of the Avatar sending the group invitation + + Key of sender - - The name of the Avatar sending the group invitation + + Name of sender - - A message containing the request information which includes - the name of the group, the groups charter and the fee to join details + + Key of destination avatar - - The Simulator + + ID of originating estate - - Set to true to accept invitation, false to decline + + Key of originating region - - - Static helper functions and global variables - + + Coordinates in originating region - - - Passed to Logger.Log() to identify the severity of a log entry - + + Instant message type - - No logging information will be output + + Group IM session toggle - - Non-noisy useful information, may be helpful in - debugging a problem + + Key of IM session, for Group Messages, the groups UUID - - A non-critical error occurred. A warning will not - prevent the rest of the library from operating as usual, - although it may be indicative of an underlying issue + + Timestamp of the instant message - - A critical error has occurred. Generally this will - be followed by the network layer shutting down, although the - stability of the library after an error is uncertain + + Instant message text - - Used for internal testing, this logging level can - generate very noisy (long and/or repetitive) messages. Don't - pass this to the Log() function, use DebugLog() instead. + + Whether this message is held for offline avatars + + + Context specific packed data + + + Print the struct data as a string + A string containing the field name, and field value + + + + Manager class for our own avatar - - This header flag signals that ACKs are appended to the packet + + The event subscribers. null if no subcribers - - This header flag signals that this packet has been sent before + + Raises the ChatFromSimulator event + A ChatEventArgs object containing the + data returned from the data server - - This header flags signals that an ACK is expected for this packet + + Thread sync lock object - - This header flag signals that the message is compressed using zerocoding + + The event subscribers. null if no subcribers - - - - - - - + + Raises the ScriptDialog event + A SctriptDialogEventArgs object containing the + data returned from the data server - - - - - - - - - + + Thread sync lock object - - - - - - - + + The event subscribers. null if no subcribers - - - - - - - - - + + Raises the ScriptQuestion event + A ScriptQuestionEventArgs object containing the + data returned from the data server - - - Given an X/Y location in absolute (grid-relative) terms, a region - handle is returned along with the local X/Y location in that region - - The absolute X location, a number such as - 255360.35 - The absolute Y location, a number such as - 255360.35 - The sim-local X position of the global X - position, a value from 0.0 to 256.0 - The sim-local Y position of the global Y - position, a value from 0.0 to 256.0 - A 64-bit region handle that can be used to teleport to + + Thread sync lock object - - - Converts a floating point number to a terse string format used for - transmitting numbers in wearable asset files - - Floating point number to convert to a string - A terse string representation of the input number + + The event subscribers. null if no subcribers - - - Convert a variable length field (byte array) to a string, with a - field name prepended to each line of the output - - If the byte array has unprintable characters in it, a - hex dump will be written instead - The StringBuilder object to write to - The byte array to convert to a string - A field name to prepend to each line of output + + Raises the LoadURL event + A LoadUrlEventArgs object containing the + data returned from the data server - - - Decode a zerocoded byte array, used to decompress packets marked - with the zerocoded flag - - Any time a zero is encountered, the next byte is a count - of how many zeroes to expand. One zero is encoded with 0x00 0x01, - two zeroes is 0x00 0x02, three zeroes is 0x00 0x03, etc. The - first four bytes are copied directly to the output buffer. - - The byte array to decode - The length of the byte array to decode. This - would be the length of the packet up to (but not including) any - appended ACKs - The output byte array to decode to - The length of the output buffer + + Thread sync lock object - - - Encode a byte array with zerocoding. Used to compress packets marked - with the zerocoded flag. Any zeroes in the array are compressed down - to a single zero byte followed by a count of how many zeroes to expand - out. A single zero becomes 0x00 0x01, two zeroes becomes 0x00 0x02, - three zeroes becomes 0x00 0x03, etc. The first four bytes are copied - directly to the output buffer. - - The byte array to encode - The length of the byte array to encode - The output byte array to encode to - The length of the output buffer + + The event subscribers. null if no subcribers - - - Calculates the CRC (cyclic redundancy check) needed to upload inventory. - - Creation date - Sale type - Inventory type - Type - Asset ID - Group ID - Sale price - Owner ID - Creator ID - Item ID - Folder ID - Everyone mask (permissions) - Flags - Next owner mask (permissions) - Group mask (permissions) - Owner mask (permissions) - The calculated CRC + + Raises the MoneyBalance event + A BalanceEventArgs object containing the + data returned from the data server - - - Attempts to load a file embedded in the assembly - - The filename of the resource to load - A Stream for the requested file, or null if the resource - was not successfully loaded + + Thread sync lock object - - - Attempts to load a file either embedded in the assembly or found in - a given search path - - The filename of the resource to load - An optional path that will be searched if - the asset is not found embedded in the assembly - A Stream for the requested file, or null if the resource - was not successfully loaded + + The event subscribers. null if no subcribers - - - Converts a list of primitives to an object that can be serialized - with the LLSD system - - Primitives to convert to a serializable object - An object that can be serialized with LLSD + + Raises the MoneyBalanceReply event + A MoneyBalanceReplyEventArgs object containing the + data returned from the data server - - - Deserializes OSD in to a list of primitives - - Structure holding the serialized primitive list, - must be of the SDMap type - A list of deserialized primitives + + Thread sync lock object - - - Converts a struct or class object containing fields only into a key value separated string - - The struct object - A string containing the struct fields as the keys, and the field value as the value separated - - - // Add the following code to any struct or class containing only fields to override the ToString() - // method to display the values of the passed object - /// Print the struct data as a string - ///A string containing the field name, and field value - public override string ToString() - { - return Helpers.StructToString(this); - } - - + + The event subscribers. null if no subcribers - - - The InternalDictionary class is used through the library for storing key/value pairs. - It is intended to be a replacement for the generic Dictionary class and should - be used in its place. It contains several methods for allowing access to the data from - outside the library that are read only and thread safe. - - Key - Value + + Raises the IM event + A InstantMessageEventArgs object containing the + data returned from the data server - - - Initializes a new instance of the Class - with the specified key/value, has the default initial capacity. - - - - // initialize a new InternalDictionary named testDict with a string as the key and an int as the value. - public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(); - - + + Thread sync lock object - - - Initializes a new instance of the Class - with the specified key/value, has its initial valies copied from the specified - - - - to copy initial values from - - - // initialize a new InternalDictionary named testAvName with a UUID as the key and an string as the value. - // populates with copied values from example KeyNameCache Dictionary. - // create source dictionary - Dictionary<UUID, string> KeyNameCache = new Dictionary<UUID, string>(); - KeyNameCache.Add("8300f94a-7970-7810-cf2c-fc9aa6cdda24", "Jack Avatar"); - KeyNameCache.Add("27ba1e40-13f7-0708-3e98-5819d780bd62", "Jill Avatar"); - // Initialize new dictionary. - public InternalDictionary<UUID, string> testAvName = new InternalDictionary<UUID, string>(KeyNameCache); - - + + The event subscribers. null if no subcribers - - - Initializes a new instance of the Class - with the specified key/value, With its initial capacity specified. - - Initial size of dictionary - - - // initialize a new InternalDictionary named testDict with a string as the key and an int as the value, - // initially allocated room for 10 entries. - public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(10); - - + + Raises the TeleportProgress event + A TeleportEventArgs object containing the + data returned from the data server - - Internal dictionary that this class wraps around. Do not - modify or enumerate the contents of this dictionary without locking - on this member + + Thread sync lock object - - - Indexer for the dictionary - - The key - The value + + The event subscribers. null if no subcribers - - - Gets the number of Key/Value pairs contained in the + + Raises the AgentDataReply event + A AgentDataReplyEventArgs object containing the + data returned from the data server - - - Try to get entry from with specified key - - Key to use for lookup - Value returned - - if specified key exists, if not found - - - // find your avatar using the Simulator.ObjectsAvatars InternalDictionary: - Avatar av; - if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) - Console.WriteLine("Found Avatar {0}", av.Name); - - - + + Thread sync lock object - - - Finds the specified match. - - The match. - Matched value - - - // use a delegate to find a prim in the ObjectsPrimitives InternalDictionary - // with the ID 95683496 - uint findID = 95683496; - Primitive findPrim = sim.ObjectsPrimitives.Find( - delegate(Primitive prim) { return prim.ID == findID; }); - - + + The event subscribers. null if no subcribers - - Find All items in an - return matching items. - a containing found items. - - Find All prims within 20 meters and store them in a List - - int radius = 20; - List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( - delegate(Primitive prim) { - Vector3 pos = prim.Position; - return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); - } - ); - + + Raises the AnimationsChanged event + A AnimationsChangedEventArgs object containing the + data returned from the data server - - Find All items in an - return matching keys. - a containing found keys. - - Find All keys which also exist in another dictionary - - List<UUID> matches = myDict.FindAll( - delegate(UUID id) { - return myOtherDict.ContainsKey(id); - } - ); - + + Thread sync lock object - - Perform an on each entry in an - - to perform - - - // Iterates over the ObjectsPrimitives InternalDictionary and prints out some information. - Client.Network.CurrentSim.ObjectsPrimitives.ForEach( - delegate(Primitive prim) - { - if (prim.Text != null) - { - Console.WriteLine("NAME={0} ID = {1} TEXT = '{2}'", - prim.PropertiesFamily.Name, prim.ID, prim.Text); - } - }); - - + + The event subscribers. null if no subcribers - - Perform an on each key of an - - to perform + + Raises the MeanCollision event + A MeanCollisionEventArgs object containing the + data returned from the data server - - - Perform an on each KeyValuePair of an - - to perform + + Thread sync lock object - - Check if Key exists in Dictionary - Key to check for - - if found, otherwise + + The event subscribers. null if no subcribers - - Check if Value exists in Dictionary - Value to check for - - if found, otherwise + + Raises the RegionCrossed event + A RegionCrossedEventArgs object containing the + data returned from the data server - - - Adds the specified key to the dictionary, dictionary locking is not performed, - - The key - The value + + Thread sync lock object - - - Removes the specified key, dictionary locking is not performed - - The key. - - if successful, otherwise + + The event subscribers. null if no subcribers + + + Raises the GroupChatJoined event + A GroupChatJoinedEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the AlertMessage event + A AlertMessageEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ScriptControlChange event + A ScriptControlEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the CameraConstraint event + A CameraConstraintEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the ScriptSensorReply event + A ScriptSensorReplyEventArgs object containing the + data returned from the data server - - - Exception class to identify inventory exceptions - + + Thread sync lock object - - - Responsible for maintaining inventory structure. Inventory constructs nodes - and manages node children as is necessary to maintain a coherant hirarchy. - Other classes should not manipulate or create InventoryNodes explicitly. When - A node's parent changes (when a folder is moved, for example) simply pass - Inventory the updated InventoryFolder and it will make the appropriate changes - to its internal representation. - + + The event subscribers. null if no subcribers - - The event subscribers, null of no subscribers + + Raises the AvatarSitResponse event + A AvatarSitResponseEventArgs object containing the + data returned from the data server - + Thread sync lock object - - The event subscribers, null of no subscribers + + The event subscribers. null if no subcribers - + + Raises the ChatSessionMemberAdded event + A ChatSessionMemberAddedEventArgs object containing the + data returned from the data server + + Thread sync lock object - - The event subscribers, null of no subscribers + + The event subscribers. null if no subcribers - - Thread sync lock object + + Raises the ChatSessionMemberLeft event + A ChatSessionMemberLeftEventArgs object containing the + data returned from the data server - - Raised when the simulator sends us data containing - ... + + Thread sync lock object - - Raised when the simulator sends us data containing - ... + + Reference to the GridClient instance - - Raised when the simulator sends us data containing - ... + + Used for movement and camera tracking - - - By using the bracket operator on this class, the program can get the - InventoryObject designated by the specified uuid. If the value for the corresponding - UUID is null, the call is equivelant to a call to RemoveNodeFor(this[uuid]). - If the value is non-null, it is equivelant to a call to UpdateNodeFor(value), - the uuid parameter is ignored. - - The UUID of the InventoryObject to get or set, ignored if set to non-null value. - The InventoryObject corresponding to uuid. + + Currently playing animations for the agent. Can be used to + check the current movement status such as walking, hovering, aiming, + etc. by checking against system animations found in the Animations class - - - The root folder of this avatars inventory - + + Dictionary containing current Group Chat sessions and members - + - The default shared library folder + Constructor, setup callbacks for packets related to our avatar + A reference to the Class - + - The root node of the avatars inventory + Send a text message from the Agent to the Simulator + A containing the message + The channel to send the message on, 0 is the public channel. Channels above 0 + can be used however only scripts listening on the specified channel will see the message + Denotes the type of message being sent, shout, whisper, etc. - + - The root node of the default shared library + Request any instant messages sent while the client was offline to be resent. - - Raises the InventoryObjectUpdated Event - A InventoryObjectUpdatedEventArgs object containing - the data sent from the simulator - - - Raises the InventoryObjectRemoved Event - A InventoryObjectRemovedEventArgs object containing - the data sent from the simulator - - - Raises the InventoryObjectAdded Event - A InventoryObjectAddedEventArgs object containing - the data sent from the simulator - - + - Returns the contents of the specified folder + Send an Instant Message to another Avatar - A folder's UUID - The contents of the folder corresponding to folder - When folder does not exist in the inventory + The recipients + A containing the message to send - + - Updates the state of the InventoryNode and inventory data structure that - is responsible for the InventoryObject. If the item was previously not added to inventory, - it adds the item, and updates structure accordingly. If it was, it updates the - InventoryNode, changing the parent node if item.parentUUID does - not match node.Parent.Data.UUID. - You can not set the inventory root folder using this method + Send an Instant Message to an existing group chat or conference chat - The InventoryObject to store + The recipients + A containing the message to send + IM session ID (to differentiate between IM windows) - + - Removes the InventoryObject and all related node data from Inventory. + Send an Instant Message - The InventoryObject to remove. + The name this IM will show up as being from + Key of Avatar + Text message being sent + IM session ID (to differentiate between IM windows) + IDs of sessions for a conference - + - Used to find out if Inventory contains the InventoryObject - specified by uuid. + Send an Instant Message - The UUID to check. - true if inventory contains uuid, false otherwise + The name this IM will show up as being from + Key of Avatar + Text message being sent + IM session ID (to differentiate between IM windows) + Type of instant message to send + Whether to IM offline avatars as well + Senders Position + RegionID Sender is In + Packed binary data that is specific to + the dialog type - + - Saves the current inventory structure to a cache file + Send an Instant Message to a group - Name of the cache file to save to + of the group to send message to + Text Message being sent. - + - Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful. + Send an Instant Message to a group the agent is a member of - Name of the cache file to load - The number of inventory items sucessfully reconstructed into the inventory node tree - - - Sort by name - - - Sort by date - - - Sort folders by name, regardless of whether items are - sorted by name or date - - - Place system folders at the top + The name this IM will show up as being from + of the group to send message to + Text message being sent - + - Possible destinations for DeRezObject request + Send a request to join a group chat session + of Group to leave - + + Exit a group chat session. This will stop further Group chat messages + from being sent until session is rejoined. + of Group chat session to leave - - Copy from in-world to agent inventory - - - Derez to TaskInventory - - + + Reply to script dialog questions. + Channel initial request came on + Index of button you're "clicking" + Label of button you're "clicking" + of Object that sent the dialog request + - - Take Object - - + + Accept invite for to a chatterbox session + of session to accept invite to - - Delete Object - - - Put an avatar attachment into agent inventory - - + + Start a friends conference + List of UUIDs to start a conference with + the temportary session ID returned in the callback> - - Return an object back to the owner's inventory - - - Return a deeded object back to the last owner's inventory - - + - Upper half of the Flags field for inventory items + Start a particle stream between an agent and an object + Key of the source agent + Key of the target object + + The type from the enum + A unique for this effect - - Indicates that the NextOwner permission will be set to the - most restrictive set of permissions found in the object set - (including linkset items and object inventory items) on next rez - - - Indicates that the object sale information has been - changed - - - If set, and a slam bit is set, indicates BaseMask will be overwritten on Rez - - - If set, and a slam bit is set, indicates OwnerMask will be overwritten on Rez - - - If set, and a slam bit is set, indicates GroupMask will be overwritten on Rez - - - If set, and a slam bit is set, indicates EveryoneMask will be overwritten on Rez - - - If set, and a slam bit is set, indicates NextOwnerMask will be overwritten on Rez - - - Indicates whether this object is composed of multiple - items or not - - - Indicates that the asset is only referenced by this - inventory item. If this item is deleted or updated to reference a - new assetID, the asset can be deleted - - + - Base Class for Inventory Items + Start a particle stream between an agent and an object + Key of the source agent + Key of the target object + A representing the beams offset from the source + A which sets the avatars lookat animation + of the Effect - + - Constructor, takes an itemID as a parameter + Create a particle beam between an avatar and an primitive - The of the item + The ID of source avatar + The ID of the target primitive + global offset + A object containing the combined red, green, blue and alpha + color values of particle beam + a float representing the duration the parcicle beam will last + A Unique ID for the beam + - + + Create a particle swirl around a target position using a packet - - + global offset + A object containing the combined red, green, blue and alpha + color values of particle beam + a float representing the duration the parcicle beam will last + A Unique ID for the beam - + - of item/folder + Sends a request to sit on the specified object + + of the object to sit on + Sit at offset - + - of parent folder - - - Name of item/folder + Follows a call to to actually sit on the object + - - Item/Folder Owners + + Stands up from sitting on a prim or the ground + true of AgentUpdate was sent - + + Does a "ground sit" at the avatar's current position - - - + - Generates a number corresponding to the value of the object to support the use of a hash table, - suitable for use in hashing algorithms and data structures such as a hash table + Starts or stops flying - A Hashcode of all the combined InventoryBase fields + True to start flying, false to stop flying - + - Determine whether the specified object is equal to the current object + Starts or stops crouching - InventoryBase object to compare against - true if objects are the same + True to start crouching, false to stop crouching - + - Determine whether the specified object is equal to the current object + Starts a jump (begin holding the jump key) - InventoryBase object to compare against - true if objects are the same - + - An Item in Inventory + Use the autopilot sim function to move the avatar to a new + position. Uses double precision to get precise movements + The z value is currently not handled properly by the simulator + Global X coordinate to move to + Global Y coordinate to move to + Z coordinate to move to - + - Construct a new InventoryItem object + Use the autopilot sim function to move the avatar to a new position - The of the item + The z value is currently not handled properly by the simulator + Integer value for the global X coordinate to move to + Integer value for the global Y coordinate to move to + Floating-point value for the Z coordinate to move to - + - Construct a new InventoryItem object of a specific Type + Use the autopilot sim function to move the avatar to a new position - The type of item from - - of the item + The z value is currently not handled properly by the simulator + Integer value for the local X coordinate to move to + Integer value for the local Y coordinate to move to + Floating-point value for the Z coordinate to move to - + + Macro to cancel autopilot sim function + Not certain if this is how it is really done + true if control flags were set and AgentUpdate was sent to the simulator + + + Grabs an object - - - - - The of this item - - - The combined of this item - - - The type of item from - - - The type of item from the enum - - - The of the creator of this item - - - A Description of this item - - - The s this item is set to or owned by - - - If true, item is owned by a group - - - The price this item can be purchased for - - - The type of sale from the enum - - - Combined flags from - - - Time and date this inventory item was created, stored as - UTC (Coordinated Universal Time) + an unsigned integer of the objects ID within the simulator + - - Used to update the AssetID in requests sent to the server + + + Overload: Grab a simulated object + + an unsigned integer of the objects ID within the simulator + + The texture coordinates to grab + The surface coordinates to grab + The face of the position to grab + The region coordinates of the position to grab + The surface normal of the position to grab (A normal is a vector perpindicular to the surface) + The surface binormal of the position to grab (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - - The of the previous owner of the item + + + Drag an object + + of the object to drag + Drag target in region coordinates - + - Indicates inventory item is a link + Overload: Drag an object - True if inventory item is a link to another inventory item + of the object to drag + Drag target in region coordinates + + The texture coordinates to grab + The surface coordinates to grab + The face of the position to grab + The region coordinates of the position to grab + The surface normal of the position to grab (A normal is a vector perpindicular to the surface) + The surface binormal of the position to grab (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - + + Release a grabbed object - - + The Objects Simulator Local ID + + + - + - Generates a number corresponding to the value of the object to support the use of a hash table. - Suitable for use in hashing algorithms and data structures such as a hash table + Release a grabbed object - A Hashcode of all the combined InventoryItem fields + The Objects Simulator Local ID + The texture coordinates to grab + The surface coordinates to grab + The face of the position to grab + The region coordinates of the position to grab + The surface normal of the position to grab (A normal is a vector perpindicular to the surface) + The surface binormal of the position to grab (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - + - Compares an object + Touches an object - The object to compare - true if comparison object matches + an unsigned integer of the objects ID within the simulator + - + - Determine whether the specified object is equal to the current object + Request the current L$ balance - The object to compare against - true if objects are the same - + - Determine whether the specified object is equal to the current object + Give Money to destination Avatar - The object to compare against - true if objects are the same + UUID of the Target Avatar + Amount in L$ - + - InventoryTexture Class representing a graphical image + Give Money to destination Avatar - + UUID of the Target Avatar + Amount in L$ + Description that will show up in the + recipients transaction history - + - Construct an InventoryTexture object + Give L$ to an object - A which becomes the - objects AssetUUID + object to give money to + amount of L$ to give + name of object - + - Construct an InventoryTexture object from a serialization stream + Give L$ to a group + group to give money to + amount of L$ to give - + - InventorySound Class representing a playable sound + Give L$ to a group + group to give money to + amount of L$ to give + description of transaction - + - Construct an InventorySound object + Pay texture/animation upload fee - A which becomes the - objects AssetUUID - + - Construct an InventorySound object from a serialization stream + Pay texture/animation upload fee + description of the transaction - + - InventoryCallingCard Class, contains information on another avatar + Give Money to destination Object or Avatar + UUID of the Target Object/Avatar + Amount in L$ + Reason (Optional normally) + The type of transaction + Transaction flags, mostly for identifying group + transactions - + - Construct an InventoryCallingCard object + Plays a gesture - A which becomes the - objects AssetUUID + Asset of the gesture - + - Construct an InventoryCallingCard object from a serialization stream + Mark gesture active + Inventory of the gesture + Asset of the gesture - + - InventoryLandmark Class, contains details on a specific location + Mark gesture inactive + Inventory of the gesture - + - Construct an InventoryLandmark object + Send an AgentAnimation packet that toggles a single animation on - A which becomes the - objects AssetUUID + The of the animation to start playing + Whether to ensure delivery of this packet or not - + - Construct an InventoryLandmark object from a serialization stream + Send an AgentAnimation packet that toggles a single animation off + The of a + currently playing animation to stop playing + Whether to ensure delivery of this packet or not - + - Landmarks use the InventoryItemFlags struct and will have a flag of 1 set if they have been visited + Send an AgentAnimation packet that will toggle animations on or off + A list of animation s, and whether to + turn that animation on or off + Whether to ensure delivery of this packet or not - + - InventoryObject Class contains details on a primitive or coalesced set of primitives + Teleports agent to their stored home location + true on successful teleport to home location - + - Construct an InventoryObject object + Teleport agent to a landmark - A which becomes the - objects AssetUUID + of the landmark to teleport agent to + true on success, false on failure - + - Construct an InventoryObject object from a serialization stream + Attempt to look up a simulator name and teleport to the discovered + destination + Region name to look up + Position to teleport to + True if the lookup and teleport were successful, otherwise + false - + - Gets or sets the upper byte of the Flags value + Attempt to look up a simulator name and teleport to the discovered + destination + Region name to look up + Position to teleport to + Target to look at + True if the lookup and teleport were successful, otherwise + false - + - Gets or sets the object attachment point, the lower byte of the Flags value + Teleport agent to another region + handle of region to teleport agent to + position in destination sim to teleport to + true on success, false on failure + This call is blocking - + - InventoryNotecard Class, contains details on an encoded text document + Teleport agent to another region + handle of region to teleport agent to + position in destination sim to teleport to + direction in destination sim agent will look at + true on success, false on failure + This call is blocking - + - Construct an InventoryNotecard object + Request teleport to a another simulator - A which becomes the - objects AssetUUID + handle of region to teleport agent to + position in destination sim to teleport to - + - Construct an InventoryNotecard object from a serialization stream + Request teleport to a another simulator + handle of region to teleport agent to + position in destination sim to teleport to + direction in destination sim agent will look at - + - InventoryCategory Class + Teleport agent to a landmark - TODO: Is this even used for anything? + of the landmark to teleport agent to - + - Construct an InventoryCategory object + Send a teleport lure to another avatar with default "Join me in ..." invitation message - A which becomes the - objects AssetUUID + target avatars to lure - + - Construct an InventoryCategory object from a serialization stream + Send a teleport lure to another avatar with custom invitation message + target avatars to lure + custom message to send with invitation - + - InventoryLSL Class, represents a Linden Scripting Language object + Respond to a teleport lure by either accepting it and initiating + the teleport, or denying it + of the avatar sending the lure + true to accept the lure, false to decline it - + - Construct an InventoryLSL object + Update agent profile - A which becomes the - objects AssetUUID + struct containing updated + profile information - + - Construct an InventoryLSL object from a serialization stream + Update agents profile interests + selection of interests from struct - + - InventorySnapshot Class, an image taken with the viewer + Set the height and the width of the client window. This is used + by the server to build a virtual camera frustum for our avatar + New height of the viewer window + New width of the viewer window - + - Construct an InventorySnapshot object + Request the list of muted objects and avatars for this agent - A which becomes the - objects AssetUUID - + - Construct an InventorySnapshot object from a serialization stream + Sets home location to agents current position + will fire an AlertMessage () with + success or failure message - + - InventoryAttachment Class, contains details on an attachable object + Move an agent in to a simulator. This packet is the last packet + needed to complete the transition in to a new simulator + Object - + - Construct an InventoryAttachment object + Reply to script permissions request - A which becomes the - objects AssetUUID + Object + of the itemID requesting permissions + of the taskID requesting permissions + list of permissions to allow - + - Construct an InventoryAttachment object from a serialization stream + Respond to a group invitation by either accepting or denying it + UUID of the group (sent in the AgentID field of the invite message) + IM Session ID from the group invitation message + Accept the group invitation or deny it - + - Get the last AttachmentPoint this object was attached to + Requests script detection of objects and avatars + name of the object/avatar to search for + UUID of the object or avatar to search for + Type of search from ScriptSensorTypeFlags + range of scan (96 max?) + the arc in radians to search within + an user generated ID to correlate replies with + Simulator to perform search in - + - InventoryWearable Class, details on a clothing item or body part + Create or update profile pick + UUID of the pick to update, or random UUID to create a new pick + Is this a top pick? (typically false) + UUID of the parcel (UUID.Zero for the current parcel) + Name of the pick + Global position of the pick landmark + UUID of the image displayed with the pick + Long description of the pick - + - Construct an InventoryWearable object + Delete profile pick - A which becomes the - objects AssetUUID + UUID of the pick to delete - + - Construct an InventoryWearable object from a serialization stream + Create or update profile Classified + UUID of the classified to update, or random UUID to create a new classified + Defines what catagory the classified is in + UUID of the image displayed with the classified + Price that the classified will cost to place for a week + Global position of the classified landmark + Name of the classified + Long description of the classified + if true, auto renew classified after expiration - + - The , Skin, Shape, Skirt, Etc + Create or update profile Classified + UUID of the classified to update, or random UUID to create a new classified + Defines what catagory the classified is in + UUID of the image displayed with the classified + Price that the classified will cost to place for a week + Name of the classified + Long description of the classified + if true, auto renew classified after expiration - + - InventoryAnimation Class, A bvh encoded object which animates an avatar + Delete a classified ad + The classified ads ID - + - Construct an InventoryAnimation object + Fetches resource usage by agents attachmetns - A which becomes the - objects AssetUUID + Called when the requested information is collected - + - Construct an InventoryAnimation object from a serialization stream + Take an incoming ImprovedInstantMessage packet, auto-parse, and if + OnInstantMessage is defined call that with the appropriate arguments + The sender + The EventArgs object containing the packet data - + - InventoryGesture Class, details on a series of animations, sounds, and actions + Take an incoming Chat packet, auto-parse, and if OnChat is defined call + that with the appropriate arguments. + The sender + The EventArgs object containing the packet data - + - Construct an InventoryGesture object + Used for parsing llDialogs - A which becomes the - objects AssetUUID + The sender + The EventArgs object containing the packet data - + - Construct an InventoryGesture object from a serialization stream + Used for parsing llRequestPermissions dialogs + The sender + The EventArgs object containing the packet data - + - A folder contains s and has certain attributes specific - to itself + Handles Script Control changes when Script with permissions releases or takes a control + The sender + The EventArgs object containing the packet data - + - Constructor + Used for parsing llLoadURL Dialogs - UUID of the folder + The sender + The EventArgs object containing the packet data - + - Construct an InventoryFolder object from a serialization stream + Update client's Position, LookAt and region handle from incoming packet + The sender + The EventArgs object containing the packet data + This occurs when after an avatar moves into a new sim - - The Preferred for a folder. - - - The Version of this folder + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Number of child items this folder contains. + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - Get Serilization data for this InventoryFolder object + Process TeleportFailed message sent via EventQueue, informs agent its last teleport has failed and why. + The Message Key + An IMessage object Deserialized from the recieved message event + The simulator originating the event message - + + Process TeleportFinish from Event Queue and pass it onto our TeleportHandler - - + The message system key for this event + IMessage object containing decoded data from OSD + The simulator originating the event message - - - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - Tools for dealing with agents inventory + Crossed region handler for message that comes across the EventQueue. Sent to an agent + when the agent crosses a sim border into a new region. + The message key + the IMessage object containing the deserialized data sent from the simulator + The which originated the packet - - - Default constructor - - Reference to the GridClient object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + This packet is now being sent via the EventQueue - + - Callback for inventory item creation finishing + Group Chat event handler - Whether the request to create an inventory - item succeeded or not - Inventory item being created. If success is - false this will be null + The capability Key + IMessage object containing decoded data from OSD + - + - Callback for an inventory item being create from an uploaded asset + Response from request to join a group chat - true if inventory item creation was successful - - - - - - + + IMessage object containing decoded data from OSD + - + + Someone joined or left group chat - - + + IMessage object containing decoded data from OSD + - + - Reply received when uploading an inventory asset + Handle a group chat Invitation - Has upload been successful - Error message if upload failed - Inventory asset UUID - New asset UUID + Caps Key + IMessage object containing decoded data from OSD + Originating Simulator - + - Delegate that is invoked when script upload is completed + Moderate a chat session - Has upload succeded (note, there still might be compile errors) - Upload status message - Is compilation successful - If compilation failed, list of error messages, null on compilation success - Script inventory UUID - Script's new asset UUID - - - Used for converting shadow_id to asset_id - - - The event subscribers, null of no subscribers - - - Thread sync lock object + the of the session to moderate, for group chats this will be the groups UUID + the of the avatar to moderate + Either "voice" to moderate users voice, or "text" to moderate users text session + true to moderate (silence user), false to allow avatar to speak - - The event subscribers, null of no subscribers + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Thread sync lock object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - The event subscribers, null of no subscribers + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Thread sync lock object + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - The event subscribers, null of no subscribers + + Raised when a scripted object or agent within range sends a public message - - Thread sync lock object + + Raised when a scripted object sends a dialog box containing possible + options an agent can respond to - - The event subscribers, null of no subscribers + + Raised when an object requests a change in the permissions an agent has permitted - - Thread sync lock object + + Raised when a script requests an agent open the specified URL - - The event subscribers, null of no subscribers + + Raised when an agents currency balance is updated - - Thread sync lock object + + Raised when a transaction occurs involving currency such as a land purchase - - The event subscribers, null of no subscribers + + Raised when an ImprovedInstantMessage packet is recieved from the simulator, this is used for everything from + private messaging to friendship offers. The Dialog field defines what type of message has arrived - - Thread sync lock object + + Raised when an agent has requested a teleport to another location, or when responding to a lure. Raised multiple times + for each teleport indicating the progress of the request - - The event subscribers, null of no subscribers + + Raised when a simulator sends agent specific information for our avatar. - - Thread sync lock object + + Raised when our agents animation playlist changes - - Partial mapping of AssetTypes to folder names + + Raised when an object or avatar forcefully collides with our agent - - Raised when the simulator sends us data containing - ... + + Raised when our agent crosses a region border into another region - - Raised when the simulator sends us data containing - ... + + Raised when our agent succeeds or fails to join a group chat session - - Raised when the simulator sends us data containing - an inventory object sent by another avatar or primitive + + Raised when a simulator sends an urgent message usually indication the recent failure of + another action we have attempted to take such as an attempt to enter a parcel where we are denied access - - Raised when the simulator sends us data containing - ... + + Raised when a script attempts to take or release specified controls for our agent - - Raised when the simulator sends us data containing - ... + + Raised when the simulator detects our agent is trying to view something + beyond its limits - - Raised when the simulator sends us data containing - ... + + Raised when a script sensor reply is received from a simulator - - Raised when the simulator sends us data containing - ... + + Raised in response to a request - - Raised when the simulator sends us data containing - ... + + Raised when an avatar enters a group chat session we are participating in - - - Get this agents Inventory data - + + Raised when an agent exits a group chat session we are participating in - - Raises the ItemReceived Event - A ItemReceivedEventArgs object containing - the data sent from the simulator + + Your (client) avatars + "client", "agent", and "avatar" all represent the same thing - - Raises the FolderUpdated Event - A FolderUpdatedEventArgs object containing - the data sent from the simulator + + Temporary assigned to this session, used for + verifying our identity in packets - - Raises the InventoryObjectOffered Event - A InventoryObjectOfferedEventArgs object containing - the data sent from the simulator + + Shared secret that is never sent over the wire - - Raises the TaskItemReceived Event - A TaskItemReceivedEventArgs object containing - the data sent from the simulator + + Your (client) avatar ID, local to the current region/sim - - Raises the FindObjectByPath Event - A FindObjectByPathEventArgs object containing - the data sent from the simulator + + Where the avatar started at login. Can be "last", "home" + or a login - - Raises the TaskInventoryReply Event - A TaskInventoryReplyEventArgs object containing - the data sent from the simulator + + The access level of this agent, usually M or PG - - Raises the SaveAssetToInventory Event - A SaveAssetToInventoryEventArgs object containing - the data sent from the simulator + + The CollisionPlane of Agent - - Raises the ScriptRunningReply Event - A ScriptRunningReplyEventArgs object containing - the data sent from the simulator + + An representing the velocity of our agent - - - Fetch an inventory item from the dataserver - - The items - The item Owners - a integer representing the number of milliseconds to wait for results - An object on success, or null if no item was found - Items will also be sent to the event + + An representing the acceleration of our agent - - - Request A single inventory item - - The items - The item Owners - + + A which specifies the angular speed, and axis about which an Avatar is rotating. - - - Request inventory items - - Inventory items to request - Owners of the inventory items - + + Position avatar client will goto when login to 'home' or during + teleport request to 'home' region. - - - Get contents of a folder - - The of the folder to search - The of the folders owner - true to retrieve folders - true to retrieve items - sort order to return results in - a integer representing the number of milliseconds to wait for results - A list of inventory items matching search criteria within folder - - InventoryFolder.DescendentCount will only be accurate if both folders and items are - requested + + LookAt point saved/restored with HomePosition - - - Request the contents of an inventory folder - - The folder to search - The folder owners - true to return s contained in folder - true to return s containd in folder - the sort order to return items in - + + Avatar First Name (i.e. Philip) - - - Returns the UUID of the folder (category) that defaults to - containing 'type'. The folder is not necessarily only for that - type - - This will return the root folder if one does not exist - - - The UUID of the desired folder if found, the UUID of the RootFolder - if not found, or UUID.Zero on failure + + Avatar Last Name (i.e. Linden) - - - Find an object in inventory using a specific path to search - - The folder to begin the search in - The object owners - A string path to search - milliseconds to wait for a reply - Found items or if - timeout occurs or item is not found + + Avatar Full Name (i.e. Philip Linden) - - - Find inventory items by path - - The folder to begin the search in - The object owners - A string path to search, folders/objects separated by a '/' - Results are sent to the event + + Gets the health of the agent - - - Search inventory Store object for an item or folder - - The folder to begin the search in - An array which creates a path to search - Number of levels below baseFolder to conduct searches - if True, will stop searching after first match is found - A list of inventory items found + + Gets the current balance of the agent - - - Move an inventory item or folder to a new location - - The item or folder to move - The to move item or folder to + + Gets the local ID of the prim the agent is sitting on, + zero if the avatar is not currently sitting - - - Move an inventory item or folder to a new location and change its name - - The item or folder to move - The to move item or folder to - The name to change the item or folder to + + Gets the of the agents active group. - - - Move and rename a folder - - The source folders - The destination folders - The name to change the folder to + + Gets the Agents powers in the currently active group - - - Update folder properties - - - of the folder to update - Sets folder's parent to - Folder name - Folder type + + Current status message for teleporting - - - Move a folder - - The source folders - The destination folders + + Current position of the agent as a relative offset from + the simulator, or the parent object if we are sitting on something - - - Move multiple folders, the keys in the Dictionary parameter, - to a new parents, the value of that folder's key. - - A Dictionary containing the - of the source as the key, and the - of the destination as the value + + Current rotation of the agent as a relative rotation from + the simulator, or the parent object if we are sitting on something - - - Move an inventory item to a new folder - - The of the source item to move - The of the destination folder + + Current position of the agent in the simulator - + - Move and rename an inventory item + A representing the agents current rotation - The of the source item to move - The of the destination folder - The name to change the folder to - - - Move multiple inventory items to new locations - - A Dictionary containing the - of the source item as the key, and the - of the destination folder as the value + + Returns the global grid position of the avatar - + - Remove descendants of a folder + Called once attachment resource usage information has been collected - The of the folder + Indicates if operation was successfull + Attachment resource usage information - - - Remove a single item from inventory - - The of the inventory item to remove + + + Agent movement and camera control + + Agent movement is controlled by setting specific + After the control flags are set, An AgentUpdate is required to update the simulator of the specified flags + This is most easily accomplished by setting one or more of the AgentMovement properties + + Movement of an avatar is always based on a compass direction, for example AtPos will move the + agent from West to East or forward on the X Axis, AtNeg will of course move agent from + East to West or backward on the X Axis, LeftPos will be South to North or forward on the Y Axis + The Z axis is Up, finer grained control of movements can be done using the Nudge properties + - - - Remove a folder from inventory - - The of the folder to remove + + Agent camera controls - - - Remove multiple items or folders from inventory - - A List containing the s of items to remove - A List containing the s of the folders to remove + + Currently only used for hiding your group title - - - Empty the Lost and Found folder - + + Action state of the avatar, which can currently be + typing and editing - - - Empty the Trash folder - + + - - - - - - - - - - - - Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. - - - - - - + + - - - - - - - - - - - - Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. - - - - - - - - + + - - - Creates a new inventory folder - - ID of the folder to put this folder in - Name of the folder to create - The UUID of the newly created folder + + - - - Creates a new inventory folder - - ID of the folder to put this folder in - Name of the folder to create - Sets this folder as the default folder - for new assets of the specified type. Use AssetType.Unknown - to create a normal folder, otherwise it will likely create a - duplicate of an existing folder type - The UUID of the newly created folder - If you specify a preferred type of AsseType.Folder - it will create a new root folder which may likely cause all sorts - of strange problems + + - - - Create an inventory item and upload asset data - - Asset data - Inventory item name - Inventory item description - Asset type - Inventory type - Put newly created inventory in this folder - Delegate that will receive feedback on success or failure + + - - - Create an inventory item and upload asset data - - Asset data - Inventory item name - Inventory item description - Asset type - Inventory type - Put newly created inventory in this folder - Permission of the newly created item - (EveryoneMask, GroupMask, and NextOwnerMask of Permissions struct are supported) - Delegate that will receive feedback on success or failure + + - - - Creates inventory link to another inventory item or folder - - Put newly created link in folder with this UUID - Inventory item or folder - Method to call upon creation of the link + + - - - Creates inventory link to another inventory item - - Put newly created link in folder with this UUID - Original inventory item - Method to call upon creation of the link + + + + + Timer for sending AgentUpdate packets + + + Default constructor - + - Creates inventory link to another inventory folder + Send an AgentUpdate with the camera set at the current agent + position and pointing towards the heading specified - Put newly created link in folder with this UUID - Original inventory folder - Method to call upon creation of the link + Camera rotation in radians + Whether to send the AgentUpdate reliable + or not - + - Creates inventory link to another inventory item or folder + Rotates the avatar body and camera toward a target position. + This will also anchor the camera position on the avatar - Put newly created link in folder with this UUID - Original item's UUID - Name - Description - Asset Type - Inventory Type - Transaction UUID - Method to call upon creation of the link + Region coordinates to turn toward - + + Send new AgentUpdate packet to update our current camera + position and rotation - - - - - - - - - + + Send new AgentUpdate packet to update our current camera + position and rotation - - - - - - - - - - + Whether to require server acknowledgement + of this packet - + + Send new AgentUpdate packet to update our current camera + position and rotation - - - - - - - - - - + Whether to require server acknowledgement + of this packet + Simulator to send the update to - + - Request a copy of an asset embedded within a notecard + Builds an AgentUpdate packet entirely from parameters. This + will not touch the state of Self.Movement or + Self.Movement.Camera in any way - Usually UUID.Zero for copying an asset from a notecard - UUID of the notecard to request an asset from - Target folder for asset to go to in your inventory - UUID of the embedded asset - callback to run when item is copied to inventory + + + + + + + + + + + - - - - - + + Move agent positive along the X axis - - - - - + + Move agent negative along the X axis - - - - - - - + + Move agent positive along the Y axis - - - - - - - - - + + Move agent negative along the Y axis - - - Save changes to notecard embedded in object contents - - Encoded notecard asset data - Notecard UUID - Object's UUID - Called upon finish of the upload with status information + + Move agent positive along the Z axis - - - Upload new gesture asset for an inventory gesture item - - Encoded gesture asset - Gesture inventory UUID - Callback whick will be called when upload is complete + + Move agent negative along the Z axis - - - Update an existing script in an agents Inventory - - A byte[] array containing the encoded scripts contents - the itemID of the script - if true, sets the script content to run on the mono interpreter - - + + - - - Update an existing script in an task Inventory - - A byte[] array containing the encoded scripts contents - the itemID of the script - UUID of the prim containting the script - if true, sets the script content to run on the mono interpreter - if true, sets the script to running - - + + - - - Rez an object from inventory - - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details + + - - - Rez an object from inventory - - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object + + - - - Rez an object from inventory - - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object - User defined queryID to correlate replies - If set to true, the CreateSelected flag - will be set on the rezzed object + + - - - DeRez an object from the simulator to the agents Objects folder in the agents Inventory - - The simulator Local ID of the object - If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed + + - - - DeRez an object from the simulator and return to inventory - - The simulator Local ID of the object - The type of destination from the enum - The destination inventory folders -or- - if DeRezzing object to a tasks Inventory, the Tasks - The transaction ID for this request which - can be used to correlate this request with other packets - If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed + + - - - Rez an item from inventory to its previous simulator location - - - - - - - - - + + Causes simulator to make agent fly - + + Stop movement + + + Finish animation + + + Stand up from a sit + + + Tells simulator to sit agent on ground + + + Place agent into mouselook mode + + + Nudge agent positive along the X axis + + + Nudge agent negative along the X axis + + + Nudge agent positive along the Y axis + + + Nudge agent negative along the Y axis + + + Nudge agent positive along the Z axis + + + Nudge agent negative along the Z axis + + + + + + + + + Tell simulator to mark agent as away + + + + + + + + + + + + + + - Give an inventory item to another avatar + Returns "always run" value, or changes it by sending a SetAlwaysRunPacket - The of the item to give - The name of the item - The type of the item from the enum - The of the recipient - true to generate a beameffect during transfer - + + The current value of the agent control flags + + + Gets or sets the interval in milliseconds at which + AgentUpdate packets are sent to the current simulator. Setting + this to a non-zero value will also enable the packet sending if + it was previously off, and setting it to zero will disable + + + Gets or sets whether AgentUpdate packets are sent to + the current simulator + + + Reset movement controls every time we send an update + + - Give an inventory Folder with contents to another avatar + Camera controls for the agent, mostly a thin wrapper around + CoordinateFrame. This class is only responsible for state + tracking and math, it does not send any packets - The of the Folder to give - The name of the folder - The type of the item from the enum - The of the recipient - true to generate a beameffect during transfer - - - Copy or move an from agent inventory to a task (primitive) inventory - - The target object - The item to copy or move from inventory - - - For items with copy permissions a copy of the item is placed in the tasks inventory, - for no-copy items the object is moved to the tasks inventory + + - - - Retrieve a listing of the items contained in a task (Primitive) - - The tasks - The tasks simulator local ID - milliseconds to wait for reply from simulator - A list containing the inventory items inside the task or null - if a timeout occurs - This request blocks until the response from the simulator arrives - or timeoutMS is exceeded + + The camera is a local frame of reference inside of + the larger grid space. This is where the math happens - + - Request the contents of a tasks (primitives) inventory from the - current simulator + Default constructor - The LocalID of the object - - - - Request the contents of a tasks (primitives) inventory - - The simulator Local ID of the object - A reference to the simulator object that contains the object - + + - - - Move an item from a tasks (Primitive) inventory to the specified folder in the avatars inventory - - LocalID of the object in the simulator - UUID of the task item to move - The ID of the destination folder in this agents inventory - Simulator Object - Raises the event + + - - - Remove an item from an objects (Prim) Inventory - - LocalID of the object in the simulator - UUID of the task item to remove - Simulator Object - You can confirm the removal by comparing the tasks inventory serial before and after the - request with the request combined with - the event + + - - - Copy an InventoryScript item from the Agents Inventory into a primitives task inventory - - An unsigned integer representing a primitive being simulated - An which represents a script object from the agents inventory - true to set the scripts running state to enabled - A Unique Transaction ID - - The following example shows the basic steps necessary to copy a script from the agents inventory into a tasks inventory - and assumes the script exists in the agents inventory. - - uint primID = 95899503; // Fake prim ID - UUID scriptID = UUID.Parse("92a7fe8a-e949-dd39-a8d8-1681d8673232"); // Fake Script UUID in Inventory - Client.Inventory.FolderContents(Client.Inventory.FindFolderForType(AssetType.LSLText), Client.Self.AgentID, - false, true, InventorySortOrder.ByName, 10000); - Client.Inventory.RezScript(primID, (InventoryItem)Client.Inventory.Store[scriptID]); - + + - + - Request the running status of a script contained in a task (primitive) inventory + Used to specify movement actions for your agent - The ID of the primitive containing the script - The ID of the script - The event can be used to obtain the results of the - request - - - - Send a request to set the running state of a script contained in a task (primitive) inventory - - The ID of the primitive containing the script - The ID of the script - true to set the script running, false to stop a running script - To verify the change you can use the method combined - with the event + + Empty flag - - - Create a CRC from an InventoryItem - - The source InventoryItem - A uint representing the source InventoryItem as a CRC + + Move Forward (SL Keybinding: W/Up Arrow) - - - Reverses a cheesy XORing with a fixed UUID to convert a shadow_id to an asset_id - - Obfuscated shadow_id value - Deobfuscated asset_id value + + Move Backward (SL Keybinding: S/Down Arrow) - - - Does a cheesy XORing with a fixed UUID to convert an asset_id to a shadow_id - - asset_id value to obfuscate - Obfuscated shadow_id value + + Move Left (SL Keybinding: Shift-(A/Left Arrow)) - - - Wrapper for creating a new object - - The type of item from the enum - The of the newly created object - An object with the type and id passed + + Move Right (SL Keybinding: Shift-(D/Right Arrow)) - - - Parse the results of a RequestTaskInventory() response - - A string which contains the data from the task reply - A List containing the items contained within the tasks inventory + + Not Flying: Jump/Flying: Move Up (SL Keybinding: E) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Not Flying: Croutch/Flying: Move Down (SL Keybinding: C) - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Unused - - - UpdateCreateInventoryItem packets are received when a new inventory item - is created. This may occur when an object that's rezzed in world is - taken into inventory, when an item is created using the CreateInventoryItem - packet, or when an object is purchased - - The sender - The EventArgs object containing the packet data + + Unused - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Unused - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + Unused - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + ORed with AGENT_CONTROL_AT_* if the keyboard is being used - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used - - Set to true to accept offer, false to decline it + + ORed with AGENT_CONTROL_UP_* if the keyboard is being used - - The folder to accept the inventory into, if null default folder for will be used + + Fly - - - Callback when an inventory object is accepted and received from a - task inventory. This is the callback in which you actually get - the ItemID, as in ObjectOfferedCallback it is null when received - from a task. - + + - - - + + Finish our current animation - - - - - + + Stand up from the ground or a prim seat - - - De-serialization constructor for the InventoryNode Class - + + Sit on the ground at our current location - - - De-serialization handler for the InventoryNode Class - + + Whether mouselook is currently enabled - - - + + Legacy, used if a key was pressed for less than a certain amount of time - - - + + Legacy, used if a key was pressed for less than a certain amount of time - - - + + Legacy, used if a key was pressed for less than a certain amount of time - - - + + Legacy, used if a key was pressed for less than a certain amount of time - - - For inventory folder nodes specifies weather the folder needs to be - refreshed from the server - + + Legacy, used if a key was pressed for less than a certain amount of time - - - Serialization handler for the InventoryNode Class - + + Legacy, used if a key was pressed for less than a certain amount of time - - - - - + + - - - Singleton logging class for the entire library - + + - - - Default constructor - + + Set when the avatar is idled or set to away. Note that the away animation is + activated separately from setting this flag - - - Callback used for client apps to receive log messages from - the library - - Data being logged - The severity of the log entry from + + + + + - - log4net logging engine + + - - Triggered whenever a message is logged. If this is left - null, log messages will go to the console + + - + - Send a log message to the logging engine + - The log message - The severity of the log entry - + - Send a log message to the logging engine + Construct a new instance of the ChatEventArgs object - The log message - The severity of the log entry - Instance of the client + Sim from which the message originates + The message sent + The audible level of the message + The type of message sent: whisper, shout, etc + The source type of the message sender + The name of the agent or object sending the message + The ID of the agent or object sending the message + The ID of the object owner, or the agent ID sending the message + The position of the agent or object sending the message - - - Send a log message to the logging engine - - The log message - The severity of the log entry - Exception that was raised + + Get the simulator sending the message - - - Send a log message to the logging engine - - The log message - The severity of the log entry - Instance of the client - Exception that was raised + + Get the message sent - - - If the library is compiled with DEBUG defined, an event will be - fired if an OnLogMessage handler is registered and the - message will be sent to the logging engine - - The message to log at the DEBUG level to the - current logging engine + + Get the audible level of the message - - - If the library is compiled with DEBUG defined and - GridClient.Settings.DEBUG is true, an event will be - fired if an OnLogMessage handler is registered and the - message will be sent to the logging engine - - The message to log at the DEBUG level to the - current logging engine - Instance of the client + + Get the type of message sent: whisper, shout, etc - - - + + Get the source type of the message sender - - - + + Get the name of the agent or object sending the message - - - + + Get the ID of the agent or object sending the message - - - + + Get the ID of the object owner, or the agent ID sending the message - - - + + Get the position of the agent or object sending the message - - - + + Contains the data sent when a primitive opens a dialog with this agent - + + Construct a new instance of the ScriptDialogEventArgs + The dialog message + The name of the object that sent the dialog request + The ID of the image to be displayed + The ID of the primitive sending the dialog + The first name of the senders owner + The last name of the senders owner + The communication channel the dialog was sent on + The string labels containing the options presented in this dialog - - - + + Get the dialog message - - - Login Request Parameters - + + Get the name of the object that sent the dialog request - - - Default constuctor, initializes sane default values - + + Get the ID of the image to be displayed - - - Instantiates new LoginParams object and fills in the values - - Instance of GridClient to read settings from - Login first name - Login last name - Password - Login channnel (application name) - Client version, should be application name + version number + + Get the ID of the primitive sending the dialog - - - Instantiates new LoginParams object and fills in the values - - Instance of GridClient to read settings from - Login first name - Login last name - Password - Login channnel (application name) - Client version, should be application name + version number - URI of the login server + + Get the first name of the senders owner - - The URL of the Login Server + + Get the last name of the senders owner - - The number of milliseconds to wait before a login is considered - failed due to timeout + + Get the communication channel the dialog was sent on, responses + should also send responses on this same channel - - The request method - login_to_simulator is currently the only supported method + + Get the string labels containing the options presented in this dialog - - The Agents First name + + Contains the data sent when a primitive requests debit or other permissions + requesting a YES or NO answer - - The Agents Last name + + + Construct a new instance of the ScriptQuestionEventArgs + + The simulator containing the object sending the request + The ID of the script making the request + The ID of the primitive containing the script making the request + The name of the primitive making the request + The name of the owner of the object making the request + The permissions being requested - - A md5 hashed password - plaintext password will be automatically hashed + + Get the simulator containing the object sending the request - - The agents starting location once logged in - Either "last", "home", or a string encoded URI - containing the simulator name and x/y/z coordinates e.g: uri:hooper&128&152&17 + + Get the ID of the script making the request - - A string containing the client software channel information - Second Life Release + + Get the ID of the primitive containing the script making the request - - The client software version information - The official viewer uses: Second Life Release n.n.n.n - where n is replaced with the current version of the viewer + + Get the name of the primitive making the request - - A string containing the platform information the agent is running on + + Get the name of the owner of the object making the request - - A string hash of the network cards Mac Address + + Get the permissions being requested - - Unknown or deprecated + + Contains the data sent when a primitive sends a request + to an agent to open the specified URL - - A string hash of the first disk drives ID used to identify this clients uniqueness + + + Construct a new instance of the LoadUrlEventArgs + + The name of the object sending the request + The ID of the object sending the request + The ID of the owner of the object sending the request + True if the object is owned by a group + The message sent with the request + The URL the object sent - - A string containing the viewers Software, this is not directly sent to the login server but - instead is used to generate the Version string + + Get the name of the object sending the request - - A string representing the software creator. This is not directly sent to the login server but - is used by the library to generate the Version information + + Get the ID of the object sending the request - - If true, this agent agrees to the Terms of Service of the grid its connecting to + + Get the ID of the owner of the object sending the request - - Unknown + + True if the object is owned by a group - - An array of string sent to the login server to enable various options + + Get the message sent with the request - - A randomly generated ID to distinguish between login attempts. This value is only used - internally in the library and is never sent over the wire + + Get the URL the object sent + + + The date received from an ImprovedInstantMessage - + - The decoded data returned from the login server after a successful login + Construct a new instance of the InstantMessageEventArgs object + the InstantMessage object + the simulator where the InstantMessage origniated - - true, false, indeterminate + + Get the InstantMessage object - - Login message of the day + + Get the simulator where the InstantMessage origniated - - M or PG, also agent_region_access and agent_access_max + + Contains the currency balance - + - Parse LLSD Login Reply Data + Construct a new BalanceEventArgs object - An - contaning the login response data - XML-RPC logins do not require this as XML-RPC.NET - automatically populates the struct properly using attributes + The currenct balance - - - Login Routines - + - NetworkManager is responsible for managing the network layer of - OpenMetaverse. It tracks all the server connections, serializes - outgoing traffic and deserializes incoming traffic, and provides - instances of delegates for network-related events. + Get the currenct balance - - - Default constructor - - Reference to the GridClient object + + Contains the transaction summary when an item is purchased, + money is given, or land is purchased - + - Explains why a simulator or the grid disconnected from us + Construct a new instance of the MoneyBalanceReplyEventArgs object + The ID of the transaction + True of the transaction was successful + The current currency balance + The meters credited + The meters comitted + A brief description of the transaction - - The client requested the logout or simulator disconnect + + Get the ID of the transaction - - The server notified us that it is disconnecting + + True of the transaction was successful - - Either a socket was closed or network traffic timed out + + Get the remaining currency balance - - The last active simulator shut down + + Get the meters credited - - - Holds a simulator reference and a decoded packet, these structs are put in - the packet inbox for event handling - + + Get the meters comitted - - Reference to the simulator that this packet came from + + Get the description of the transaction - - Packet that needs to be processed + + Data sent from the simulator containing information about your agent and active group information - + - Holds a simulator reference and a serialized packet, these structs are put in - the packet outbox for sending + Construct a new instance of the AgentDataReplyEventArgs object + The agents first name + The agents last name + The agents active group ID + The group title of the agents active group + The combined group powers the agent has in the active group + The name of the group the agent has currently active - - Reference to the simulator this packet is destined for + + Get the agents first name - - Packet that needs to be sent + + Get the agents last name - - Sequence number of the wrapped packet + + Get the active group ID of your agent - - Number of times this packet has been resent + + Get the active groups title of your agent - - Environment.TickCount when this packet was last sent over the wire + + Get the combined group powers of your agent - + + Get the active group name of your agent + + + Data sent by the simulator to indicate the active/changed animations + applied to your agent + + + Construct a new instance of the AnimationsChangedEventArgs class - - - - - - - - - - + The dictionary that contains the changed animations - - The event subscribers, null of no subscribers + + Get the dictionary that contains the changed animations - - Thread sync lock object + + + Data sent from a simulator indicating a collision with your agent + - - Seed CAPS URL returned from the login server + + + Construct a new instance of the MeanCollisionEventArgs class + + The type of collision that occurred + The ID of the agent or object that perpetrated the agression + The ID of the Victim + The strength of the collision + The Time the collision occurred - - A list of packets obtained during the login process which - networkmanager will log but not process + + Get the Type of collision - - The event subscribers, null of no subscribers + + Get the ID of the agent or object that collided with your agent - - Thread sync lock object + + Get the ID of the agent that was attacked - - The event subscribers, null of no subscribers + + A value indicating the strength of the collision - - Thread sync lock object + + Get the time the collision occurred - - The event subscribers, null of no subscribers + + Data sent to your agent when it crosses region boundaries - - Thread sync lock object + + + Construct a new instance of the RegionCrossedEventArgs class + + The simulator your agent just left + The simulator your agent is now in - - The event subscribers, null of no subscribers + + Get the simulator your agent just left - - Thread sync lock object + + Get the simulator your agent is now in - - The event subscribers, null of no subscribers + + Data sent from the simulator when your agent joins a group chat session - - Thread sync lock object + + + Construct a new instance of the GroupChatJoinedEventArgs class + + The ID of the session + The name of the session + A temporary session id used for establishing new sessions + True of your agent successfully joined the session - - The event subscribers, null of no subscribers + + Get the ID of the group chat session - - Thread sync lock object + + Get the name of the session - - The event subscribers, null of no subscribers + + Get the temporary session ID used for establishing new sessions - - Thread sync lock object + + True if your agent successfully joined the session - - The event subscribers, null of no subscribers + + Data sent by the simulator containing urgent messages - - Thread sync lock object + + + Construct a new instance of the AlertMessageEventArgs class + + The alert message - - All of the simulators we are currently connected to + + Get the alert message + + + Data sent by a script requesting to take or release specified controls to your agent + + + + Construct a new instance of the ScriptControlEventArgs class + + The controls the script is attempting to take or release to the agent + True if the script is passing controls back to the agent + True if the script is requesting controls be released to the script + + + Get the controls the script is attempting to take or release to the agent + + + True if the script is passing controls back to the agent + + + True if the script is requesting controls be released to the script - - Handlers for incoming capability events + + + Data sent from the simulator to an agent to indicate its view limits + - - Handlers for incoming packets + + + Construct a new instance of the CameraConstraintEventArgs class + + The collision plane - - Incoming packets that are awaiting handling + + Get the collision plane - - Outgoing packets that are awaiting handling + + + Data containing script sensor requests which allow an agent to know the specific details + of a primitive sending script sensor requests + - - Raised when the simulator sends us data containing - ... + + + Construct a new instance of the ScriptSensorReplyEventArgs + + The ID of the primitive sending the sensor + The ID of the group associated with the primitive + The name of the primitive sending the sensor + The ID of the primitive sending the sensor + The ID of the owner of the primitive sending the sensor + The position of the primitive sending the sensor + The range the primitive specified to scan + The rotation of the primitive sending the sensor + The type of sensor the primitive sent + The velocity of the primitive sending the sensor - - Called when a reply is received from the login server, the - login sequence will block until this event returns + + Get the ID of the primitive sending the sensor - - Raised when the simulator sends us data containing - ... + + Get the ID of the group associated with the primitive - - Raised when the simulator sends us data containing - ... + + Get the name of the primitive sending the sensor - - Raised when the simulator sends us data containing - ... + + Get the ID of the primitive sending the sensor - - Raised when the simulator sends us data containing - ... + + Get the ID of the owner of the primitive sending the sensor - - Raised when the simulator sends us data containing - ... + + Get the position of the primitive sending the sensor - - Raised when the simulator sends us data containing - ... + + Get the range the primitive specified to scan - - Raised when the simulator sends us data containing - ... + + Get the rotation of the primitive sending the sensor - - Raised when the simulator sends us data containing - ... + + Get the type of sensor the primitive sent - - Current state of logging in + + Get the velocity of the primitive sending the sensor - - Upon login failure, contains a short string key for the - type of login error that occurred + + Contains the response data returned from the simulator in response to a - - The raw XML-RPC reply from the login server, exactly as it - was received (minus the HTTP header) + + Construct a new instance of the AvatarSitResponseEventArgs object - - During login this contains a descriptive version of - LoginStatusCode. After a successful login this will contain the - message of the day, and after a failed login a descriptive error - message will be returned + + Get the ID of the primitive the agent will be sitting on - - Unique identifier associated with our connections to - simulators + + True if the simulator Autopilot functions were involved - - The simulator that the logged in avatar is currently - occupying + + Get the camera offset of the agent when seated - - Shows whether the network layer is logged in to the - grid or not + + Get the camera eye offset of the agent when seated - - Number of packets in the incoming queue + + True of the agent will be in mouselook mode when seated - - Number of packets in the outgoing queue + + Get the position of the agent when seated - - Raises the LoginProgress Event - A LoginProgressEventArgs object containing - the data sent from the simulator + + Get the rotation of the agent when seated - - - Generate sane default values for a login request - - Account first name - Account last name - Account password - Client application name - Client application version - A populated struct containing - sane defaults + + Data sent when an agent joins a chat session your agent is currently participating in - + - Simplified login that takes the most common and required fields + Construct a new instance of the ChatSessionMemberAddedEventArgs object - Account first name - Account last name - Account password - Client application name - Client application version - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error + The ID of the chat session + The ID of the agent joining - - - Simplified login that takes the most common fields along with a - starting location URI, and can accept an MD5 string instead of a - plaintext password - - Account first name - Account last name - Account password or MD5 hash of the password - such as $1$1682a1e45e9f957dcdf0bb56eb43319c - Client application name - Starting location URI that can be built with - StartLocation() - Client application version - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error + + Get the ID of the chat session - - - Login that takes a struct of all the values that will be passed to - the login server - - The values that will be passed to the login - server, all fields must be set even if they are String.Empty - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error + + Get the ID of the agent that joined - + + Data sent when an agent exits a chat session your agent is currently participating in + + - Build a start location URI for passing to the Login function + Construct a new instance of the ChatSessionMemberLeftEventArgs object - Name of the simulator to start in - X coordinate to start at - Y coordinate to start at - Z coordinate to start at - String with a URI that can be used to login to a specified - location + The ID of the chat session + The ID of the Agent that left - + + Get the ID of the chat session + + + Get the ID of the agent that left + + - Handles response from XML-RPC login replies + Starts a thread that keeps the daemon running + + - + - Handle response from LLSD login replies + Stops the daemon and the thread keeping it running - - - - - - - + - Get current OS + - Either "Win" or "Linux" + + + - + - Get clients default Mac Address + This is used to initialize and stop the Connector as a whole. The Connector + Create call must be completed successfully before any other requests are made + (typically during application initialization). The shutdown should be called + when the application is shutting down to gracefully release resources - A string containing the first found Mac Address - - - Raises the PacketSent Event - A PacketSentEventArgs object containing - the data sent from the simulator - - - Raises the LoggedOut Event - A LoggedOutEventArgs object containing - the data sent from the simulator - - - Raises the SimConnecting Event - A SimConnectingEventArgs object containing - the data sent from the simulator - - - Raises the SimConnected Event - A SimConnectedEventArgs object containing - the data sent from the simulator - - - Raises the SimDisconnected Event - A SimDisconnectedEventArgs object containing - the data sent from the simulator - - - Raises the Disconnected Event - A DisconnectedEventArgs object containing - the data sent from the simulator - - - Raises the SimChanged Event - A SimChangedEventArgs object containing - the data sent from the simulator - - - Raises the EventQueueRunning Event - A EventQueueRunningEventArgs object containing - the data sent from the simulator + A string value indicting the Application name + URL for the management server + LoggingSettings + + - + - Register an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library + Shutdown Connector -- Should be called when the application is shutting down + to gracefully release resources - Packet type to trigger events for - Callback to fire when a packet of this type - is received + Handle returned from successful Connector ‘create’ request - + - Register an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library + Mute or unmute the microphone - Packet type to trigger events for - Callback to fire when a packet of this type - is received - True if the callback should be ran - asynchronously. Only set this to false (synchronous for callbacks - that will always complete quickly) - If any callback for a packet type is marked as - asynchronous, all callbacks for that packet type will be fired - asynchronously + Handle returned from successful Connector ‘create’ request + true (mute) or false (unmute) - + - Unregister an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library + Mute or unmute the speaker - Packet type this callback is registered with - Callback to stop firing events for + Handle returned from successful Connector ‘create’ request + true (mute) or false (unmute) - + - Register a CAPS event handler. This is a low level event interface - and should only be used if you are doing something not supported in - the library + Set microphone volume - Name of the CAPS event to register a handler for - Callback to fire when a CAPS event is received + Handle returned from successful Connector ‘create’ request + The level of the audio, a number between -100 and 100 where + 0 represents ‘normal’ speaking volume - + - Unregister a CAPS event handler. This is a low level event interface - and should only be used if you are doing something not supported in - the library + Set local speaker volume - Name of the CAPS event this callback is - registered with - Callback to stop firing events for + Handle returned from successful Connector ‘create’ request + The level of the audio, a number between -100 and 100 where + 0 represents ‘normal’ speaking volume - + - Send a packet to the simulator the avatar is currently occupying + Create a Session + Sessions typically represent a connection to a media session with one or more + participants. This is used to generate an ‘outbound’ call to another user or + channel. The specifics depend on the media types involved. A session handle is + required to control the local user functions within the session (or remote + users if the current account has rights to do so). Currently creating a + session automatically connects to the audio media, there is no need to call + Session.Connect at this time, this is reserved for future use. - Packet to send + Handle returned from successful Connector ‘create’ request + This is the URI of the terminating point of the session (ie who/what is being called) + This is the display name of the entity being called (user or channel) + Only needs to be supplied when the target URI is password protected + This indicates the format of the password as passed in. This can either be + “ClearText†or “SHA1UserNameâ€. If this element does not exist, it is assumed to be “ClearTextâ€. If it is + “SHA1UserNameâ€, the password as passed in is the SHA1 hash of the password and username concatenated together, + then base64 encoded, with the final “=†character stripped off. + + + - + - Send a packet to a specified simulator + Used to accept a call - Packet to send - Simulator to send the packet to + SessionHandle such as received from SessionNewEvent + "default" + - + - Connect to a simulator + This command is used to start the audio render process, which will then play + the passed in file through the selected audio render device. This command + should not be issued if the user is on a call. - IP address to connect to - Port to connect to - Handle for this simulator, to identify its - location in the grid - Whether to set CurrentSim to this new - connection, use this if the avatar is moving in to this simulator - URL of the capabilities server to use for - this sim connection - A Simulator object on success, otherwise null + The fully qualified path to the sound file. + True if the file is to be played continuously and false if it is should be played once. + - + - Connect to a simulator + This command is used to stop the audio render process. - IP address and port to connect to - Handle for this simulator, to identify its - location in the grid - Whether to set CurrentSim to this new - connection, use this if the avatar is moving in to this simulator - URL of the capabilities server to use for - this sim connection - A Simulator object on success, otherwise null + The fully qualified path to the sound file issued in the start render command. + - + - Initiate a blocking logout request. This will return when the logout - handshake has completed or when Settings.LOGOUT_TIMEOUT - has expired and the network layer is manually shut down + This is used to ‘end’ an established session (i.e. hang-up or disconnect). + Handle returned from successful Session ‘create’ request or a SessionNewEvent + - + - Initiate the logout process. Check if logout succeeded with the - OnLogoutReply event, and if this does not fire the - Shutdown() function needs to be manually called + Set the combined speaking and listening position in 3D space. + Handle returned from successful Session ‘create’ request or a SessionNewEvent + Speaking position + Listening position + - + - Close a connection to the given simulator + Set User Volume for a particular user. Does not affect how other users hear that user. - - - - + Handle returned from successful Session ‘create’ request or a SessionNewEvent + + The level of the audio, a number between -100 and 100 where 0 represents ‘normal’ speaking volume + - + - Shutdown will disconnect all the sims except for the current sim - first, and then kill the connection to CurrentSim. This should only - be called if the logout process times out on RequestLogout - Type of shutdown + This is used to get a list of audio devices that can be used for capture (input) of voice. + + - + - Shutdown will disconnect all the sims except for the current sim - first, and then kill the connection to CurrentSim. This should only - be called if the logout process times out on RequestLogout - Type of shutdown - Shutdown message + This is used to get a list of audio devices that can be used for render (playback) of voice. + - + - Searches through the list of currently connected simulators to find - one attached to the given IPEndPoint + This command is used to select the render device. - IPEndPoint of the Simulator to search for - A Simulator reference on success, otherwise null + The name of the device as returned by the Aux.GetRenderDevices command. - + - Fire an event when an event queue connects for capabilities + This command is used to select the capture device. - Simulator the event queue is attached to - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + The name of the device as returned by the Aux.GetCaptureDevices command. - + - A Name Value pair with additional settings, used in the protocol - primarily to transmit avatar names and active group in object packets + This command is used to start the audio capture process which will cause + AuxAudioProperty Events to be raised. These events can be used to display a + microphone VU meter for the currently selected capture device. This command + should not be issued if the user is on a call. + (unused but required) + - + - Constructor that takes all the fields as parameters + This command is used to stop the audio capture process. - - - - - - - - - - + - + - Constructor that takes a single line from a NameValue field + This command is used to set the mic volume while in the audio tuning process. + Once an acceptable mic level is attained, the application must issue a + connector set mic volume command to have that level be used while on voice + calls. - - - - - Type of the value - - - Unknown - - - String value + the microphone volume (-100 to 100 inclusive) + - + + This command is used to set the speaker volume while in the audio tuning + process. Once an acceptable speaker level is attained, the application must + issue a connector set speaker volume command to have that level be used while + on voice calls. + the speaker volume (-100 to 100 inclusive) + - + + Start up the Voice service. - + + Handle miscellaneous request status + + + ///If something goes wrong, we log it. - + + Cleanup oject resources - - Deprecated - - - String value, but designated as an asset + + + Request voice cap when changing regions + - + + Handle a change in session state - + + Close a voice session + - + + Locate a Session context from its handle + Creates the session context if it does not exist. - + + Handle completion of main voice cap request. + + + - + + Daemon has started so connect to it. - + + The daemon TCP connection is open. - + + Handle creation of the Connector. - + + Handle response to audio output device query - + + Handle response to audio input device query - + + + Set voice channel for new parcel + + + + + Request info from a parcel capability Uri. + - + + Receive parcel voice cap + + + - + + Tell Vivox where we are standing + This has to be called when we move or turn. - + + Start and stop updating out position. + - + + This is used to login a specific user account(s). It may only be called after + Connector initialization has completed successfully + Handle returned from successful Connector ‘create’ request + User's account name + User's account password + Values may be “AutoAnswer†or “VerifyAnswer†+ "" + This is an integer that specifies how often + the daemon will send participant property events while in a channel. If this is not set + the default will be “on state changeâ€, which means that the events will be sent when + the participant starts talking, stops talking, is muted, is unmuted. + The valid values are: + 0 – Never + 5 – 10 times per second + 10 – 5 times per second + 50 – 1 time per second + 100 – on participant state change (this is the default) + false + - + + This is used to logout a user session. It should only be called with a valid AccountHandle. + Handle returned from successful Connector ‘login’ request + - + + List of audio input devices - + + List of audio output devices - + + Set audio test mode - - No report - - - Unknown report type - - - Bug report - - - Complaint report - - - Customer service report - - + - Bitflag field for ObjectUpdateCompressed data blocks, describing - which options are present for each object + Event for most mundane request reposnses. - - Unknown - - - Whether the object has a TreeSpecies - - - Whether the object has floating text ala llSetText - - - Whether the object has an active particle system - - - Whether the object has sound attached to it - - - Whether the object is attached to a root object or not - - - Whether the object has texture animation settings - - - Whether the object has an angular velocity + + Response to Connector.Create request - - Whether the object has a name value pairs string + + Response to Aux.GetCaptureDevices request - - Whether the object has a Media URL set + + Response to Aux.GetRenderDevices request - - - Specific Flags for MultipleObjectUpdate requests - + + Audio Properties Events are sent after audio capture is started. + These events are used to display a microphone VU meter - - None + + Response to Account.Login request - - Change position of prims + + This event message is sent whenever the login state of the + particular Account has transitioned from one value to another - - Change rotation of prims + + Enable logging - - Change size of prims + + The folder where any logs will be created - - Perform operation on link set + + This will be prepended to beginning of each log file - - Scale prims uniformly, same as selecing ctrl+shift in the - viewer. Used in conjunction with Scale + + The suffix or extension to be appended to each log file - + - Special values in PayPriceReply. If the price is not one of these - literal value of the price should be use + 0: NONE - No logging + 1: ERROR - Log errors only + 2: WARNING - Log errors and warnings + 3: INFO - Log errors, warnings and info + 4: DEBUG - Log errors, warnings, info and debug - + - Indicates that this pay option should be hidden + Constructor for default logging settings - - - Indicates that this pay option should have the default value - + + Audio Properties Events are sent after audio capture is started. These events are used to display a microphone VU meter - + - Contains the variables sent in an object update packet for objects. - Used to track position and movement of prims and avatars + - - - + + - - - + + - - - + + - + + Thrown when a packet could not be successfully deserialized - + + Default constructor - + + Constructor that takes an additional error message + An error message to attach to this exception - + + The header of a message template packet. Holds packet flags, sequence + number, packet ID, and any ACKs that will be appended at the end of + the packet - + + Convert the AckList to a byte array, used for packet serializing + Reference to the target byte array + Beginning position to start writing to in the byte + array, will be updated with the ending position of the ACK list - + + + + + + - + + + + + - + - Handles all network traffic related to prims and avatar positions and - movement. + A block of data in a packet. Packets are composed of one or more blocks, + each block containing one or more fields - + - Construct a new instance of the ObjectManager class + Create a block from a byte array - A reference to the instance + Byte array containing the serialized block + Starting position of the block in the byte array. + This will point to the data after the end of the block when the + call returns - + - Callback for getting object media data via CAP + Serialize this block into a byte array - Indicates if the operation was succesfull - Object media version string - Array indexed on prim face of media entry data + Byte array to serialize this block into + Starting position in the byte array to serialize to. + This will point to the position directly after the end of the + serialized block when the call returns - - The event subscribers, null of no subscribers + + Current length of the data in this packet - - Thread sync lock object + + A generic value, not an actual packet type - - The event subscribers, null of no subscribers + + + Attempts to convert an LLSD structure to a known Packet type + + Event name, this must match an actual + packet name for a Packet to be successfully built + LLSD to convert to a Packet + A Packet on success, otherwise null - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - Reference to the GridClient object + + - - Does periodic dead reckoning calculation to convert - velocity and acceleration to new positions for objects + + - - Raised when the simulator sends us data containing - A , Foliage or Attachment - - + + - - Raised when the simulator sends us data containing - additional information - - + + - - Raised when the simulator sends us data containing - Primitive.ObjectProperties for an object we are currently tracking + + - - Raised when the simulator sends us data containing - additional and details - + + - - Raised when the simulator sends us data containing - updated information for an + + - - Raised when the simulator sends us data containing - and movement changes + + - - Raised when the simulator sends us data containing - updates to an Objects DataBlock + + - - Raised when the simulator informs us an - or is no longer within view + + - - Raised when the simulator sends us data containing - updated sit information for our + + - - Raised when the simulator sends us data containing - purchase price information for a + + - - Raises the ObjectProperties Event - A ObjectPropertiesEventArgs object containing - the data sent from the simulator + + - - Raises the ObjectPropertiesUpdated Event - A ObjectPropertiesUpdatedEventArgs object containing - the data sent from the simulator + + - - Raises the ObjectPropertiesFamily Event - A ObjectPropertiesFamilyEventArgs object containing - the data sent from the simulator + + - - Raises the AvatarUpdate Event - A AvatarUpdateEventArgs object containing - the data sent from the simulator + + - - Raises the ObjectDataBlockUpdate Event - A ObjectDataBlockUpdateEventArgs object containing - the data sent from the simulator + + - - Raises the KillObject Event - A KillObjectEventArgs object containing - the data sent from the simulator + + - - Raises the AvatarSitChanged Event - A AvatarSitChangedEventArgs object containing - the data sent from the simulator + + - - Raises the PayPriceReply Event - A PayPriceReplyEventArgs object containing - the data sent from the simulator + + - - - Request information for a single object from a - you are currently connected to - - The the object is located - The Local ID of the object + + - - - Request information for multiple objects contained in - the same simulator - - The the objects are located - An array containing the Local IDs of the objects + + - - - Attempt to purchase an original object, a copy, or the contents of - an object - - The the object is located - The Local ID of the object - Whether the original, a copy, or the object - contents are on sale. This is used for verification, if the this - sale type is not valid for the object the purchase will fail - Price of the object. This is used for - verification, if it does not match the actual price the purchase - will fail - Group ID that will be associated with the new - purchase - Inventory folder UUID where the object or objects - purchased should be placed - - - BuyObject(Client.Network.CurrentSim, 500, SaleType.Copy, - 100, UUID.Zero, Client.Self.InventoryRootFolderUUID); - - + + - - - Request prices that should be displayed in pay dialog. This will triggger the simulator - to send us back a PayPriceReply which can be handled by OnPayPriceReply event - - The the object is located - The ID of the object - The result is raised in the event + + - - - Select a single object. This will cause the to send us - an which will raise the event - - The the object is located - The Local ID of the object - + + - - - Select a single object. This will cause the to send us - an which will raise the event - - The the object is located - The Local ID of the object - if true, a call to is - made immediately following the request - + + - - - Select multiple objects. This will cause the to send us - an which will raise the event - - The the objects are located - An array containing the Local IDs of the objects - Should objects be deselected immediately after selection - + + - - - Select multiple objects. This will cause the to send us - an which will raise the event - - The the objects are located - An array containing the Local IDs of the objects - + + - - - Update the properties of an object - - The the object is located - The Local ID of the object - true to turn the objects physical property on - true to turn the objects temporary property on - true to turn the objects phantom property on - true to turn the objects cast shadows property on + + - - - Sets the sale properties of a single object - - The the object is located - The Local ID of the object - One of the options from the enum - The price of the object + + - - - Sets the sale properties of multiple objects - - The the objects are located - An array containing the Local IDs of the objects - One of the options from the enum - The price of the object + + - - - Deselect a single object - - The the object is located - The Local ID of the object + + - - - Deselect multiple objects. - - The the objects are located - An array containing the Local IDs of the objects + + - - - Perform a click action on an object - - The the object is located - The Local ID of the object + + - - - Perform a click action (Grab) on a single object - - The the object is located - The Local ID of the object - The texture coordinates to touch - The surface coordinates to touch - The face of the position to touch - The region coordinates of the position to touch - The surface normal of the position to touch (A normal is a vector perpindicular to the surface) - The surface binormal of the position to touch (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space + + - - - Create (rez) a new prim object in a simulator - - A reference to the object to place the object in - Data describing the prim object to rez - Group ID that this prim will be set to, or UUID.Zero if you - do not want the object to be associated with a specific group - An approximation of the position at which to rez the prim - Scale vector to size this prim - Rotation quaternion to rotate this prim - Due to the way client prim rezzing is done on the server, - the requested position for an object is only close to where the prim - actually ends up. If you desire exact placement you'll need to - follow up by moving the object after it has been created. This - function will not set textures, light and flexible data, or other - extended primitive properties + + - - - Create (rez) a new prim object in a simulator - - A reference to the object to place the object in - Data describing the prim object to rez - Group ID that this prim will be set to, or UUID.Zero if you - do not want the object to be associated with a specific group - An approximation of the position at which to rez the prim - Scale vector to size this prim - Rotation quaternion to rotate this prim - Specify the - Due to the way client prim rezzing is done on the server, - the requested position for an object is only close to where the prim - actually ends up. If you desire exact placement you'll need to - follow up by moving the object after it has been created. This - function will not set textures, light and flexible data, or other - extended primitive properties + + - - - Rez a Linden tree - - A reference to the object where the object resides - The size of the tree - The rotation of the tree - The position of the tree - The Type of tree - The of the group to set the tree to, - or UUID.Zero if no group is to be set - true to use the "new" Linden trees, false to use the old + + - - - Rez grass and ground cover - - A reference to the object where the object resides - The size of the grass - The rotation of the grass - The position of the grass - The type of grass from the enum - The of the group to set the tree to, - or UUID.Zero if no group is to be set + + - - - Set the textures to apply to the faces of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The texture data to apply + + - - - Set the textures to apply to the faces of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The texture data to apply - A media URL (not used) + + - - - Set the Light data on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set + + - - - Set the flexible data on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set + + - - - Set the sculptie texture and data on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set + + - - - Unset additional primitive parameters on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The extra parameters to set + + - - - Link multiple prims into a linkset - - A reference to the object where the objects reside - An array which contains the IDs of the objects to link - The last object in the array will be the root object of the linkset TODO: Is this true? + + - - - Delink/Unlink multiple prims from a linkset - - A reference to the object where the objects reside - An array which contains the IDs of the objects to delink + + - - - Change the rotation of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new rotation of the object + + - - - Set the name of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A string containing the new name of the object + + - - - Set the name of multiple objects - - A reference to the object where the objects reside - An array which contains the IDs of the objects to change the name of - An array which contains the new names of the objects + + - - - Set the description of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A string containing the new description of the object + + - - - Set the descriptions of multiple objects - - A reference to the object where the objects reside - An array which contains the IDs of the objects to change the description of - An array which contains the new descriptions of the objects + + - - - Attach an object to this avatar - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The point on the avatar the object will be attached - The rotation of the attached object + + - - - Drop an attached object from this avatar - - A reference to the - object where the objects reside. This will always be the simulator the avatar is currently in - - The object's ID which is local to the simulator the object is in + + - - - Detach an object from yourself - - A reference to the - object where the objects reside - This will always be the simulator the avatar is currently in - - An array which contains the IDs of the objects to detach + + - - - Change the position of an object, Will change position of entire linkset - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new position of the object + + - - - Change the position of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new position of the object - if true, will change position of (this) child prim only, not entire linkset + + - - - Change the Scale (size) of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new scale of the object - If true, will change scale of this prim only, not entire linkset - True to resize prims uniformly + + - - - Change the Rotation of an object that is either a child or a whole linkset - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new scale of the object - If true, will change rotation of this prim only, not entire linkset + + - - - Send a Multiple Object Update packet to change the size, scale or rotation of a primitive - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new rotation, size, or position of the target object - The flags from the Enum + + - - - Deed an object (prim) to a group, Object must be shared with group which - can be accomplished with SetPermissions() - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The of the group to deed the object to + + - - - Deed multiple objects (prims) to a group, Objects must be shared with group which - can be accomplished with SetPermissions() - - A reference to the object where the object resides - An array which contains the IDs of the objects to deed - The of the group to deed the object to + + - - - Set the permissions on multiple objects - - A reference to the object where the objects reside - An array which contains the IDs of the objects to set the permissions on - The new Who mask to set - The new Permissions mark to set - TODO: What does this do? + + - - - Request additional properties for an object - - A reference to the object where the object resides - - + + - - - Request additional properties for an object - - A reference to the object where the object resides - Absolute UUID of the object - Whether to require server acknowledgement of this request + + - - - Set the ownership of a list of objects to the specified group - - A reference to the object where the objects reside - An array which contains the IDs of the objects to set the group id on - The Groups ID + + - - - Update current URL of the previously set prim media - - UUID of the prim - Set current URL to this - Prim face number - Simulator in which prim is located + + - - - Set object media - - UUID of the prim - Array the length of prims number of faces. Null on face indexes where there is - no media, on faces which contain the media - Simulatior in which prim is located + + - - - Retrieve information about object media - - UUID of the primitive - Simulator where prim is located - Call this callback when done + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - - A terse object update, used when a transformation matrix or - velocity/acceleration for an object changes but nothing else - (scale/position/rotation/acceleration/velocity) - - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + + + + + + + + + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - - Setup construction data for a basic primitive shape - - Primitive shape to construct - Construction data that can be plugged into a + + - - - - - - - - - - - + + - - - - - - - + + - - - Set the Shape data of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - Data describing the prim shape + + - - - Set the Material data of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new material of the object + + - - - - - - - - - - - + + - - - - - - - - - - - + + - - Provides data for the event - - The event occurs when the simulator sends - an containing a Primitive, Foliage or Attachment data - Note 1: The event will not be raised when the object is an Avatar - Note 2: It is possible for the to be - raised twice for the same object if for example the primitive moved to a new simulator, then returned to the current simulator or - if an Avatar crosses the border into a new simulator and returns to the current simulator - - - The following code example uses the , , and - properties to display new Primitives and Attachments on the window. - - // Subscribe to the event that gives us prim and foliage information - Client.Objects.ObjectUpdate += Objects_ObjectUpdate; - private void Objects_ObjectUpdate(object sender, PrimEventArgs e) - { - Console.WriteLine("Primitive {0} {1} in {2} is an attachment {3}", e.Prim.ID, e.Prim.LocalID, e.Simulator.Name, e.IsAttachment); - } - - - - + + - - - Construct a new instance of the PrimEventArgs class - - The simulator the object originated from - The Primitive - The simulator time dilation - The prim was not in the dictionary before this update - true if the primitive represents an attachment to an agent + + - - Get the simulator the originated from + + - - Get the details + + - - true if the did not exist in the dictionary before this update (always true if object tracking has been disabled) + + - - true if the is attached to an + + - - Get the simulator Time Dilation + + - - Provides data for the event - - The event occurs when the simulator sends - an containing Avatar data - Note 1: The event will not be raised when the object is an Avatar - Note 2: It is possible for the to be - raised twice for the same avatar if for example the avatar moved to a new simulator, then returned to the current simulator - - - The following code example uses the property to make a request for the top picks - using the method in the class to display the names - of our own agents picks listings on the window. - - // subscribe to the AvatarUpdate event to get our information - Client.Objects.AvatarUpdate += Objects_AvatarUpdate; - Client.Avatars.AvatarPicksReply += Avatars_AvatarPicksReply; - private void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e) - { - // we only want our own data - if (e.Avatar.LocalID == Client.Self.LocalID) - { - // Unsubscribe from the avatar update event to prevent a loop - // where we continually request the picks every time we get an update for ourselves - Client.Objects.AvatarUpdate -= Objects_AvatarUpdate; - // make the top picks request through AvatarManager - Client.Avatars.RequestAvatarPicks(e.Avatar.ID); - } - } - private void Avatars_AvatarPicksReply(object sender, AvatarPicksReplyEventArgs e) - { - // we'll unsubscribe from the AvatarPicksReply event since we now have the data - // we were looking for - Client.Avatars.AvatarPicksReply -= Avatars_AvatarPicksReply; - // loop through the dictionary and extract the names of the top picks from our profile - foreach (var pickName in e.Picks.Values) - { - Console.WriteLine(pickName); - } - } - - - + + - - - Construct a new instance of the AvatarUpdateEventArgs class - - The simulator the packet originated from - The data - The simulator time dilation - The avatar was not in the dictionary before this update + + - - Get the simulator the object originated from + + - - Get the data + + - - Get the simulator time dilation + + - - true if the did not exist in the dictionary before this update (always true if avatar tracking has been disabled) + + - - Provides additional primitive data for the event - - The event occurs when the simulator sends - an containing additional details for a Primitive, Foliage data or Attachment data - The event is also raised when a request is - made. - - - The following code example uses the , and - - properties to display new attachments and send a request for additional properties containing the name of the - attachment then display it on the window. - - // Subscribe to the event that provides additional primitive details - Client.Objects.ObjectProperties += Objects_ObjectProperties; - // handle the properties data that arrives - private void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e) - { - Console.WriteLine("Primitive Properties: {0} Name is {1}", e.Properties.ObjectID, e.Properties.Name); - } - + + - - - Construct a new instance of the ObjectPropertiesEventArgs class - - The simulator the object is located - The primitive Properties + + - - Get the simulator the object is located + + - - Get the primitive properties + + - - Provides additional primitive data for the event - - The event occurs when the simulator sends - an containing additional details for a Primitive or Foliage data that is currently - being tracked in the dictionary - The event is also raised when a request is - made and is enabled - + + - - - Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class - - The simulator the object is located - The Primitive - The primitive Properties + + - - Get the simulator the object is located + + - - Get the primitive details + + - - Get the primitive properties + + - - Provides additional primitive data, permissions and sale info for the event - - The event occurs when the simulator sends - an containing additional details for a Primitive, Foliage data or Attachment. This includes - Permissions, Sale info, and other basic details on an object - The event is also raised when a request is - made, the viewer equivalent is hovering the mouse cursor over an object - + + - - Get the simulator the object is located + + - - - + + - - - + + - - Provides primitive data containing updated location, velocity, rotation, textures for the event - - The event occurs when the simulator sends updated location, velocity, rotation, etc - + + - - Get the simulator the object is located + + - - Get the primitive details + + - - - + + - - - + + - - - + + - - Get the simulator the object is located + + - - Get the primitive details + + - - - + + - - - + + - - - + + - - - + + - - Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the - event + + - - Get the simulator the object is located + + - - The LocalID of the object + + - - - Provides updates sit position data - + + - - Get the simulator the object is located + + - - - + + + + + + + + - - - + + - - - + + - - - + + - - Get the simulator the object is located + + - - - + + - - - + + - - - + + - - - Indicates if the operation was successful - + + - - - Media version string - + + - - - Array of media entries indexed by face number - + + - - - Create an allocated UDP packet buffer for receiving a packet - + + - - - Create an allocated UDP packet buffer for sending a packet - - EndPoint of the remote host + + - - - Create an allocated UDP packet buffer for sending a packet - - EndPoint of the remote host - Size of the buffer to allocate for packet data + + - - Size of the byte array used to store raw packet data + + - - Raw packet data buffer + + - - Length of the data to transmit + + - - EndPoint of the remote host + + - - - Object pool for packet buffers. This is used to allocate memory for all - incoming and outgoing packets, and zerocoding buffers for those packets - + + - - - Initialize the object pool in client mode - - Server to connect to - - - - + + - - - Initialize the object pool in server mode - - - - - + + - - - Returns a packet buffer with EndPoint set if the buffer is in - client mode, or with EndPoint set to null in server mode - - Initialized UDPPacketBuffer object + + - - - Default constructor - + + - - - Check a packet buffer out of the pool - - A packet buffer object + + - - - Returns an instance of the class that has been checked out of the Object Pool. - + + - - - Checks the instance back into the object pool - + + - - - Creates a new instance of the ObjectPoolBase class. Initialize MUST be called - after using this constructor. - + + - - - Creates a new instance of the ObjectPool Base class. - - The object pool is composed of segments, which - are allocated whenever the size of the pool is exceeded. The number of items - in a segment should be large enough that allocating a new segmeng is a rare - thing. For example, on a server that will have 10k people logged in at once, - the receive buffer object pool should have segment sizes of at least 1000 - byte arrays per segment. - - The minimun number of segments that may exist. - Perform a full GC.Collect whenever a segment is allocated, and then again after allocation to compact the heap. - The frequency which segments are checked to see if they're eligible for cleanup. + + - - - The total number of segments created. Intended to be used by the Unit Tests. - + + - - - The number of items that are in a segment. Items in a segment - are all allocated at the same time, and are hopefully close to - each other in the managed heap. - + + - - - The minimum number of segments. When segments are reclaimed, - this number of segments will always be left alone. These - segments are allocated at startup. - + + - - - The age a segment must be before it's eligible for cleanup. - This is used to prevent thrash, and typical values are in - the 5 minute range. - + + - - - The frequence which the cleanup thread runs. This is typically - expected to be in the 5 minute range. - + + - - - Forces the segment cleanup algorithm to be run. This method is intended - primarly for use from the Unit Test libraries. - + + - - - Responsible for allocate 1 instance of an object that will be stored in a segment. - - An instance of whatever objec the pool is pooling. + + - - - Checks in an instance of T owned by the object pool. This method is only intended to be called - by the WrappedObject class. - - The segment from which the instance is checked out. - The instance of T to check back into the segment. + + - - - Checks an instance of T from the pool. If the pool is not sufficient to - allow the checkout, a new segment is created. - - A WrappedObject around the instance of T. To check - the instance back into the segment, be sureto dispose the WrappedObject - when finished. + + - - - + + - - - + + - - - + + - - - + + - - - The ObservableDictionary class is used for storing key/value pairs. It has methods for firing - events to subscribers when items are added, removed, or changed. - - Key - Value + + - - - Initializes a new instance of the Class - with the specified key/value, has the default initial capacity. - - - - // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value. - public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(); - - + + - - - Initializes a new instance of the Class - with the specified key/value, With its initial capacity specified. - - Initial size of dictionary - - - // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value, - // initially allocated room for 10 entries. - public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(10); - - + + - - - A dictionary of callbacks to fire when specified action occurs - + + - - Internal dictionary that this class wraps around. Do not - modify or enumerate the contents of this dictionary without locking + + - - - Indexer for the dictionary - - The key - The value + + - - - Gets the number of Key/Value pairs contained in the + + - - - Register a callback to be fired when an action occurs - - The action - The callback to fire + + + + + - - - Unregister a callback - - The action - The callback to fire + + - - - - - - - + + - - - Try to get entry from the with specified key - - Key to use for lookup - Value returned - - if specified key exists, if not found - - - // find your avatar using the Simulator.ObjectsAvatars ObservableDictionary: - Avatar av; - if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) - Console.WriteLine("Found Avatar {0}", av.Name); - - - + + - - - Finds the specified match. - - The match. - Matched value - - - // use a delegate to find a prim in the ObjectsPrimitives ObservableDictionary - // with the ID 95683496 - uint findID = 95683496; - Primitive findPrim = sim.ObjectsPrimitives.Find( - delegate(Primitive prim) { return prim.ID == findID; }); - - + + - - Find All items in an - return matching items. - a containing found items. - - Find All prims within 20 meters and store them in a List - - int radius = 20; - List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( - delegate(Primitive prim) { - Vector3 pos = prim.Position; - return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); - } - ); - + + - - Find All items in an - return matching keys. - a containing found keys. - - Find All keys which also exist in another dictionary - - List<UUID> matches = myDict.FindAll( - delegate(UUID id) { - return myOtherDict.ContainsKey(id); - } - ); - + + - - Check if Key exists in Dictionary - Key to check for - - if found, otherwise + + - - Check if Value exists in Dictionary - Value to check for - - if found, otherwise + + - - - Adds the specified key to the dictionary, dictionary locking is not performed, - - The key - The value + + - - - Removes the specified key, dictionary locking is not performed - - The key. - - if successful, otherwise + + - - - Clear the contents of the dictionary - + + - - - Enumerator for iterating dictionary entries - - - + + - - - A custom decoder callback - - The key of the object - the data to decode - A string represending the fieldData + + - - - Add a custom decoder callback - - The key of the field to decode - The custom decode handler + + - - - Remove a custom decoder callback - - The key of the field to decode - The custom decode handler + + - - - Creates a formatted string containing the values of a Packet - - The Packet - A formatted string of values of the nested items in the Packet object + + - - - Decode an IMessage object into a beautifully formatted string - - The IMessage object - Recursion level (used for indenting) - A formatted string containing the names and values of the source object + + - - - Type of return to use when returning objects from a parcel - + + - - - + + - - Return objects owned by parcel owner + + - - Return objects set to group + + - - Return objects not owned by parcel owner or set to group + + - - Return a specific list of objects on parcel + + - - Return objects that are marked for-sale + + - - - Blacklist/Whitelist flags used in parcels Access List - + + - - Agent is denied access + + - - Agent is granted access + + - - - The result of a request for parcel properties - + + - - No matches were found for the request + + - - Request matched a single parcel + + - - Request matched multiple parcels + + - - - Flags used in the ParcelAccessListRequest packet to specify whether - we want the access list (whitelist), ban list (blacklist), or both - + + - - Request the access list + + - - Request the ban list + + - - Request both White and Black lists + + - - - Sequence ID in ParcelPropertiesReply packets (sent when avatar - tries to cross a parcel border) - + + - - Parcel is currently selected + + - - Parcel restricted to a group the avatar is not a - member of + + - - Avatar is banned from the parcel + + - - Parcel is restricted to an access list that the - avatar is not on + + - - Response to hovering over a parcel + + - - - The tool to use when modifying terrain levels - + + - - Level the terrain + + - - Raise the terrain + + - - Lower the terrain + + - - Smooth the terrain + + - - Add random noise to the terrain + + - - Revert terrain to simulator default + + - - - The tool size to use when changing terrain levels - + + - - Small + + - - Medium + + - - Large + + - - - Reasons agent is denied access to a parcel on the simulator - + + - - Agent is not denied, access is granted + + - - Agent is not a member of the group set for the parcel, or which owns the parcel + + - - Agent is not on the parcels specific allow list + + + + + - - Agent is on the parcels ban list + + - - Unknown + + - - Agent is not age verified and parcel settings deny access to non age verified avatars + + - - - Parcel overlay type. This is used primarily for highlighting and - coloring which is why it is a single integer instead of a set of - flags - - These values seem to be poorly thought out. The first three - bits represent a single value, not flags. For example Auction (0x05) is - not a combination of OwnedByOther (0x01) and ForSale(0x04). However, - the BorderWest and BorderSouth values are bit flags that get attached - to the value stored in the first three bits. Bits four, five, and six - are unused + + - - Public land + + - - Land is owned by another avatar + + - - Land is owned by a group + + - - Land is owned by the current avatar + + - - Land is for sale + + - - Land is being auctioned + + - - To the west of this area is a parcel border + + - - To the south of this area is a parcel border + + - - - Various parcel properties - + + - - No flags set + + - - Allow avatars to fly (a client-side only restriction) + + - - Allow foreign scripts to run + + - - This parcel is for sale + + - - Allow avatars to create a landmark on this parcel + + - - Allows all avatars to edit the terrain on this parcel + + - - Avatars have health and can take damage on this parcel. - If set, avatars can be killed and sent home here + + - - Foreign avatars can create objects here + + - - All objects on this parcel can be purchased + + - - Access is restricted to a group + + - - Access is restricted to a whitelist + + - - Ban blacklist is enabled + + - - Unknown + + - - List this parcel in the search directory + + - - Allow personally owned parcels to be deeded to group + + - - If Deeded, owner contributes required tier to group parcel is deeded to + + - - Restrict sounds originating on this parcel to the - parcel boundaries + + - - Objects on this parcel are sold when the land is - purchsaed + + - - Allow this parcel to be published on the web + + - - The information for this parcel is mature content + + - - The media URL is an HTML page + + - - The media URL is a raw HTML string + + - - Restrict foreign object pushes + + - - Ban all non identified/transacted avatars + + - - Allow group-owned scripts to run + + - - Allow object creation by group members or group - objects + + - - Allow all objects to enter this parcel + + - - Only allow group and owner objects to enter this parcel + + - - Voice Enabled on this parcel + + - - Use Estate Voice channel for Voice on this parcel + + - - Deny Age Unverified Users + + - - - Parcel ownership status - + + - - Placeholder + + - - Parcel is leased (owned) by an avatar or group + + - - Parcel is in process of being leased (purchased) by an avatar or group + + - - Parcel has been abandoned back to Governor Linden + + - - - Category parcel is listed in under search - + + - - No assigned category + + - - Linden Infohub or public area + + - - Adult themed area + + - - Arts and Culture + + - - Business + + - - Educational + + - - Gaming + + - - Hangout or Club + + - - Newcomer friendly + + - - Parks and Nature + + - - Residential + + - - Shopping + + - - Not Used? + + - - Other + + - - Not an actual category, only used for queries + + - - - Type of teleport landing for a parcel - + + - - Unset, simulator default + + - - Specific landing point set for this parcel + + - - No landing point set, direct teleports enabled for - this parcel + + - - - Parcel Media Command used in ParcelMediaCommandMessage - + + - - Stop the media stream and go back to the first frame + + - - Pause the media stream (stop playing but stay on current frame) + + - - Start the current media stream playing and stop when the end is reached + + - - Start the current media stream playing, - loop to the beginning when the end is reached and continue to play + + - - Specifies the texture to replace with video - If passing the key of a texture, it must be explicitly typecast as a key, - not just passed within double quotes. + + - - Specifies the movie URL (254 characters max) + + - - Specifies the time index at which to begin playing + + + + + - - Specifies a single agent to apply the media command to + + - - Unloads the stream. While the stop command sets the texture to the first frame of the movie, - unload resets it to the real texture that the movie was replacing. + + - - Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties - (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter. + + - - Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only). - Use "text/html" for HTML. + + - - Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only). - This might still not be working + + - - Sets a description for the media being displayed (1.19.1 RC0 and later only). + + - - - Some information about a parcel of land returned from a DirectoryManager search - + + - - Global Key of record + + - - Parcel Owners + + - - Name field of parcel, limited to 128 characters + + - - Description field of parcel, limited to 256 characters + + - - Total Square meters of parcel + + - - Total area billable as Tier, for group owned land this will be 10% less than ActualArea + + - - True of parcel is in Mature simulator + + - - Grid global X position of parcel + + - - Grid global Y position of parcel + + - - Grid global Z position of parcel (not used) + + - - Name of simulator parcel is located in + + - - Texture of parcels display picture + + - - Float representing calculated traffic based on time spent on parcel by avatars + + - - Sale price of parcel (not used) + + - - Auction ID of parcel + + - - - Parcel Media Information - + + - - A byte, if 0x1 viewer should auto scale media to fit object + + - - A boolean, if true the viewer should loop the media + + - - The Asset UUID of the Texture which when applied to a - primitive will display the media + + - - A URL which points to any Quicktime supported media type + + - - A description of the media + + - - An Integer which represents the height of the media + + - - An integer which represents the width of the media + + - - A string which contains the mime type of the media + + - - - Parcel of land, a portion of virtual real estate in a simulator - + + - - - Defalt constructor - - Local ID of this parcel + + - - The total number of contiguous 4x4 meter blocks your agent owns within this parcel + + - - The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own + + - - Deprecated, Value appears to always be 0 + + - - Simulator-local ID of this parcel + + - - UUID of the owner of this parcel + + - - Whether the land is deeded to a group or not + + - - - + + - - Date land was claimed + + - - Appears to always be zero + + - - This field is no longer used + + - - Minimum corner of the axis-aligned bounding box for this - parcel + + - - Maximum corner of the axis-aligned bounding box for this - parcel + + - - Bitmap describing land layout in 4x4m squares across the - entire region + + - - Total parcel land area + + - - - + + - - Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used + + - - Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel - owned by the agent or group that owns this parcel + + - - Maximum number of primitives this parcel supports + + - - Total number of primitives on this parcel + + - - For group-owned parcels this indicates the total number of prims deeded to the group, - for parcels owned by an individual this inicates the number of prims owned by the individual + + - - Total number of primitives owned by the parcel group on - this parcel, or for parcels owned by an individual with a group set the - total number of prims set to that group. + + - - Total number of prims owned by other avatars that are not set to group, or not the parcel owner + + - - A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect - the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed + + - - Autoreturn value in minutes for others' objects + + - - - + + - - Sale price of the parcel, only useful if ForSale is set - The SalePrice will remain the same after an ownership - transfer (sale), so it can be used to see the purchase price after - a sale if the new owner has not changed it + + - - Parcel Name + + - - Parcel Description + + - - URL For Music Stream + + - - - + + - - Price for a temporary pass + + - - How long is pass valid for + + - - - + + - - Key of authorized buyer + + - - Key of parcel snapshot + + - - The landing point location + + - - The landing point LookAt + + - - The type of landing enforced from the enum + + - - - + + - - - + + - - - + + - - Access list of who is whitelisted on this - parcel + + - - Access list of who is blacklisted on this - parcel + + - - TRUE of region denies access to age unverified users + + - - true to obscure (hide) media url + + - - true to obscure (hide) music url + + - - A struct containing media details + + - - - Displays a parcel object in string format - - string containing key=value pairs of a parcel object + + - - - Update the simulator with any local changes to this Parcel object - - Simulator to send updates to - Whether we want the simulator to confirm - the update with a reply packet or not + + - - - Set Autoreturn time - - Simulator to send the update to + + - - - Parcel (subdivided simulator lots) subsystem - + + - - - Default constructor - - A reference to the GridClient object + + - - - Parcel Accesslist - + + - - Agents + + - - - + + - - Flags for specific entry in white/black lists + + - - - Owners of primitives on parcel - + + - - Prim Owners + + - - True of owner is group + + - - Total count of prims owned by OwnerID + + - - true of OwnerID is currently online and is not a group + + - - The date of the most recent prim left by OwnerID + + - - - Called once parcel resource usage information has been collected - - Indicates if operation was successfull - Parcel resource usage information + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a request + + - - Raised when the simulator responds to a Parcel Update request + + - - Raised when the parcel your agent is located sends a ParcelMediaCommand + + - - Raises the ParcelDwellReply event - A ParcelDwellReplyEventArgs object containing the - data returned from the simulator + + - - Raises the ParcelInfoReply event - A ParcelInfoReplyEventArgs object containing the - data returned from the simulator + + - - Raises the ParcelProperties event - A ParcelPropertiesEventArgs object containing the - data returned from the simulator + + - - Raises the ParcelAccessListReply event - A ParcelAccessListReplyEventArgs object containing the - data returned from the simulator + + - - Raises the ParcelObjectOwnersReply event - A ParcelObjectOwnersReplyEventArgs object containing the - data returned from the simulator + + - - Raises the SimParcelsDownloaded event - A SimParcelsDownloadedEventArgs object containing the - data returned from the simulator + + - - Raises the ForceSelectObjectsReply event - A ForceSelectObjectsReplyEventArgs object containing the - data returned from the simulator + + - - Raises the ParcelMediaUpdateReply event - A ParcelMediaUpdateReplyEventArgs object containing the - data returned from the simulator + + - - Raises the ParcelMediaCommand event - A ParcelMediaCommandEventArgs object containing the - data returned from the simulator + + - - - Request basic information for a single parcel - - Simulator-local ID of the parcel + + - - - Request properties of a single parcel - - Simulator containing the parcel - Simulator-local ID of the parcel - An arbitrary integer that will be returned - with the ParcelProperties reply, useful for distinguishing between - multiple simultaneous requests + + - - - Request the access list for a single parcel - - Simulator containing the parcel - Simulator-local ID of the parcel - An arbitrary integer that will be returned - with the ParcelAccessList reply, useful for distinguishing between - multiple simultaneous requests - - + + - - - Request properties of parcels using a bounding box selection - - Simulator containing the parcel - Northern boundary of the parcel selection - Eastern boundary of the parcel selection - Southern boundary of the parcel selection - Western boundary of the parcel selection - An arbitrary integer that will be returned - with the ParcelProperties reply, useful for distinguishing between - different types of parcel property requests - A boolean that is returned with the - ParcelProperties reply, useful for snapping focus to a single - parcel + + - - - Request all simulator parcel properties (used for populating the Simulator.Parcels - dictionary) - - Simulator to request parcels from (must be connected) + + - - - Request all simulator parcel properties (used for populating the Simulator.Parcels - dictionary) - - Simulator to request parcels from (must be connected) - If TRUE, will force a full refresh - Number of milliseconds to pause in between each request + + - - - Request the dwell value for a parcel - - Simulator containing the parcel - Simulator-local ID of the parcel + + - - - Send a request to Purchase a parcel of land - - The Simulator the parcel is located in - The parcels region specific local ID - true if this parcel is being purchased by a group - The groups - true to remove tier contribution if purchase is successful - The parcels size - The purchase price of the parcel - - + + - - - Reclaim a parcel of land - - The simulator the parcel is in - The parcels region specific local ID + + - - - Deed a parcel to a group - - The simulator the parcel is in - The parcels region specific local ID - The groups + + - - - Request prim owners of a parcel of land. - - Simulator parcel is in - The parcels region specific local ID + + - - - Return objects from a parcel - - Simulator parcel is in - The parcels region specific local ID - the type of objects to return, - A list containing object owners s to return + + - - - Subdivide (split) a parcel - - - - - - - - - - - + + - - - Join two parcels of land creating a single parcel - - - - - - - - - - - + + - - - Get a parcels LocalID - - Simulator parcel is in - Vector3 position in simulator (Z not used) - 0 on failure, or parcel LocalID on success. - A call to Parcels.RequestAllSimParcels is required to populate map and - dictionary. + + - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() + + - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() + + - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - How many meters + or - to lower, 1 = 1 meter - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() + + - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - How many meters + or - to lower, 1 = 1 meter - Height at which the terraform operation is acting at + + - - - Sends a request to the simulator to return a list of objects owned by specific owners - - Simulator local ID of parcel - Owners, Others, Etc - List containing keys of avatars objects to select; - if List is null will return Objects of type selectType - Response data is returned in the event + + - - - Eject and optionally ban a user from a parcel - - target key of avatar to eject - true to also ban target + + - - - Freeze or unfreeze an avatar over your land - - target key to freeze - true to freeze, false to unfreeze + + - - - Abandon a parcel of land - - Simulator parcel is in - Simulator local ID of parcel + + - - - Requests the UUID of the parcel in a remote region at a specified location - - Location of the parcel in the remote region - Remote region handle - Remote region UUID - If successful UUID of the remote parcel, UUID.Zero otherwise + + - - - Retrieves information on resources used by the parcel - - UUID of the parcel - Should per object resource usage be requested - Callback invoked when the request is complete + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event + + - - Contains a parcels dwell data returned from the simulator in response to an + + - - - Construct a new instance of the ParcelDwellReplyEventArgs class - - The global ID of the parcel - The simulator specific ID of the parcel - The calculated dwell for the parcel + + - - Get the global ID of the parcel + + - - Get the simulator specific ID of the parcel + + - - Get the calculated dwell + + - - Contains basic parcel information data returned from the - simulator in response to an request + + - - - Construct a new instance of the ParcelInfoReplyEventArgs class - - The object containing basic parcel info + + - - Get the object containing basic parcel info + + - - Contains basic parcel information data returned from the simulator in response to an request + + - - - Construct a new instance of the ParcelPropertiesEventArgs class - - The object containing the details - The object containing the details - The result of the request - The number of primitieves your agent is - currently selecting and or sitting on in this parcel - The user assigned ID used to correlate a request with - these results - TODO: + + - - Get the simulator the parcel is located in + + - - Get the object containing the details - If Result is NoData, this object will not contain valid data + + - - Get the result of the request + + - - Get the number of primitieves your agent is - currently selecting and or sitting on in this parcel + + - - Get the user assigned ID used to correlate a request with - these results + + - - TODO: + + - - Contains blacklist and whitelist data returned from the simulator in response to an request + + - - - Construct a new instance of the ParcelAccessListReplyEventArgs class - - The simulator the parcel is located in - The user assigned ID used to correlate a request with - these results - The simulator specific ID of the parcel - TODO: - The list containing the white/blacklisted agents for the parcel + + - - Get the simulator the parcel is located in + + - - Get the user assigned ID used to correlate a request with - these results + + - - Get the simulator specific ID of the parcel + + - - TODO: + + - - Get the list containing the white/blacklisted agents for the parcel + + - - Contains blacklist and whitelist data returned from the - simulator in response to an request + + - - - Construct a new instance of the ParcelObjectOwnersReplyEventArgs class - - The simulator the parcel is located in - The list containing prim ownership counts + + - - Get the simulator the parcel is located in + + - - Get the list containing prim ownership counts + + - - Contains the data returned when all parcel data has been retrieved from a simulator + + - - - Construct a new instance of the SimParcelsDownloadedEventArgs class - - The simulator the parcel data was retrieved from - The dictionary containing the parcel data - The multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. + + - - Get the simulator the parcel data was retrieved from + + - - A dictionary containing the parcel data where the key correlates to the ParcelMap entry + + - - Get the multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. + + - - Contains the data returned when a request + + - - - Construct a new instance of the ForceSelectObjectsReplyEventArgs class - - The simulator the parcel data was retrieved from - The list of primitive IDs - true if the list is clean and contains the information - only for a given request + + - - Get the simulator the parcel data was retrieved from + + - - Get the list of primitive IDs + + - - true if the list is clean and contains the information - only for a given request + + - - Contains data when the media data for a parcel the avatar is on changes + + - - - Construct a new instance of the ParcelMediaUpdateReplyEventArgs class - - the simulator the parcel media data was updated in - The updated media information + + - - Get the simulator the parcel media data was updated in + + - - Get the updated media information + + - - Contains the media command for a parcel the agent is currently on + + - - - Construct a new instance of the ParcelMediaCommandEventArgs class - - The simulator the parcel media command was issued in - - - - - The media command that was sent - - + + - - Get the simulator the parcel media command was issued in + + - - - + + - - - + + - - Get the media command that was sent + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - - - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - - - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - - - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - - - + + - - - + + - - - - - - - + + - - - - - - - + + - - - - - + + - - - Class for controlling various system settings. - - Some values are readonly because they affect things that - happen when the GridClient object is initialized, so changing them at - runtime won't do any good. Non-readonly values may affect things that - happen at login or dynamically + + - - Constructor - Reference to a GridClient object + + - - Main grid login server + + - - Beta grid login server + + - - - InventoryManager requests inventory information on login, - GridClient initializes an Inventory store for main inventory. - + + - - - InventoryManager requests library information on login, - GridClient initializes an Inventory store for the library. - + + - - Number of milliseconds between sending pings to each sim + + - - Number of milliseconds between sending camera updates + + - - Number of milliseconds between updating the current - positions of moving, non-accelerating and non-colliding objects + + - - Millisecond interval between ticks, where all ACKs are - sent out and the age of unACKed packets is checked + + - - The initial size of the packet inbox, where packets are - stored before processing + + - - Maximum size of packet that we want to send over the wire + + - - The maximum value of a packet sequence number before it - rolls over back to one + + - - The maximum size of the sequence number archive, used to - check for resent and/or duplicate packets + + - - The relative directory where external resources are kept + + - - Login server to connect to + + - - IP Address the client will bind to + + - - Use XML-RPC Login or LLSD Login, default is XML-RPC Login + + - - Number of milliseconds before an asset transfer will time - out + + - - Number of milliseconds before a teleport attempt will time - out + + - - Number of milliseconds before NetworkManager.Logout() will - time out + + - - Number of milliseconds before a CAPS call will time out - Setting this too low will cause web requests time out and - possibly retry repeatedly + + - - Number of milliseconds for xml-rpc to timeout + + - - Milliseconds before a packet is assumed lost and resent + + + + + - - Milliseconds without receiving a packet before the - connection to a simulator is assumed lost + + - - Milliseconds to wait for a simulator info request through - the grid interface + + - - Maximum number of queued ACKs to be sent before SendAcks() - is forced + + - - Network stats queue length (seconds) + + - - Enable/disable storing terrain heightmaps in the - TerrainManager + + - - Enable/disable sending periodic camera updates + + - - Enable/disable automatically setting agent appearance at - login and after sim crossing + + - - Enable/disable automatically setting the bandwidth throttle - after connecting to each simulator - The default throttle uses the equivalent of the maximum - bandwidth setting in the official client. If you do not set a - throttle your connection will by default be throttled well below - the minimum values and you may experience connection problems + + - - Enable/disable the sending of pings to monitor lag and - packet loss + + - - Should we connect to multiple sims? This will allow - viewing in to neighboring simulators and sim crossings - (Experimental) + + - - If true, all object update packets will be decoded in to - native objects. If false, only updates for our own agent will be - decoded. Registering an event handler will force objects for that - type to always be decoded. If this is disabled the object tracking - will have missing or partial prim and avatar information + + - - If true, when a cached object check is received from the - server the full object info will automatically be requested + + - - Whether to establish connections to HTTP capabilities - servers for simulators + + - - Whether to decode sim stats + + - - The capabilities servers are currently designed to - periodically return a 502 error which signals for the client to - re-establish a connection. Set this to true to log those 502 errors + + - - If true, any reference received for a folder or item - the library is not aware of will automatically be fetched + + - - If true, and SEND_AGENT_UPDATES is true, - AgentUpdate packets will continuously be sent out to give the bot - smoother movement and autopiloting + + - - If true, currently visible avatars will be stored - in dictionaries inside Simulator.ObjectAvatars. - If false, a new Avatar or Primitive object will be created - each time an object update packet is received + + - - If true, currently visible avatars will be stored - in dictionaries inside Simulator.ObjectPrimitives. - If false, a new Avatar or Primitive object will be created - each time an object update packet is received + + - - If true, position and velocity will periodically be - interpolated (extrapolated, technically) for objects and - avatars that are being tracked by the library. This is - necessary to increase the accuracy of speed and position - estimates for simulated objects + + - - - If true, utilization statistics will be tracked. There is a minor penalty - in CPU time for enabling this option. - + + - - If true, parcel details will be stored in the - Simulator.Parcels dictionary as they are received + + - - - If true, an incoming parcel properties reply will automatically send - a request for the parcel access list - + + - - - if true, an incoming parcel properties reply will automatically send - a request for the traffic count. - + + - - - If true, images, and other assets downloaded from the server - will be cached in a local directory - + + - - Path to store cached texture data + + - - Maximum size cached files are allowed to take on disk (bytes) + + - - Default color used for viewer particle effects + + - - Maximum number of times to resend a failed packet + + - - Throttle outgoing packet rate + + - - UUID of a texture used by some viewers to indentify type of client used + + - - - Download textures using GetTexture capability when available - + + - - The maximum number of concurrent texture downloads allowed - Increasing this number will not necessarily increase texture retrieval times due to - simulator throttles + + - - - The Refresh timer inteval is used to set the delay between checks for stalled texture downloads - - This is a static variable which applies to all instances + + - - - Textures taking longer than this value will be flagged as timed out and removed from the pipeline - + + - - - Get or set the minimum log level to output to the console by default - If the library is not compiled with DEBUG defined and this level is set to DEBUG - You will get no output on the console. This behavior can be overriden by creating - a logger configuration file for log4net - + + - - Attach avatar names to log messages + + - - Log packet retransmission info + + - - Cost of uploading an asset - Read-only since this value is dynamically fetched at login + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - - Simulator (region) properties - + + - - No flags set + + - - Agents can take damage and be killed + + - - Landmarks can be created here + + - - Home position can be set in this sim + + - - Home position is reset when an agent teleports away + + - - Sun does not move + + - - No object, land, etc. taxes + + - - Disable heightmap alterations (agents can still plant - foliage) + + - - Land cannot be released, sold, or purchased + + - - All content is wiped nightly + + - - Unknown: Related to the availability of an overview world map tile.(Think mainland images when zoomed out.) + + - - Unknown: Related to region debug flags. Possibly to skip processing of agent interaction with world. + + - - Region does not update agent prim interest lists. Internal debugging option. + + - - No collision detection for non-agent objects + + - - No scripts are ran + + - - All physics processing is turned off + + - - Region can be seen from other regions on world map. (Legacy world map option?) + + - - Region can be seen from mainland on world map. (Legacy world map option?) + + - - Agents not explicitly on the access list can visit the region. + + - - Traffic calculations are not run across entire region, overrides parcel settings. + + - - Flight is disabled (not currently enforced by the sim) + + - - Allow direct (p2p) teleporting + + - - Estate owner has temporarily disabled scripting + + - - Restricts the usage of the LSL llPushObject function, applies to whole region. + + + + + - - Deny agents with no payment info on file + + - - Deny agents with payment info on file + + - - Deny agents who have made a monetary transaction + + - - Parcels within the region may be joined or divided by anyone, not just estate owners/managers. + + - - Abuse reports sent from within this region are sent to the estate owner defined email. + + - - Region is Voice Enabled + + - - Removes the ability from parcel owners to set their parcels to show in search. + + - - Deny agents who have not been age verified from entering the region. + + - - - Access level for a simulator - + + - - Unknown or invalid access level + + - - Trial accounts allowed + + - - PG rating + + - - Mature rating + + - - Adult rating + + - - Simulator is offline + + - - Simulator does not exist + + - - - + + - - - - Reference to the GridClient object - IPEndPoint of the simulator - handle of the simulator + + - - - Simulator Statistics - + + - - Total number of packets sent by this simulator to this agent + + - - Total number of packets received by this simulator to this agent + + - - Total number of bytes sent by this simulator to this agent + + - - Total number of bytes received by this simulator to this agent + + - - Time in seconds agent has been connected to simulator + + - - Total number of packets that have been resent + + - - Total number of resent packets recieved + + - - Total number of pings sent to this simulator by this agent + + - - Total number of ping replies sent to this agent by this simulator + + - - - Incoming bytes per second - - It would be nice to have this claculated on the fly, but - this is far, far easier + + - - - Outgoing bytes per second - - It would be nice to have this claculated on the fly, but - this is far, far easier + + - - Time last ping was sent + + - - ID of last Ping sent + + - - - + + - - - + + - - Current time dilation of this simulator + + - - Current Frames per second of simulator + + - - Current Physics frames per second of simulator + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - Total number of objects Simulator is simulating + + - - Total number of Active (Scripted) objects running + + - - Number of agents currently in this simulator + + - - Number of agents in neighbor simulators + + - - Number of Active scripts running in this simulator + + - - - + + - - - + + - - - + + - - Number of downloads pending + + - - Number of uploads pending + + - - - + + - - - + + - - Number of local uploads pending + + - - Unacknowledged bytes in queue + + - - A public reference to the client that this Simulator object - is attached to + + - - A Unique Cache identifier for this simulator + + - - The capabilities for this simulator + + - - - + + - - The current version of software this simulator is running + + - - - + + - - A 64x64 grid of parcel coloring values. The values stored - in this array are of the type + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - true if your agent has Estate Manager rights on this region + + - - - + + - - - + + - - - + + - - Statistics information for this simulator and the - connection to the simulator, calculated by the simulator itself - and the library + + - - The regions Unique ID + + - - The physical data center the simulator is located - Known values are: - DallasChandlerSF + + - - The CPU Class of the simulator - Most full mainland/estate sims appear to be 5, - Homesteads and Openspace appear to be 501 + + - - The number of regions sharing the same CPU as this one - "Full Sims" appear to be 1, Homesteads appear to be 4 + + - - The billing product name - Known values are: - Mainland / Full Region (Sku: 023)Estate / Full Region (Sku: 024)Estate / Openspace (Sku: 027)Estate / Homestead (Sku: 029)Mainland / Homestead (Sku: 129) (Linden Owned)Mainland / Linden Homes (Sku: 131) + + - - The billing product SKU - Known values are: - 023 Mainland / Full Region024 Estate / Full Region027 Estate / Openspace029 Estate / Homestead129 Mainland / Homestead (Linden Owned)131 Linden Homes / Full Region + + - - The current sequence number for packets sent to this - simulator. Must be Interlocked before modifying. Only - useful for applications manipulating sequence numbers + + - - - A thread-safe dictionary containing avatars in a simulator - + + - - - A thread-safe dictionary containing primitives in a simulator - + + - - - Provides access to an internal thread-safe dictionary containing parcel - information found in this simulator - + + - - Used internally to track sim disconnections + + - - Event that is triggered when the simulator successfully - establishes a connection + + - - Whether this sim is currently connected or not. Hooked up - to the property Connected + + - - Coarse locations of avatars in this simulator + + - - AvatarPositions key representing TrackAgent target + + - - Sequence numbers of packets we've received - (for duplicate checking) + + - - Packets we sent out that need ACKs from the simulator + + - - Sequence number for pause/resume + + - - Indicates if UDP connection to the sim is fully established + + - - - Provides access to an internal thread-safe multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. - + + - - The IP address and port of the server + + - - Whether there is a working connection to the simulator or - not + + - - Coarse locations of avatars in this simulator + + - - AvatarPositions key representing TrackAgent target + + - - Indicates if UDP connection to the sim is fully established + + - - - Checks simulator parcel map to make sure it has downloaded all data successfully - - true if map is full (contains no 0's) + + - - - Called when this Simulator object is being destroyed - + + - - - Attempt to connect to this simulator - - Whether to move our agent in to this sim or not - True if the connection succeeded or connection status is - unknown, false if there was a failure + + - - - Initiates connection to the simulator - + + - - - Disconnect from this simulator - + + - - - Instructs the simulator to stop sending update (and possibly other) packets - + + - - - Instructs the simulator to resume sending update packets (unpause) - + + - - - Retrieve the terrain height at a given coordinate - - Sim X coordinate, valid range is from 0 to 255 - Sim Y coordinate, valid range is from 0 to 255 - The terrain height at the given point if the - lookup was successful, otherwise 0.0f - True if the lookup was successful, otherwise false + + - - - Sends a packet - - Packet to be sent + + - - - + + - - - Returns Simulator Name as a String - - - + + - - - - - + + - - - - - - - + + - - - Sends out pending acknowledgements - - Number of ACKs sent + + - - - Resend unacknowledged packets - + + - - - + + - - - Construct a new instance of the SoundManager class, used for playing and receiving - sound assets - - A reference to the current GridClient instance + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - The event subscribers, null of no subscribers + + - - Thread sync lock object + + - - Raised when the simulator sends us data containing - sound + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - Raised when the simulator sends us data containing - ... + + - - Raises the AttachedSound Event - A AttachedSoundEventArgs object containing - the data sent from the simulator + + - - Raises the AttachedSoundGainChange Event - A AttachedSoundGainChangeEventArgs object containing - the data sent from the simulator + + - - Raises the SoundTrigger Event - A SoundTriggerEventArgs object containing - the data sent from the simulator + + - - Raises the PreloadSound Event - A PreloadSoundEventArgs object containing - the data sent from the simulator + + - - - Plays a sound in the current region at full volume from avatar position - - UUID of the sound to be played + + - - - Plays a sound in the current region at full volume - - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. + + - - - Plays a sound in the current region - - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 + + - - - Plays a sound in the specified sim - - UUID of the sound to be played. - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 + + - - - Play a sound asset - - UUID of the sound to be played. - handle id for the sim to be played in. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data + + - - Provides data for the event - The event occurs when the simulator sends - the sound data which emits from an agents attachment - - The following code example shows the process to subscribe to the event - and a stub to handle the data passed from the simulator - - // Subscribe to the AttachedSound event - Client.Sound.AttachedSound += Sound_AttachedSound; - // process the data raised in the event here - private void Sound_AttachedSound(object sender, AttachedSoundEventArgs e) - { - // ... Process AttachedSoundEventArgs here ... - } - + + - - - Construct a new instance of the SoundTriggerEventArgs class - - Simulator where the event originated - The sound asset id - The ID of the owner - The ID of the object - The volume level - The + + - - Simulator where the event originated + + - - Get the sound asset id + + - - Get the ID of the owner + + - - Get the ID of the Object + + - - Get the volume level + + - - Get the + + - - Provides data for the event - The event occurs when an attached sound - changes its volume level + + - - - Construct a new instance of the AttachedSoundGainChangedEventArgs class - - Simulator where the event originated - The ID of the Object - The new volume level + + - - Simulator where the event originated + + - - Get the ID of the Object + + - - Get the volume level + + - - Provides data for the event - - The event occurs when the simulator forwards - a request made by yourself or another agent to play either an asset sound or a built in sound - Requests to play sounds where the is not one of the built-in - will require sending a request to download the sound asset before it can be played - - - The following code example uses the , - and - properties to display some information on a sound request on the window. - - // subscribe to the event - Client.Sound.SoundTrigger += Sound_SoundTrigger; - // play the pre-defined BELL_TING sound - Client.Sound.SendSoundTrigger(Sounds.BELL_TING); - // handle the response data - private void Sound_SoundTrigger(object sender, SoundTriggerEventArgs e) - { - Console.WriteLine("{0} played the sound {1} at volume {2}", - e.OwnerID, e.SoundID, e.Gain); - } - + + - - - Construct a new instance of the SoundTriggerEventArgs class - - Simulator where the event originated - The sound asset id - The ID of the owner - The ID of the object - The ID of the objects parent - The volume level - The regionhandle - The source position + + - - Simulator where the event originated + + - - Get the sound asset id + + - - Get the ID of the owner + + - - Get the ID of the Object + + - - Get the ID of the objects parent + + - - Get the volume level + + - - Get the regionhandle + + - - Get the source position + + - - Provides data for the event - The event occurs when the simulator sends - the appearance data for an avatar - - The following code example uses the and - properties to display the selected shape of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; - // handle the data when the event is raised - void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) - { - Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") - } - + + - - - Construct a new instance of the PreloadSoundEventArgs class - - Simulator where the event originated - The sound asset id - The ID of the owner - The ID of the object + + - - Simulator where the event originated + + - - Get the sound asset id + + - - Get the ID of the owner + + - - Get the ID of the Object + + - - - pre-defined built in sounds - + + + + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - coins + + - - cash register bell + + - - - + + - - - + + - - rubber + + - - plastic + + - - flesh + + - - wood splintering? + + - - glass break + + - - metal clunk + + - - whoosh + + - - shake + + - - - + + - - ding + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - A dictionary containing all pre-defined sounds - - A dictionary containing the pre-defined sounds, - where the key is the sounds ID, and the value is a string - containing a name to identify the purpose of the sound + + - - X position of this patch + + - - Y position of this patch + + - - A 16x16 array of floats holding decompressed layer data + + - - - Creates a LayerData packet for compressed land data given a full - simulator heightmap and an array of indices of patches to compress - - A 256 * 256 array of floating point values - specifying the height at each meter in the simulator - Array of indexes in the 16x16 grid of patches - for this simulator. For example if 1 and 17 are specified, patches - x=1,y=0 and x=1,y=1 are sent - - + + - - - Add a patch of terrain to a BitPacker - - BitPacker to write the patch to - Heightmap of the simulator, must be a 256 * - 256 float array - X offset of the patch to create, valid values are - from 0 to 15 - Y offset of the patch to create, valid values are - from 0 to 15 + + - - - Default constructor - - - + + - - The event subscribers. null if no subcribers + + - - Thread sync lock object + + - - Raised when the simulator responds sends + + - - Raises the LandPatchReceived event - A LandPatchReceivedEventArgs object containing the - data returned from the simulator + + - - Simulator from that sent tha data + + - - Sim coordinate of the patch + + - - Sim coordinate of the patch + + - - Size of tha patch + + - - Heightmap for the patch + + - - - The current status of a texture request as it moves through the pipeline or final result of a texture request. - + + - - The initial state given to a request. Requests in this state - are waiting for an available slot in the pipeline + + - - A request that has been added to the pipeline and the request packet - has been sent to the simulator + + - - A request that has received one or more packets back from the simulator + + - - A request that has received all packets back from the simulator + + - - A request that has taken longer than - to download OR the initial packet containing the packet information was never received + + - - The texture request was aborted by request of the agent + + - - The simulator replied to the request that it was not able to find the requested texture + + - - - Texture request download handler, allows a configurable number of download slots which manage multiple - concurrent texture downloads from the - This class makes full use of the internal - system for full texture downloads. + + - - - Default constructor, Instantiates a new copy of the TexturePipeline class - - Reference to the instantiated object + + - - - A request task containing information and status of a request as it is processed through the + + - - The current which identifies the current status of the request + + - - The Unique Request ID, This is also the Asset ID of the texture being requested + + - - The slot this request is occupying in the threadpoolSlots array + + + + + - - The ImageType of the request. + + - - The callback to fire when the request is complete, will include - the and the - object containing the result data + + - - If true, indicates the callback will be fired whenever new data is returned from the simulator. - This is used to progressively render textures as portions of the texture are received. + + - - An object that maintains the data of an request thats in-process. + + - - A dictionary containing all pending and in-process transfer requests where the Key is both the RequestID - and also the Asset Texture ID, and the value is an object containing the current state of the request and also - the asset data as it is being re-assembled + + - - Holds the reference to the client object + + - - Maximum concurrent texture requests allowed at a time + + - - An array of objects used to manage worker request threads + + - - An array of worker slots which shows the availablity status of the slot + + - - The primary thread which manages the requests. + + - - true if the TexturePipeline is currently running + + - - A synchronization object used by the primary thread + + - - A refresh timer used to increase the priority of stalled requests + + - - Current number of pending and in-process transfers + + - - - Initialize callbacks required for the TexturePipeline to operate - + + - - - Shutdown the TexturePipeline and cleanup any callbacks or transfers - + + - - - Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - A float indicating the requested priority for the transfer. Higher priority values tell the simulator - to prioritize the request before lower valued requests. An image already being transferred using the can have - its priority changed by resending the request with the new priority value - Number of quality layers to discard. - This controls the end marker of the data sent - The packet number to begin the request at. A value of 0 begins the request - from the start of the asset texture - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request + + - - - Sends the actual request packet to the simulator - - The image to download - Type of the image to download, either a baked - avatar texture or a normal texture - Priority level of the download. Default is - 1,013,000.0f - Number of quality layers to discard. - This controls the end marker of the data sent - Packet number to start the download at. - This controls the start marker of the data sent - Sending a priority of 0 and a discardlevel of -1 aborts - download + + - - - Cancel a pending or in process texture request - - The texture assets unique ID + + - - - Master Download Thread, Queues up downloads in the threadpool - + + - - - The worker thread that sends the request and handles timeouts - - A object containing the request details + + - - - Handle responses from the simulator that tell us a texture we have requested is unable to be located - or no longer exists. This will remove the request from the pipeline and free up a slot if one is in use - - The sender - The EventArgs object containing the packet data + + - - - Handles the remaining Image data that did not fit in the initial ImageData packet - - The sender - The EventArgs object containing the packet data + + - - - Handle the initial ImageDataPacket sent from the simulator - - The sender - The EventArgs object containing the packet data + + - - - + + - - - Delegate to wrap another delegate and its arguments - - - - - + + - - - An instance of DelegateWrapper which calls InvokeWrappedDelegate, - which in turn calls the DynamicInvoke method of the wrapped - delegate - + + - - - Callback used to call EndInvoke on the asynchronously - invoked DelegateWrapper - + + - - - Executes the specified delegate with the specified arguments - asynchronously on a thread pool thread - - - - - + + - - - Invokes the wrapped delegate synchronously - - - - - + + - - - Calls EndInvoke on the wrapper and Close on the resulting WaitHandle - to prevent resource leaks - - - + + - - - + + - - - Initialize the UDP packet handler in server mode - - Port to listening for incoming UDP packets on + + - - - Initialize the UDP packet handler in client mode - - Remote UDP server to connect to + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - Thrown when a packet could not be successfully deserialized - + + - - - Default constructor - + + - - - Constructor that takes an additional error message - - An error message to attach to this exception + + - - - The header of a message template packet. Holds packet flags, sequence - number, packet ID, and any ACKs that will be appended at the end of - the packet - + + - - - Convert the AckList to a byte array, used for packet serializing - - Reference to the target byte array - Beginning position to start writing to in the byte - array, will be updated with the ending position of the ACK list + + - - - - - - - - - - - + + - - - - - - - - - + + - - - A block of data in a packet. Packets are composed of one or more blocks, - each block containing one or more fields - + + - - Current length of the data in this packet + + - - - Create a block from a byte array - - Byte array containing the serialized block - Starting position of the block in the byte array. - This will point to the data after the end of the block when the - call returns + + - - - Serialize this block into a byte array - - Byte array to serialize this block into - Starting position in the byte array to serialize to. - This will point to the position directly after the end of the - serialized block when the call returns + + - - A generic value, not an actual packet type + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + Avatar group management + - - + + Key of Group Member - - + + Total land contribution - - + + Online status information - - + + Abilities that the Group Member has - - + + Current group title - - + + Is a group owner - - + + + Role manager for a group + - - + + Key of the group - - + + Key of Role - - + + Name of Role - - + + Group Title associated with Role - - + + Description of Role - - + + Abilities Associated with Role - - + + Returns the role's title + The role's title - - + + + Class to represent Group Title + - - + + Key of the group - - + + ID of the role title belongs to - - + + Group Title - - + + Whether title is Active - - + + Returns group title - - + + + Represents a group on the grid + - - + + Key of Group - - + + Key of Group Insignia - - + + Key of Group Founder - - + + Key of Group Role for Owners - - + + Name of Group - - + + Text of Group Charter - - + + Title of "everyone" role - - + + Is the group open for enrolement to everyone - - + + Will group show up in search - - + + - - + + - - + + - - + + Is the group Mature - - + + Cost of group membership - - + + - - + + - - + + The total number of current members this group has - - + + The number of roles this group has configured - - + + Show this group in agent's profile - - + + Returns the name of the group + A string containing the name of the group - - + + + A group Vote + - - + + Key of Avatar who created Vote - - + + Text of the Vote proposal - - + + Total number of votes - - + + + A group proposal + - - + + The Text of the proposal - - + + The minimum number of members that must vote before proposal passes or failes - - + + The required ration of yes/no votes required for vote to pass + The three options are Simple Majority, 2/3 Majority, and Unanimous + TODO: this should be an enum - - + + The duration in days votes are accepted - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + Struct representing a group notice + - - + + - - + + - - + + - - + + - - + + + + + - - + + + Struct representing a group notice list entry + - - + + Notice ID - - + + Creation timestamp of notice - - + + Agent name who created notice - - + + Notice subject - - + + Is there an attachment? - - + + Attachment Type - - + + + Struct representing a member of a group chat session and their settings + - - + + The of the Avatar - - + + True if user has voice chat enabled - - + + True of Avatar has moderator abilities - - + + True if a moderator has muted this avatars chat - - + + True if a moderator has muted this avatars voice - - + + + Role update flags + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + Can send invitations to groups default role - - + + Can eject members from group - - + + Can toggle 'Open Enrollment' and change 'Signup fee' - - + + Member is visible in the public member list - - + + Can create new roles - - + + Can delete existing roles - - + + Can change Role names, titles and descriptions - - + + Can assign other members to assigners role - - + + Can assign other members to any role - - + + Can remove members from roles - - + + Can assign and remove abilities in roles - - + + Can change group Charter, Insignia, 'Publish on the web' and which + members are publicly visible in group member listings - - + + Can buy land or deed land to group - - + + Can abandon group owned land to Governor Linden on mainland, or Estate owner for + private estates - - + + Can set land for-sale information on group owned parcels - - + + Can subdivide and join parcels - - + + Can join group chat sessions - - + + Can use voice chat in Group Chat sessions - - + + Can moderate group chat sessions - - + + Can toggle "Show in Find Places" and set search category - - + + Can change parcel name, description, and 'Publish on web' settings - - + + Can set the landing point and teleport routing on group land - - + + Can change music and media settings - - + + Can toggle 'Edit Terrain' option in Land settings - - + + Can toggle various About Land > Options settings - - + + Can always terraform land, even if parcel settings have it turned off - - + + Can always fly while over group owned land - - + + Can always rez objects on group owned land - - + + Can always create landmarks for group owned parcels - - + + Can set home location on any group owned parcel - - + + Can modify public access settings for group owned parcels - - + + Can manager parcel ban lists on group owned land - - + + Can manage pass list sales information - - + + Can eject and freeze other avatars on group owned land - - + + Can return objects set to group - - + + Can return non-group owned/set objects - - + + Can return group owned objects - - + + Can landscape using Linden plants - - + + Can deed objects to group - - + + Can move group owned objects - - + + Can set group owned objects for-sale - - + + Pay group liabilities and receive group dividends - - + + Can send group notices - - + + Can receive group notices - - + + Can create group proposals - - + + Can vote on group proposals - - + + + Handles all network traffic related to reading and writing group + information + - - + + The event subscribers. null if no subcribers - - + + Raises the CurrentGroups event + A CurrentGroupsEventArgs object containing the + data sent from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupNamesReply event + A GroupNamesEventArgs object containing the + data response from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupProfile event + An GroupProfileEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupMembers event + A GroupMembersEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupRolesDataReply event + A GroupRolesDataReplyEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupRoleMembersReply event + A GroupRolesRoleMembersReplyEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupTitlesReply event + A GroupTitlesReplyEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupAccountSummary event + A GroupAccountSummaryReplyEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupCreated event + An GroupCreatedEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupJoined event + A GroupOperationEventArgs object containing the + result of the operation returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupLeft event + A GroupOperationEventArgs object containing the + result of the operation returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupDropped event + An GroupDroppedEventArgs object containing the + the group your agent left - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupMemberEjected event + An GroupMemberEjectedEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupNoticesListReply event + An GroupNoticesListReplyEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the GroupInvitation event + An GroupInvitationEventArgs object containing the + data returned from the simulator - - + + Thread sync lock object - - + + A reference to the current instance - - + + Currently-active group members requests - - + + Currently-active group roles requests - - + + Currently-active group role-member requests - - + + Dictionary keeping group members while request is in progress - - + + Dictionary keeping mebmer/role mapping while request is in progress - - + + Dictionary keeping GroupRole information while request is in progress - - + + Caches group name lookups - - + + + Construct a new instance of the GroupManager class + + A reference to the current instance - - + + + Request a current list of groups the avatar is a member of. + + CAPS Event Queue must be running for this to work since the results + come across CAPS. - - + + + Lookup name of group based on groupID + + groupID of group to lookup name for. - - + + + Request lookup of multiple group names + + List of group IDs to request. - - + + Lookup group profile data such as name, enrollment, founder, logo, etc + Subscribe to OnGroupProfile event to receive the results. + group ID (UUID) - - + + Request a list of group members. + Subscribe to OnGroupMembers event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache - - + + Request group roles + Subscribe to OnGroupRoles event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache - - + + Request members (members,role) role mapping for a group. + Subscribe to OnGroupRolesMembers event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache - - + + Request a groups Titles + Subscribe to OnGroupTitles event to receive the results. + group ID (UUID) + UUID of the request, use to index into cache - - + + Begin to get the group account summary + Subscribe to the OnGroupAccountSummary event to receive the results. + group ID (UUID) + How long of an interval + Which interval (0 for current, 1 for last) - - + + Invites a user to a group + The group to invite to + A list of roles to invite a person to + Key of person to invite - - + + Set a group as the current active group + group ID (UUID) - - + + Change the role that determines your active title + Group ID to use + Role ID to change to - - + + Set this avatar's tier contribution + Group ID to change tier in + amount of tier to donate - - + + + Save wheather agent wants to accept group notices and list this group in their profile + + Group + Accept notices from this group + List this group in the profile - - + + Request to join a group + Subscribe to OnGroupJoined event for confirmation. + group ID (UUID) to join. - - + + + Request to create a new group. If the group is successfully + created, L$100 will automatically be deducted + + Subscribe to OnGroupCreated event to receive confirmation. + Group struct containing the new group info - - + + Update a group's profile and other information + Groups ID (UUID) to update. + Group struct to update. - - + + Eject a user from a group + Group ID to eject the user from + Avatar's key to eject - - + + Update role information + Modified role to be updated - - + + Create a new group role + Group ID to update + Role to create - - + + Delete a group role + Group ID to update + Role to delete - - + + Remove an avatar from a role + Group ID to update + Role ID to be removed from + Avatar's Key to remove - - + + Assign an avatar to a role + Group ID to update + Role ID to assign to + Avatar's ID to assign to role - - + + Request the group notices list + Group ID to fetch notices for - - + + Request a group notice by key + ID of group notice - - + + Send out a group notice + Group ID to update + GroupNotice structure containing notice data - - + + Start a group proposal (vote) + The Group ID to send proposal to + GroupProposal structure containing the proposal - - + + Request to leave a group + Subscribe to OnGroupLeft event to receive confirmation + The group to leave - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Raised when the simulator sends us data containing + our current group membership - - + + Raised when the simulator responds to a RequestGroupName + or RequestGroupNames request - - + + Raised when the simulator responds to a request - - + + Raised when the simulator responds to a request - - + + Raised when the simulator responds to a request - - + + Raised when the simulator responds to a request - - + + Raised when the simulator responds to a request - - + + Raised when a response to a RequestGroupAccountSummary is returned + by the simulator - - + + Raised when a request to create a group is successful - - + + Raised when a request to join a group either + fails or succeeds - - + + Raised when a request to leave a group either + fails or succeeds - - + + Raised when A group is removed from the group server - - + + Raised when a request to eject a member from a group either + fails or succeeds - - + + Raised when the simulator sends us group notices + - - + + Raised when another agent invites our avatar to join a group - - + + Contains the current groups your agent is a member of - - + + Construct a new instance of the CurrentGroupsEventArgs class + The current groups your agent is a member of - - + + Get the current groups your agent is a member of - - + + A Dictionary of group names, where the Key is the groups ID and the value is the groups name - - + + Construct a new instance of the GroupNamesEventArgs class + The Group names dictionary - - + + Get the Group Names dictionary - - + + Represents the members of a group - - + + + Construct a new instance of the GroupMembersReplyEventArgs class + + The ID of the request + The ID of the group + The membership list of the group - - + + Get the ID as returned by the request to correlate + this result set and the request - - + + Get the ID of the group - - + + Get the dictionary of members - - + + Represents the roles associated with a group - - + + Construct a new instance of the GroupRolesDataReplyEventArgs class + The ID as returned by the request to correlate + this result set and the request + The ID of the group + The dictionary containing the roles - - + + Get the ID as returned by the request to correlate + this result set and the request - - + + Get the ID of the group - - + + Get the dictionary containing the roles - - + + Represents the Role to Member mappings for a group - - + + Construct a new instance of the GroupRolesMembersReplyEventArgs class + The ID as returned by the request to correlate + this result set and the request + The ID of the group + The member to roles map - - + + Get the ID as returned by the request to correlate + this result set and the request - - + + Get the ID of the group - - + + Get the member to roles map - - + + Represents the titles for a group - - + + Construct a new instance of the GroupTitlesReplyEventArgs class + The ID as returned by the request to correlate + this result set and the request + The ID of the group + The titles - - + + Get the ID as returned by the request to correlate + this result set and the request - - + + Get the ID of the group - - + + Get the titles - - + + Represents the summary data for a group - - + + Construct a new instance of the GroupAccountSummaryReplyEventArgs class + The ID of the group + The summary data - - + + Get the ID of the group - - + + Get the summary data - - + + A response to a group create request - - + + Construct a new instance of the GroupCreatedReplyEventArgs class + The ID of the group + the success or faulure of the request + A string containing additional information - - + + Get the ID of the group - - + + true of the group was created successfully - - + + A string containing the message - - + + Represents a response to a request - - + + Construct a new instance of the GroupOperationEventArgs class + The ID of the group + true of the request was successful - - + + Get the ID of the group - - + + true of the request was successful - - + + Represents your agent leaving a group - - + + Construct a new instance of the GroupDroppedEventArgs class + The ID of the group - - + + Get the ID of the group - - + + Represents a list of active group notices - - + + Construct a new instance of the GroupNoticesListReplyEventArgs class + The ID of the group + The list containing active notices - - + + Get the ID of the group - - + + Get the notices list - - + + Represents the profile of a group - - + + Construct a new instance of the GroupProfileEventArgs class + The group profile - - + + Get the group profile - - + + + Provides notification of a group invitation request sent by another Avatar + + The invitation is raised when another avatar makes an offer for our avatar + to join a group. - - + + The ID of the Avatar sending the group invitation - - + + The name of the Avatar sending the group invitation - - + + A message containing the request information which includes + the name of the group, the groups charter and the fee to join details - - + + The Simulator - - + + Set to true to accept invitation, false to decline - - + + + A Wrapper around openjpeg to encode and decode images to and from byte arrays + - - + + TGA Header size - - + + OpenJPEG is not threadsafe, so this object is used to lock + during calls into unmanaged code - - + + + Encode a object into a byte array + + The object to encode + true to enable lossless conversion, only useful for small images ie: sculptmaps + A byte array containing the encoded Image object - - + + + Encode a object into a byte array + + The object to encode + a byte array of the encoded image - - + + + Decode JPEG2000 data to an and + + + JPEG2000 encoded data + ManagedImage object to decode to + Image object to decode to + True if the decode succeeds, otherwise false - - + + + + + + + - - + + + + + + + + - - + + + Encode a object into a byte array + + The source object to encode + true to enable lossless decoding + A byte array containing the source Bitmap object - - + + + Defines the beginning and ending file positions of a layer in an + LRCP-progression JPEG2000 file + - - + + + This structure is used to marshal both encoded and decoded images. + MUST MATCH THE STRUCT IN dotnet.h! + - - + + + Information about a single packet in a JPEG2000 stream + - - + + Packet start position - - + + Packet header end position - - + + Packet end position - - + + + Represents a Landmark with RegionID and Position vector + - - + + UUID of the Landmark target region - - + + Local position of the target - - + + Construct an Asset of type Landmark - - + + + Construct an Asset object of type Landmark + + A unique specific to this asset + A byte array containing the raw asset data - - + + + Encode the raw contents of a string with the specific Landmark format + - - + + + Decode the raw asset data, populating the RegionID and Position + + true if the AssetData was successfully decoded to a UUID and Vector - - + + Override the base classes AssetType - - + + + Represents an that can be worn on an avatar + such as a Shirt, Pants, etc. + - - + + Initializes a new instance of an AssetScriptBinary object - - + + Initializes a new instance of an AssetScriptBinary object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - + + Override the base classes AssetType - - + + + + - - + + + + - - + + + + - - + + + + - - + + + + + + - - + + + The ObservableDictionary class is used for storing key/value pairs. It has methods for firing + events to subscribers when items are added, removed, or changed. + + Key + Value - - + + + A dictionary of callbacks to fire when specified action occurs + - - + + + Register a callback to be fired when an action occurs + + The action + The callback to fire - - + + + Unregister a callback + + The action + The callback to fire - - + + + + + + - - + + Internal dictionary that this class wraps around. Do not + modify or enumerate the contents of this dictionary without locking - - + + + Initializes a new instance of the Class + with the specified key/value, has the default initial capacity. + + + + // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value. + public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(); + + - - + + + Initializes a new instance of the Class + with the specified key/value, With its initial capacity specified. + + Initial size of dictionary + + + // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value, + // initially allocated room for 10 entries. + public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(10); + + - - + + + Try to get entry from the with specified key + + Key to use for lookup + Value returned + if specified key exists, if not found + + + // find your avatar using the Simulator.ObjectsAvatars ObservableDictionary: + Avatar av; + if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) + Console.WriteLine("Found Avatar {0}", av.Name); + + + - - + + + Finds the specified match. + + The match. + Matched value + + + // use a delegate to find a prim in the ObjectsPrimitives ObservableDictionary + // with the ID 95683496 + uint findID = 95683496; + Primitive findPrim = sim.ObjectsPrimitives.Find( + delegate(Primitive prim) { return prim.ID == findID; }); + + - - + + Find All items in an + return matching items. + a containing found items. + + Find All prims within 20 meters and store them in a List + + int radius = 20; + List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( + delegate(Primitive prim) { + Vector3 pos = prim.Position; + return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); + } + ); + + - - + + Find All items in an + return matching keys. + a containing found keys. + + Find All keys which also exist in another dictionary + + List<UUID> matches = myDict.FindAll( + delegate(UUID id) { + return myOtherDict.ContainsKey(id); + } + ); + + - - + + Check if Key exists in Dictionary + Key to check for + if found, otherwise - - + + Check if Value exists in Dictionary + Value to check for + if found, otherwise - - + + + Adds the specified key to the dictionary, dictionary locking is not performed, + + + The key + The value - - + + + Removes the specified key, dictionary locking is not performed + + The key. + if successful, otherwise - - + + + Clear the contents of the dictionary + - - + + + Enumerator for iterating dictionary entries + + - - + + + Gets the number of Key/Value pairs contained in the + - - + + + Indexer for the dictionary + + The key + The value - - + + Describes tasks returned in LandStatReply - - + + + Estate level administration and utilities + - - + + Textures for each of the four terrain height levels - - + + Upper/lower texture boundaries for each corner of the sim - - + + + Constructor for EstateTools class + + - - + + The event subscribers. null if no subcribers - - + + Raises the TopCollidersReply event + A TopCollidersReplyEventArgs object containing the + data returned from the data server - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the TopScriptsReply event + A TopScriptsReplyEventArgs object containing the + data returned from the data server - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the EstateUsersReply event + A EstateUsersReplyEventArgs object containing the + data returned from the data server - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the EstateGroupsReply event + A EstateGroupsReplyEventArgs object containing the + data returned from the data server - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the EstateManagersReply event + A EstateManagersReplyEventArgs object containing the + data returned from the data server - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the EstateBansReply event + A EstateBansReplyEventArgs object containing the + data returned from the data server - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the EstateCovenantReply event + A EstateCovenantReplyEventArgs object containing the + data returned from the data server - - + + Thread sync lock object - - + + The event subscribers. null if no subcribers - - + + Raises the EstateUpdateInfoReply event + A EstateUpdateInfoReplyEventArgs object containing the + data returned from the data server - - + + Thread sync lock object - - + + + Requests estate information such as top scripts and colliders + + + + + - - + + Requests estate settings, including estate manager and access/ban lists - - + + Requests the "Top Scripts" list for the current region - - + + Requests the "Top Colliders" list for the current region - - + + + Set several estate specific configuration variables + + The Height of the waterlevel over the entire estate. Defaults to 20 + The maximum height change allowed above the baked terrain. Defaults to 4 + The minimum height change allowed below the baked terrain. Defaults to -4 + true to use + if True forces the sun position to the position in SunPosition + The current position of the sun on the estate, or when FixedSun is true the static position + the sun will remain. 6.0 = Sunrise, 30.0 = Sunset - - + + + Request return of objects owned by specified avatar + + The Agents owning the primitives to return + specify the coverage and type of objects to be included in the return + true to perform return on entire estate - - + + + + - - + + + Used for setting and retrieving various estate panel settings + + EstateOwnerMessage Method field + List of parameters to include - - + + + Kick an avatar from an estate + + Key of Agent to remove - - + + + Ban an avatar from an estate + Key of Agent to remove + Ban user from this estate and all others owned by the estate owner - - + + Unban an avatar from an estate + Key of Agent to remove + /// Unban user from this estate and all others owned by the estate owner - - + + + Send a message dialog to everyone in an entire estate + + Message to send all users in the estate - - + + + Send a message dialog to everyone in a simulator + + Message to send all users in the simulator - - + + + Send an avatar back to their home location + + Key of avatar to send home - - + + + Begin the region restart process + - - + + + Cancels a region restart + - - + + Estate panel "Region" tab settings - - + + Estate panel "Debug" tab settings - - + + Used for setting the region's terrain textures for its four height levels + + + + - - + + Used for setting sim terrain texture heights - - + + Requests the estate covenant - - + + + Upload a terrain RAW file + + A byte array containing the encoded terrain data + The name of the file being uploaded + The Id of the transfer request - - + + + Teleports all users home in current Estate + - - + + + Remove estate manager + Key of Agent to Remove + removes manager to this estate and all others owned by the estate owner - - + + + Add estate manager + Key of Agent to Add + Add agent as manager to this estate and all others owned by the estate owner - - + + + Add's an agent to the estate Allowed list + Key of Agent to Add + Add agent as an allowed reisdent to All estates if true - - + + + Removes an agent from the estate Allowed list + Key of Agent to Remove + Removes agent as an allowed reisdent from All estates if true - - + + + + Add's a group to the estate Allowed list + Key of Group to Add + Add Group as an allowed group to All estates if true - - + + + + Removes a group from the estate Allowed list + Key of Group to Remove + Removes Group as an allowed Group from All estates if true - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Raised when the data server responds to a request. - - + + Used in the ReportType field of a LandStatRequest - - + + Used by EstateOwnerMessage packets - - + + Used by EstateOwnerMessage packets - - + + + + - - + + No flags set - - + + Only return targets scripted objects - - + + Only return targets objects if on others land - - + + Returns target's scripted objects and objects on other parcels - - + + Ground texture settings for each corner of the region - - + + Used by GroundTextureHeightSettings - - + + The high and low texture thresholds for each corner of the sim - - + + Raised on LandStatReply when the report type is for "top colliders" - - + + Construct a new instance of the TopCollidersReplyEventArgs class + The number of returned items in LandStatReply + Dictionary of Object UUIDs to tasks returned in LandStatReply - - + + + The number of returned items in LandStatReply + - - + + + A Dictionary of Object UUIDs to tasks returned in LandStatReply + - - + + Raised on LandStatReply when the report type is for "top Scripts" - - + + Construct a new instance of the TopScriptsReplyEventArgs class + The number of returned items in LandStatReply + Dictionary of Object UUIDs to tasks returned in LandStatReply - - + + + The number of scripts returned in LandStatReply + - - + + + A Dictionary of Object UUIDs to tasks returned in LandStatReply + - - + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateBansReplyEventArgs class + The estate's identifier on the grid + The number of returned items in LandStatReply + User UUIDs banned - - + + + The identifier of the estate + - - + + + The number of returned itmes + - - + + + List of UUIDs of Banned Users + - - + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateUsersReplyEventArgs class + The estate's identifier on the grid + The number of users + Allowed users UUIDs - - + + + The identifier of the estate + - - + + + The number of returned items + - - + + + List of UUIDs of Allowed Users + - - + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateGroupsReplyEventArgs class + The estate's identifier on the grid + The number of Groups + Allowed Groups UUIDs - - + + + The identifier of the estate + - - + + + The number of returned items + - - + + + List of UUIDs of Allowed Groups + - - + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateManagersReplyEventArgs class + The estate's identifier on the grid + The number of Managers + Managers UUIDs - - + + + The identifier of the estate + - - + + + The number of returned items + - - + + + List of UUIDs of the Estate's Managers + - - + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateCovenantReplyEventArgs class + The Covenant ID + The timestamp + The estate's name + The Estate Owner's ID (can be a GroupID) - - + + + The Covenant + - - + + + The timestamp + - - + + + The Estate name + - - + + + The Estate Owner's ID (can be a GroupID) + - - + + Returned, along with other info, upon a successful .RequestInfo() - - + + Construct a new instance of the EstateUpdateInfoReplyEventArgs class + The estate's name + The Estate Owners ID (can be a GroupID) + The estate's identifier on the grid + - - + + + The estate's name + - - + + + The Estate Owner's ID (can be a GroupID) + - - + + + The identifier of the estate on the grid + - - + + - - + + + Wrapper around a byte array that allows bit to be packed and unpacked + one at a time or by a variable amount. Useful for very tightly packed + data like LayerData packets + - - + + - - + + + Default constructor, initialize the bit packer / bit unpacker + with a byte array and starting position + + Byte array to pack bits in to or unpack from + Starting position in the byte array - - + + + Pack a floating point value in to the data + + Floating point value to pack - - + + + Pack part or all of an integer in to the data + + Integer containing the data to pack + Number of bits of the integer to pack - - + + + Pack part or all of an unsigned integer in to the data + + Unsigned integer containing the data to pack + Number of bits of the integer to pack - - + + + Pack a single bit in to the data + + Bit to pack - - + + + + + + + + - - + + + + + - - + + + + + - - + + + Unpacking a floating point value from the data + + Unpacked floating point value - - + + + Unpack a variable number of bits from the data in to integer format + + Number of bits to unpack + An integer containing the unpacked bits + This function is only useful up to 32 bits - - + + + Unpack a variable number of bits from the data in to unsigned + integer format + + Number of bits to unpack + An unsigned integer containing the unpacked bits + This function is only useful up to 32 bits - - + + + Unpack a 16-bit signed integer + + 16-bit signed integer - - + + + Unpack a 16-bit unsigned integer + + 16-bit unsigned integer - - + + + Unpack a 32-bit signed integer + + 32-bit signed integer - - + + + Unpack a 32-bit unsigned integer + + 32-bit unsigned integer - - + + - - + + - - + + + Checks the instance back into the object pool + - - + + + Returns an instance of the class that has been checked out of the Object Pool. + - - + + + Creates a new instance of the ObjectPoolBase class. Initialize MUST be called + after using this constructor. + - - + + + Creates a new instance of the ObjectPool Base class. + + The object pool is composed of segments, which + are allocated whenever the size of the pool is exceeded. The number of items + in a segment should be large enough that allocating a new segmeng is a rare + thing. For example, on a server that will have 10k people logged in at once, + the receive buffer object pool should have segment sizes of at least 1000 + byte arrays per segment. + + The minimun number of segments that may exist. + Perform a full GC.Collect whenever a segment is allocated, and then again after allocation to compact the heap. + The frequency which segments are checked to see if they're eligible for cleanup. - - + + + Forces the segment cleanup algorithm to be run. This method is intended + primarly for use from the Unit Test libraries. + - - + + + Responsible for allocate 1 instance of an object that will be stored in a segment. + + An instance of whatever objec the pool is pooling. - - + + + Checks in an instance of T owned by the object pool. This method is only intended to be called + by the WrappedObject class. + + The segment from which the instance is checked out. + The instance of T to check back into the segment. - - + + + Checks an instance of T from the pool. If the pool is not sufficient to + allow the checkout, a new segment is created. + + A WrappedObject around the instance of T. To check + the instance back into the segment, be sureto dispose the WrappedObject + when finished. - - + + + The total number of segments created. Intended to be used by the Unit Tests. + - - + + + The number of items that are in a segment. Items in a segment + are all allocated at the same time, and are hopefully close to + each other in the managed heap. + - - + + + The minimum number of segments. When segments are reclaimed, + this number of segments will always be left alone. These + segments are allocated at startup. + - - + + + The age a segment must be before it's eligible for cleanup. + This is used to prevent thrash, and typical values are in + the 5 minute range. + - - + + + The frequence which the cleanup thread runs. This is typically + expected to be in the 5 minute range. + - - + + = - - + + Number of times we've received an unknown CAPS exception in series. - - + + For exponential backoff on error. - - + + + Represents a texture + - - + + A object containing image data - - + + - - + + - - + + Initializes a new instance of an AssetTexture object - - + + + Initializes a new instance of an AssetTexture object + + A unique specific to this asset + A byte array containing the raw asset data - - + + + Initializes a new instance of an AssetTexture object + + A object containing texture data - - + + + Populates the byte array with a JPEG2000 + encoded image created from the data in + - - + + + Decodes the JPEG2000 data in AssetData to the + object + + True if the decoding was successful, otherwise false - - + + + Decodes the begin and end byte positions for each quality layer in + the image + + - - + + Override the base classes AssetType - - + + + A Name Value pair with additional settings, used in the protocol + primarily to transmit avatar names and active group in object packets + - - + + - - + + - - + + - - + + - - + + - - + + + Constructor that takes all the fields as parameters + + + + + + - - + + + Constructor that takes a single line from a NameValue field + + - - + + Type of the value - - + + Unknown - - + + String value - - + + - - + + - - + + - - + + - - + + Deprecated - - + + String value, but designated as an asset - - + + - - + + + + - - + + - - + + - - + + - - + + - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + + Represents a single Voice Session to the Vivox service. + - - + + + Close this session. + - - + + + Look up an existing Participants in this session + + + - - + + + Represents an Animation + - - + + Default Constructor - - + + + Construct an Asset object of type Animation + + A unique specific to this asset + A byte array containing the raw asset data - - + + Override the base classes AssetType - - + + + Constants for the archiving module + - - + + + The location of the archive control file + - - + + + Path for the assets held in an archive + - - + + + Path for the prims file + - - + + + Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. + - - + + + Path for region settings. + - - + + + The character the separates the uuid from extension information in an archived asset filename + - - + + + Extensions used for asset types in the archive + - - + + + Represents an AssetScriptBinary object containing the + LSO compiled bytecode of an LSL script + - - + + Initializes a new instance of an AssetScriptBinary object - - + + Initializes a new instance of an AssetScriptBinary object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - + + + TODO: Encodes a scripts contents into a LSO Bytecode file + - - + + + TODO: Decode LSO Bytecode into a string + + true - - + + Override the base classes AssetType - - + + + + - - + + No report - - + + Unknown report type - - + + Bug report - - + + Complaint report - - + + Customer service report - - + + + Bitflag field for ObjectUpdateCompressed data blocks, describing + which options are present for each object + - - + + Unknown - - + + Whether the object has a TreeSpecies - - + + Whether the object has floating text ala llSetText - - + + Whether the object has an active particle system - - + + Whether the object has sound attached to it - - + + Whether the object is attached to a root object or not - - + + Whether the object has texture animation settings - - + + Whether the object has an angular velocity - - + + Whether the object has a name value pairs string - - + + Whether the object has a Media URL set - - + + + Specific Flags for MultipleObjectUpdate requests + - - + + None - - + + Change position of prims - - + + Change rotation of prims - - + + Change size of prims - - + + Perform operation on link set - - + + Scale prims uniformly, same as selecing ctrl+shift in the + viewer. Used in conjunction with Scale - - + + + Special values in PayPriceReply. If the price is not one of these + literal value of the price should be use + - - + + + Indicates that this pay option should be hidden + - - + + + Indicates that this pay option should have the default value + - - + + + Contains the variables sent in an object update packet for objects. + Used to track position and movement of prims and avatars + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + Handles all network traffic related to prims and avatar positions and + movement. + - - + + The event subscribers, null of no subscribers - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Raises the ObjectProperties Event + A ObjectPropertiesEventArgs object containing + the data sent from the simulator - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Raises the ObjectPropertiesUpdated Event + A ObjectPropertiesUpdatedEventArgs object containing + the data sent from the simulator - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Raises the ObjectPropertiesFamily Event + A ObjectPropertiesFamilyEventArgs object containing + the data sent from the simulator - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Raises the AvatarUpdate Event + A AvatarUpdateEventArgs object containing + the data sent from the simulator - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Raises the ObjectDataBlockUpdate Event + A ObjectDataBlockUpdateEventArgs object containing + the data sent from the simulator - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Raises the KillObject Event + A KillObjectEventArgs object containing + the data sent from the simulator - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Raises the AvatarSitChanged Event + A AvatarSitChangedEventArgs object containing + the data sent from the simulator - - + + Thread sync lock object - - + + The event subscribers, null of no subscribers - - + + Raises the PayPriceReply Event + A PayPriceReplyEventArgs object containing + the data sent from the simulator - - + + Thread sync lock object - - + + Reference to the GridClient object - - + + Does periodic dead reckoning calculation to convert + velocity and acceleration to new positions for objects - - + + + Construct a new instance of the ObjectManager class + + A reference to the instance - - + + + Request information for a single object from a + you are currently connected to + + The the object is located + The Local ID of the object - - + + + Request information for multiple objects contained in + the same simulator + + The the objects are located + An array containing the Local IDs of the objects - - + + + Attempt to purchase an original object, a copy, or the contents of + an object + + The the object is located + The Local ID of the object + Whether the original, a copy, or the object + contents are on sale. This is used for verification, if the this + sale type is not valid for the object the purchase will fail + Price of the object. This is used for + verification, if it does not match the actual price the purchase + will fail + Group ID that will be associated with the new + purchase + Inventory folder UUID where the object or objects + purchased should be placed + + + BuyObject(Client.Network.CurrentSim, 500, SaleType.Copy, + 100, UUID.Zero, Client.Self.InventoryRootFolderUUID); + + - - + + + Request prices that should be displayed in pay dialog. This will triggger the simulator + to send us back a PayPriceReply which can be handled by OnPayPriceReply event + + The the object is located + The ID of the object + The result is raised in the event - - + + + Select a single object. This will cause the to send us + an which will raise the event + + The the object is located + The Local ID of the object + - - + + + Select a single object. This will cause the to send us + an which will raise the event + + The the object is located + The Local ID of the object + if true, a call to is + made immediately following the request + - - + + + Select multiple objects. This will cause the to send us + an which will raise the event + + The the objects are located + An array containing the Local IDs of the objects + Should objects be deselected immediately after selection + - - + + + Select multiple objects. This will cause the to send us + an which will raise the event + + The the objects are located + An array containing the Local IDs of the objects + - - + + + Update the properties of an object + + The the object is located + The Local ID of the object + true to turn the objects physical property on + true to turn the objects temporary property on + true to turn the objects phantom property on + true to turn the objects cast shadows property on - - + + + Sets the sale properties of a single object + + The the object is located + The Local ID of the object + One of the options from the enum + The price of the object - - + + + Sets the sale properties of multiple objects + + The the objects are located + An array containing the Local IDs of the objects + One of the options from the enum + The price of the object - - + + + Deselect a single object + + The the object is located + The Local ID of the object - - + + + Deselect multiple objects. + + The the objects are located + An array containing the Local IDs of the objects - - + + + Perform a click action on an object + + The the object is located + The Local ID of the object - - + + + Perform a click action (Grab) on a single object + + The the object is located + The Local ID of the object + The texture coordinates to touch + The surface coordinates to touch + The face of the position to touch + The region coordinates of the position to touch + The surface normal of the position to touch (A normal is a vector perpindicular to the surface) + The surface binormal of the position to touch (A binormal is a vector tangen to the surface + pointing along the U direction of the tangent space - - + + + Create (rez) a new prim object in a simulator + + A reference to the object to place the object in + Data describing the prim object to rez + Group ID that this prim will be set to, or UUID.Zero if you + do not want the object to be associated with a specific group + An approximation of the position at which to rez the prim + Scale vector to size this prim + Rotation quaternion to rotate this prim + Due to the way client prim rezzing is done on the server, + the requested position for an object is only close to where the prim + actually ends up. If you desire exact placement you'll need to + follow up by moving the object after it has been created. This + function will not set textures, light and flexible data, or other + extended primitive properties - - + + + Create (rez) a new prim object in a simulator + + A reference to the object to place the object in + Data describing the prim object to rez + Group ID that this prim will be set to, or UUID.Zero if you + do not want the object to be associated with a specific group + An approximation of the position at which to rez the prim + Scale vector to size this prim + Rotation quaternion to rotate this prim + Specify the + Due to the way client prim rezzing is done on the server, + the requested position for an object is only close to where the prim + actually ends up. If you desire exact placement you'll need to + follow up by moving the object after it has been created. This + function will not set textures, light and flexible data, or other + extended primitive properties - - + + + Rez a Linden tree + + A reference to the object where the object resides + The size of the tree + The rotation of the tree + The position of the tree + The Type of tree + The of the group to set the tree to, + or UUID.Zero if no group is to be set + true to use the "new" Linden trees, false to use the old - - + + + Rez grass and ground cover + + A reference to the object where the object resides + The size of the grass + The rotation of the grass + The position of the grass + The type of grass from the enum + The of the group to set the tree to, + or UUID.Zero if no group is to be set - - + + + Set the textures to apply to the faces of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The texture data to apply - - + + + Set the textures to apply to the faces of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The texture data to apply + A media URL (not used) - - + + + Set the Light data on an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A object containing the data to set - - + + + Set the flexible data on an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A object containing the data to set - - + + + Set the sculptie texture and data on an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A object containing the data to set - - + + + Unset additional primitive parameters on an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The extra parameters to set - - + + + Link multiple prims into a linkset + + A reference to the object where the objects reside + An array which contains the IDs of the objects to link + The last object in the array will be the root object of the linkset TODO: Is this true? - - + + + Delink/Unlink multiple prims from a linkset + + A reference to the object where the objects reside + An array which contains the IDs of the objects to delink - - + + + Change the rotation of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new rotation of the object - - + + + Set the name of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A string containing the new name of the object - - + + + Set the name of multiple objects + + A reference to the object where the objects reside + An array which contains the IDs of the objects to change the name of + An array which contains the new names of the objects - - + + + Set the description of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + A string containing the new description of the object - - + + + Set the descriptions of multiple objects + + A reference to the object where the objects reside + An array which contains the IDs of the objects to change the description of + An array which contains the new descriptions of the objects - - + + + Attach an object to this avatar + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The point on the avatar the object will be attached + The rotation of the attached object - - + + + Drop an attached object from this avatar + + A reference to the + object where the objects reside. This will always be the simulator the avatar is currently in + + The object's ID which is local to the simulator the object is in - - + + + Detach an object from yourself + + A reference to the + object where the objects reside + + This will always be the simulator the avatar is currently in + + An array which contains the IDs of the objects to detach - - + + + Change the position of an object, Will change position of entire linkset + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new position of the object - - + + + Change the position of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new position of the object + if true, will change position of (this) child prim only, not entire linkset - - + + + Change the Scale (size) of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new scale of the object + If true, will change scale of this prim only, not entire linkset + True to resize prims uniformly - - + + + Change the Rotation of an object that is either a child or a whole linkset + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new scale of the object + If true, will change rotation of this prim only, not entire linkset - - + + + Send a Multiple Object Update packet to change the size, scale or rotation of a primitive + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new rotation, size, or position of the target object + The flags from the Enum - - + + + Deed an object (prim) to a group, Object must be shared with group which + can be accomplished with SetPermissions() + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The of the group to deed the object to - - + + + Deed multiple objects (prims) to a group, Objects must be shared with group which + can be accomplished with SetPermissions() + + A reference to the object where the object resides + An array which contains the IDs of the objects to deed + The of the group to deed the object to - - + + + Set the permissions on multiple objects + + A reference to the object where the objects reside + An array which contains the IDs of the objects to set the permissions on + The new Who mask to set + The new Permissions mark to set + TODO: What does this do? - - + + + Request additional properties for an object + + A reference to the object where the object resides + - - + + + Request additional properties for an object + + A reference to the object where the object resides + Absolute UUID of the object + Whether to require server acknowledgement of this request - - + + + Set the ownership of a list of objects to the specified group + + A reference to the object where the objects reside + An array which contains the IDs of the objects to set the group id on + The Groups ID - - + + + Update current URL of the previously set prim media + + UUID of the prim + Set current URL to this + Prim face number + Simulator in which prim is located - - + + + Set object media + + UUID of the prim + Array the length of prims number of faces. Null on face indexes where there is + no media, on faces which contain the media + Simulatior in which prim is located - - + + + Retrieve information about object media + + UUID of the primitive + Simulator where prim is located + Call this callback when done - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + + A terse object update, used when a transformation matrix or + velocity/acceleration for an object changes but nothing else + (scale/position/rotation/acceleration/velocity) + + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + + Setup construction data for a basic primitive shape + + Primitive shape to construct + Construction data that can be plugged into a - - + + + + + + + + - - + + + + + + - - + + + Set the Shape data of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + Data describing the prim shape - - + + + Set the Material data of an object + + A reference to the object where the object resides + The objects ID which is local to the simulator the object is in + The new material of the object - - + + + + + + + + - - + + + + + + + + - - + + Raised when the simulator sends us data containing + A , Foliage or Attachment + + - - + + Raised when the simulator sends us data containing + additional information + + - - + + Raised when the simulator sends us data containing + Primitive.ObjectProperties for an object we are currently tracking - - + + Raised when the simulator sends us data containing + additional and details + - - + + Raised when the simulator sends us data containing + updated information for an - - + + Raised when the simulator sends us data containing + and movement changes - - + + Raised when the simulator sends us data containing + updates to an Objects DataBlock - - + + Raised when the simulator informs us an + or is no longer within view - - + + Raised when the simulator sends us data containing + updated sit information for our - - + + Raised when the simulator sends us data containing + purchase price information for a - - + + + Callback for getting object media data via CAP + + Indicates if the operation was succesfull + Object media version string + Array indexed on prim face of media entry data - - + + Provides data for the event + The event occurs when the simulator sends + an containing a Primitive, Foliage or Attachment data + Note 1: The event will not be raised when the object is an Avatar + Note 2: It is possible for the to be + raised twice for the same object if for example the primitive moved to a new simulator, then returned to the current simulator or + if an Avatar crosses the border into a new simulator and returns to the current simulator + + + The following code example uses the , , and + properties to display new Primitives and Attachments on the window. + + // Subscribe to the event that gives us prim and foliage information + Client.Objects.ObjectUpdate += Objects_ObjectUpdate; + + + private void Objects_ObjectUpdate(object sender, PrimEventArgs e) + { + Console.WriteLine("Primitive {0} {1} in {2} is an attachment {3}", e.Prim.ID, e.Prim.LocalID, e.Simulator.Name, e.IsAttachment); + } + + + + + - - + + + Construct a new instance of the PrimEventArgs class + + The simulator the object originated from + The Primitive + The simulator time dilation + The prim was not in the dictionary before this update + true if the primitive represents an attachment to an agent - - + + Get the simulator the originated from - - + + Get the details - - + + true if the did not exist in the dictionary before this update (always true if object tracking has been disabled) - - + + true if the is attached to an - - + + Get the simulator Time Dilation - - + + Provides data for the event + The event occurs when the simulator sends + an containing Avatar data + Note 1: The event will not be raised when the object is an Avatar + Note 2: It is possible for the to be + raised twice for the same avatar if for example the avatar moved to a new simulator, then returned to the current simulator + + + The following code example uses the property to make a request for the top picks + using the method in the class to display the names + of our own agents picks listings on the window. + + // subscribe to the AvatarUpdate event to get our information + Client.Objects.AvatarUpdate += Objects_AvatarUpdate; + Client.Avatars.AvatarPicksReply += Avatars_AvatarPicksReply; + + private void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e) + { + // we only want our own data + if (e.Avatar.LocalID == Client.Self.LocalID) + { + // Unsubscribe from the avatar update event to prevent a loop + // where we continually request the picks every time we get an update for ourselves + Client.Objects.AvatarUpdate -= Objects_AvatarUpdate; + // make the top picks request through AvatarManager + Client.Avatars.RequestAvatarPicks(e.Avatar.ID); + } + } + + private void Avatars_AvatarPicksReply(object sender, AvatarPicksReplyEventArgs e) + { + // we'll unsubscribe from the AvatarPicksReply event since we now have the data + // we were looking for + Client.Avatars.AvatarPicksReply -= Avatars_AvatarPicksReply; + // loop through the dictionary and extract the names of the top picks from our profile + foreach (var pickName in e.Picks.Values) + { + Console.WriteLine(pickName); + } + } + + + + - - + + + Construct a new instance of the AvatarUpdateEventArgs class + + The simulator the packet originated from + The data + The simulator time dilation + The avatar was not in the dictionary before this update - - + + Get the simulator the object originated from - - + + Get the data - - + + Get the simulator time dilation - - + + true if the did not exist in the dictionary before this update (always true if avatar tracking has been disabled) - - + + Provides additional primitive data for the event + The event occurs when the simulator sends + an containing additional details for a Primitive, Foliage data or Attachment data + The event is also raised when a request is + made. + + + The following code example uses the , and + + properties to display new attachments and send a request for additional properties containing the name of the + attachment then display it on the window. + + // Subscribe to the event that provides additional primitive details + Client.Objects.ObjectProperties += Objects_ObjectProperties; + + // handle the properties data that arrives + private void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e) + { + Console.WriteLine("Primitive Properties: {0} Name is {1}", e.Properties.ObjectID, e.Properties.Name); + } + + - - + + + Construct a new instance of the ObjectPropertiesEventArgs class + + The simulator the object is located + The primitive Properties - - + + Get the simulator the object is located - - + + Get the primitive properties - - + + Provides additional primitive data for the event + The event occurs when the simulator sends + an containing additional details for a Primitive or Foliage data that is currently + being tracked in the dictionary + The event is also raised when a request is + made and is enabled + - - + + + Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class + + The simulator the object is located + The Primitive + The primitive Properties - - + + Get the simulator the object is located - - + + Get the primitive details - - + + Get the primitive properties - - + + Provides additional primitive data, permissions and sale info for the event + The event occurs when the simulator sends + an containing additional details for a Primitive, Foliage data or Attachment. This includes + Permissions, Sale info, and other basic details on an object + The event is also raised when a request is + made, the viewer equivalent is hovering the mouse cursor over an object + - - + + Get the simulator the object is located - - + + - - + + - - + + Provides primitive data containing updated location, velocity, rotation, textures for the event + The event occurs when the simulator sends updated location, velocity, rotation, etc + - - + + Get the simulator the object is located - - + + Get the primitive details - - + + - - + + - - + + + + - - + + Get the simulator the object is located - - + + Get the primitive details - - + + - - + + - - + + - - + + - - + + Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the + event - - + + Get the simulator the object is located - - + + The LocalID of the object - - + + + Provides updates sit position data + - - + + Get the simulator the object is located - - + + - - + + - - + + - - + + + + - - + + Get the simulator the object is located - - + + - - + + - - + + - - + + + Indicates if the operation was successful + - - + + + Media version string + - - + + + Array of media entries indexed by face number + - - + + + + - - + + + + + - - + + + De-serialization constructor for the InventoryNode Class + - - + + + Serialization handler for the InventoryNode Class + - - + + + De-serialization handler for the InventoryNode Class + - - + + + + + - - + + - - + + - - + + - - + + - - + + + For inventory folder nodes specifies weather the folder needs to be + refreshed from the server + - - + + + Main class to expose grid functionality to clients. All of the + classes needed for sending and receiving data are accessible through + this class. + + + + // Example minimum code required to instantiate class and + // connect to a simulator. + using System; + using System.Collections.Generic; + using System.Text; + using OpenMetaverse; + + namespace FirstBot + { + class Bot + { + public static GridClient Client; + static void Main(string[] args) + { + Client = new GridClient(); // instantiates the GridClient class + // to the global Client object + // Login to Simulator + Client.Network.Login("FirstName", "LastName", "Password", "FirstBot", "1.0"); + // Wait for a Keypress + Console.ReadLine(); + // Logout of simulator + Client.Network.Logout(); + } + } + } + + - - + + Networking subsystem - - + + Settings class including constant values and changeable + parameters for everything - - + + Parcel (subdivided simulator lots) subsystem - - + + Our own avatars subsystem - - + + Other avatars subsystem - - + + Estate subsystem - - + + Friends list subsystem - - + + Grid (aka simulator group) subsystem - - + + Object subsystem - - + + Group subsystem - - + + Asset subsystem - - + + Appearance subsystem - - + + Inventory subsystem - - + + Directory searches including classifieds, people, land + sales, etc - - + + Handles land, wind, and cloud heightmaps - - + + Handles sound-related networking - - + + Throttling total bandwidth usage, or allocating bandwidth + for specific data stream types - - + + + Default constructor + - - + + + Return the full name of this instance + + Client avatars full name - - + + + Class that handles the local asset cache + - - + + + Default constructor + + A reference to the GridClient object - - + + + Disposes cleanup timer + - - + + + Only create timer when needed + - - + + + Return bytes read from the local asset cache, null if it does not exist + + UUID of the asset we want to get + Raw bytes of the asset, or null on failure - - + + + Returns ImageDownload object of the + image from the local image cache, null if it does not exist + + UUID of the image we want to get + ImageDownload object containing the image, or null on failure - - + + + Constructs a file name of the cached asset + + UUID of the asset + String with the file name of the cahced asset - - + + + Saves an asset to the local cache + + UUID of the asset + Raw bytes the asset consists of + Weather the operation was successfull - - + + + Get the file name of the asset stored with gived UUID + + UUID of the asset + Null if we don't have that UUID cached on disk, file name if found in the cache folder - - + + + Checks if the asset exists in the local cache + + UUID of the asset + True is the asset is stored in the cache, otherwise false - - + + + Wipes out entire cache + - - + + + Brings cache size to the 90% of the max size + - - + + + Asynchronously brings cache size to the 90% of the max size + - - + + + Adds up file sizes passes in a FileInfo array + - - + + + Checks whether caching is enabled + - - + + + Periodically prune the cache + - - + + + Nicely formats file sizes + + Byte size we want to output + String with humanly readable file size - - + + + Allows setting weather to periodicale prune the cache if it grows too big + Default is enabled, when caching is enabled + - - + + + How long (in ms) between cache checks (default is 5 min.) + - - + + + Helper class for sorting files by their last accessed time + - - + + + Permissions for control of object media + - - + + + Style of cotrols that shold be displayed to the user + - - + + + Class representing media data for a single face + - - + + Is display of the alternative image enabled - - + + Should media auto loop - - + + Shoule media be auto played - - + + Auto scale media to prim face - - + + Should viewer automatically zoom in on the face when clicked - - + + Should viewer interpret first click as interaction with the media + or when false should the first click be treated as zoom in commadn - - + + Style of controls viewer should display when + viewer media on this face - - + + Starting URL for the media - - + + Currently navigated URL - - + + Media height in pixes - - + + Media width in pixels - - + + Who can controls the media - - + + Who can interact with the media - - + + Is URL whitelist enabled - - + + Array of URLs that are whitelisted - - + + + Serialize to OSD + + OSDMap with the serialized data - - + + + Deserialize from OSD data + + Serialized OSD data + Deserialized object - - + + + Class for controlling various system settings. + + Some values are readonly because they affect things that + happen when the GridClient object is initialized, so changing them at + runtime won't do any good. Non-readonly values may affect things that + happen at login or dynamically - - + + Main grid login server - - + + Beta grid login server - - + + + InventoryManager requests inventory information on login, + GridClient initializes an Inventory store for main inventory. + - - + + + InventoryManager requests library information on login, + GridClient initializes an Inventory store for the library. + - - + + Number of milliseconds between sending pings to each sim - - + + Number of milliseconds between sending camera updates - - + + Number of milliseconds between updating the current + positions of moving, non-accelerating and non-colliding objects - - + + Millisecond interval between ticks, where all ACKs are + sent out and the age of unACKed packets is checked - - + + The initial size of the packet inbox, where packets are + stored before processing - - + + Maximum size of packet that we want to send over the wire - - + + The maximum value of a packet sequence number before it + rolls over back to one - - + + The maximum size of the sequence number archive, used to + check for resent and/or duplicate packets - - + + The relative directory where external resources are kept - - + + Login server to connect to - - + + IP Address the client will bind to - - + + Use XML-RPC Login or LLSD Login, default is XML-RPC Login - - + + Number of milliseconds before an asset transfer will time + out - - + + Number of milliseconds before a teleport attempt will time + out - - + + Number of milliseconds before NetworkManager.Logout() will + time out - - + + Number of milliseconds before a CAPS call will time out + Setting this too low will cause web requests time out and + possibly retry repeatedly - - + + Number of milliseconds for xml-rpc to timeout - - + + Milliseconds before a packet is assumed lost and resent - - + + Milliseconds without receiving a packet before the + connection to a simulator is assumed lost - - + + Milliseconds to wait for a simulator info request through + the grid interface - - + + Maximum number of queued ACKs to be sent before SendAcks() + is forced - - + + Network stats queue length (seconds) - - + + Enable/disable storing terrain heightmaps in the + TerrainManager - - + + Enable/disable sending periodic camera updates - - + + Enable/disable automatically setting agent appearance at + login and after sim crossing - - + + Enable/disable automatically setting the bandwidth throttle + after connecting to each simulator + The default throttle uses the equivalent of the maximum + bandwidth setting in the official client. If you do not set a + throttle your connection will by default be throttled well below + the minimum values and you may experience connection problems - - + + Enable/disable the sending of pings to monitor lag and + packet loss - - + + Should we connect to multiple sims? This will allow + viewing in to neighboring simulators and sim crossings + (Experimental) - - + + If true, all object update packets will be decoded in to + native objects. If false, only updates for our own agent will be + decoded. Registering an event handler will force objects for that + type to always be decoded. If this is disabled the object tracking + will have missing or partial prim and avatar information - - + + If true, when a cached object check is received from the + server the full object info will automatically be requested - - + + Whether to establish connections to HTTP capabilities + servers for simulators - - + + Whether to decode sim stats - - + + The capabilities servers are currently designed to + periodically return a 502 error which signals for the client to + re-establish a connection. Set this to true to log those 502 errors - - + + If true, any reference received for a folder or item + the library is not aware of will automatically be fetched - - + + If true, and SEND_AGENT_UPDATES is true, + AgentUpdate packets will continuously be sent out to give the bot + smoother movement and autopiloting - - + + If true, currently visible avatars will be stored + in dictionaries inside Simulator.ObjectAvatars. + If false, a new Avatar or Primitive object will be created + each time an object update packet is received - - + + If true, currently visible avatars will be stored + in dictionaries inside Simulator.ObjectPrimitives. + If false, a new Avatar or Primitive object will be created + each time an object update packet is received - - + + If true, position and velocity will periodically be + interpolated (extrapolated, technically) for objects and + avatars that are being tracked by the library. This is + necessary to increase the accuracy of speed and position + estimates for simulated objects - - + + + If true, utilization statistics will be tracked. There is a minor penalty + in CPU time for enabling this option. + - - + + If true, parcel details will be stored in the + Simulator.Parcels dictionary as they are received - - + + + If true, an incoming parcel properties reply will automatically send + a request for the parcel access list + - - + + + if true, an incoming parcel properties reply will automatically send + a request for the traffic count. + - - + + + If true, images, and other assets downloaded from the server + will be cached in a local directory + - - + + Path to store cached texture data - - + + Maximum size cached files are allowed to take on disk (bytes) - - + + Default color used for viewer particle effects - - + + Maximum number of times to resend a failed packet - - + + Throttle outgoing packet rate - - + + UUID of a texture used by some viewers to indentify type of client used - - + + + Download textures using GetTexture capability when available + - - + + The maximum number of concurrent texture downloads allowed + Increasing this number will not necessarily increase texture retrieval times due to + simulator throttles - - + + + The Refresh timer inteval is used to set the delay between checks for stalled texture downloads + + This is a static variable which applies to all instances - - + + + Textures taking longer than this value will be flagged as timed out and removed from the pipeline + - - + + + Get or set the minimum log level to output to the console by default + + If the library is not compiled with DEBUG defined and this level is set to DEBUG + You will get no output on the console. This behavior can be overriden by creating + a logger configuration file for log4net + - - + + Attach avatar names to log messages - - + + Log packet retransmission info - - + + Constructor + Reference to a GridClient object - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - + + Cost of uploading an asset + Read-only since this value is dynamically fetched at login - - + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + + Login Request Parameters + - - + + The URL of the Login Server - - + + The number of milliseconds to wait before a login is considered + failed due to timeout - - + + The request method + login_to_simulator is currently the only supported method - - + + The Agents First name - - + + The Agents Last name - - + + A md5 hashed password + plaintext password will be automatically hashed - - + + The agents starting location once logged in + Either "last", "home", or a string encoded URI + containing the simulator name and x/y/z coordinates e.g: uri:hooper&128&152&17 - - + + A string containing the client software channel information + Second Life Release - - + + The client software version information + The official viewer uses: Second Life Release n.n.n.n + where n is replaced with the current version of the viewer - - + + A string containing the platform information the agent is running on - - + + A string hash of the network cards Mac Address - - + + Unknown or deprecated - - + + A string hash of the first disk drives ID used to identify this clients uniqueness - - + + A string containing the viewers Software, this is not directly sent to the login server but + instead is used to generate the Version string - - + + A string representing the software creator. This is not directly sent to the login server but + is used by the library to generate the Version information - - + + If true, this agent agrees to the Terms of Service of the grid its connecting to - - + + Unknown - - + + An array of string sent to the login server to enable various options - - + + A randomly generated ID to distinguish between login attempts. This value is only used + internally in the library and is never sent over the wire - - + + + Default constuctor, initializes sane default values + - - + + + Instantiates new LoginParams object and fills in the values + + Instance of GridClient to read settings from + Login first name + Login last name + Password + Login channnel (application name) + Client version, should be application name + version number - - + + + Instantiates new LoginParams object and fills in the values + + Instance of GridClient to read settings from + Login first name + Login last name + Password + Login channnel (application name) + Client version, should be application name + version number + URI of the login server - - + + + The decoded data returned from the login server after a successful login + - - + + true, false, indeterminate - - + + Login message of the day - - + + M or PG, also agent_region_access and agent_access_max - - + + + Parse LLSD Login Reply Data + + An + contaning the login response data + XML-RPC logins do not require this as XML-RPC.NET + automatically populates the struct properly using attributes - - + + + Reads in a byte array of an Animation Asset created by the SecondLife(tm) client. + - - + + + Rotation Keyframe count (used internally) + - - + + + Position Keyframe count (used internally) + - - + + + Animation Priority + - - + + + The animation length in seconds. + - - + + + Expression set in the client. Null if [None] is selected + - - + + + The time in seconds to start the animation + - - + + + The time in seconds to end the animation + - - + + + Loop the animation + - - + + + Meta data. Ease in Seconds. + - - + + + Meta data. Ease out seconds. + - - + + + Meta Data for the Hand Pose + - - + + + Number of joints defined in the animation + - - + + + Contains an array of joints + - - + + + Searialize an animation asset into it's joints/keyframes/meta data + + - - + + + Variable length strings seem to be null terminated in the animation asset.. but.. + use with caution, home grown. + advances the index. + + The animation asset byte array + The offset to start reading + a string - - + + + Read in a Joint from an animation asset byte array + Variable length Joint fields, yay! + Advances the index + + animation asset byte array + Byte Offset of the start of the joint + The Joint data serialized into the binBVHJoint structure - - + + + Read Keyframes of a certain type + advance i + + Animation Byte array + Offset in the Byte Array. Will be advanced + Number of Keyframes + Scaling Min to pass to the Uint16ToFloat method + Scaling Max to pass to the Uint16ToFloat method + - - + + + A Joint and it's associated meta data and keyframes + - - + + + Name of the Joint. Matches the avatar_skeleton.xml in client distros + - - + + + Joint Animation Override? Was the same as the Priority in testing.. + - - + + + Array of Rotation Keyframes in order from earliest to latest + - - + + + Array of Position Keyframes in order from earliest to latest + This seems to only be for the Pelvis? + - - + + + A Joint Keyframe. This is either a position or a rotation. + - - + + + Either a Vector3 position or a Vector3 Euler rotation + - - + + + Poses set in the animation metadata for the hands. + - - + + + Avatar profile flags + - - + + + Represents an avatar (other than your own) + - - + + Groups that this avatar is a member of - - + + Positive and negative ratings - - + + Avatar properties including about text, profile URL, image IDs and + publishing settings - - + + Avatar interests including spoken languages, skills, and "want to" + choices - - + + Movement control flags for avatars. Typically not set or used by + clients. To move your avatar, use Client.Self.Movement instead - - + + + Contains the visual parameters describing the deformation of the avatar + - - + + + Default constructor + - - + + First name - - + + Last name - - + + Full name - - + + Active group - - + + + Positive and negative ratings + - - + + Positive ratings for Behavior - - + + Negative ratings for Behavior - - + + Positive ratings for Appearance - - + + Negative ratings for Appearance - - + + Positive ratings for Building - - + + Negative ratings for Building - - + + Positive ratings given by this avatar - - + + Negative ratings given by this avatar - - + + + Avatar properties including about text, profile URL, image IDs and + publishing settings + - - + + First Life about text - - + + First Life image ID - - + + - - + + - - + + - - + + - - + + Profile image ID - - + + Flags of the profile - - + + Web URL for this profile - - + + Should this profile be published on the web - - + + Avatar Online Status - - - Operation to apply when applying color to texture - + + Is this a mature profile - - - Information needed to translate visual param value to RGBA color - + + - - - Construct VisualColorParam - - Operation to apply when applying color to texture - Colors + + - + - Represents alpha blending and bump infor for a visual parameter - such as sleive length + Avatar interests including spoken languages, skills, and "want to" + choices - - - Create new alhpa information for a visual param - - Stregth of the alpha to apply - File containing the alpha channel - Skip blending if parameter value is 0 - Use miltiply insted of alpha blending + + Languages profile field - - Stregth of the alpha to apply + + - - File containing the alpha channel + + - - Skip blending if parameter value is 0 + + - - Use miltiply insted of alpha blending + + - + - A single visual characteristic of an avatar mesh, such as eyebrow height + Extract the avatar UUID encoded in a SIP URI + + - + - Set all the values through the constructor + The type of bump-mapping applied to a face - Index of this visual param - Internal name - - - - - Displayable label of this characteristic - Displayable label for the minimum value of this characteristic - Displayable label for the maximum value of this characteristic - Default value - Minimum value - Maximum value - Is this param used for creation of bump layer? - Array of param IDs that are drivers for this parameter - Alpha blending/bump info - Color information - - Index of this visual param + + - - Internal name + + - - Group ID this parameter belongs to + + - - Name of the wearable this parameter belongs to + + - - Displayable label of this characteristic + + - - Displayable label for the minimum value of this characteristic + + - - Displayable label for the maximum value of this characteristic + + - - Default value + + - - Minimum value + + - - Maximum value + + - - Is this param used for creation of bump layer? + + - - Alpha blending/bump info + + - - Color information + + - - Array of param IDs that are drivers for this parameter + + - - - Holds the Params array of all the avatar appearance parameters - + + - - - Base class for all Asset types - + + - - - Construct a new Asset object - + + - + + + + - Construct a new Asset object + The level of shininess applied to a face - A unique specific to this asset - A byte array containing the raw asset data - - A byte array containing the raw asset data - - - True if the asset it only stored on the server temporarily + + - - A unique ID + + - - The assets unique ID + + - - - The "type" of asset, Notecard, Animation, etc - + + - + - Regenerates the AssetData byte array from the properties - of the derived class. + The texture mapping style used for a face - - - Decodes the AssetData, placing it in appropriate properties of the derived - class. - - True if the asset decoding succeeded, otherwise false + + - - - Constants for the archiving module - + + - - - The location of the archive control file - + + - - - Path for the assets held in an archive - + + - + - Path for the prims file + Flags in the TextureEntry block that describe which properties are + set - - - Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. - + + - - - Path for region settings. - + + - - - The character the separates the uuid from extension information in an archived asset filename - + + - - - Extensions used for asset types in the archive - + + - - - Archives assets - + + - - - Archive assets - + + - - - Archive the assets given to this archiver to the given archive. - - - + + - - - Write an assets metadata file to the given archive - - - + + - - - Write asset data files to the given archive - - - + + - - - Temporary code to do the bare minimum required to read a tar archive for our purposes - + + - - - Generate a tar reader which reads from the given stream. - - - + + - - - Binary reader for the underlying stream - + + - + - Used to trim off null chars + - - - Used to trim off space chars - + + - - - Read the next entry in the tar file. - - - - - - the data for the entry. Returns null if there are no more entries + + - - - Read the next 512 byte chunk of data as a tar header. - - A tar header struct. null if we have reached the end of the archive. + + - - - Read data following a header - - - - - + + - - - Convert octal bytes to a decimal representation - - - - - - - - - + + - - - Temporary code to produce a tar archive in tar v7 format - + + - - - Binary writer for the underlying stream - + + - - - Write a directory entry to the tar archive. We can only handle one path level right now! - - - + + - - - Write a file to the tar archive - - - - - + + - - - Write a file to the tar archive - - - - - + + - - - Finish writing the raw tar archive data to a stream. The stream will be closed on completion. - + + - - - Write a particular entry - - - - - - - + + - - - Represents an Animation - + + - - Default Constructor + + - - - Construct an Asset object of type Animation - - A unique specific to this asset - A byte array containing the raw asset data + + - - Override the base classes AssetType + + - - - Represents an that represents an avatars body ie: Hair, Etc. - + + - - Initializes a new instance of an AssetBodyPart object + + - - Initializes a new instance of an AssetBodyPart object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + - - Override the base classes AssetType + + - + + + + - Represents an that can be worn on an avatar - such as a Shirt, Pants, etc. + - - Initializes a new instance of an AssetScriptBinary object + + - - Initializes a new instance of an AssetScriptBinary object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + - - Override the base classes AssetType + + - - - Type of gesture step - + + - + - Base class for gesture steps + + + - + - Retururns what kind of gesture step this is + - - - Describes animation step of a gesture - + + - - - If true, this step represents start of animation, otherwise animation stop - + + - - - Animation asset + + - + + + + - Animation inventory name + + + - + - Returns what kind of gesture step this is + - + + + + + + + + + + + + + + + + + + + - Describes sound step of a gesture + - - - Sound asset + + - + + + + + + + + + + + + + - Sound inventory name + + + - + - Returns what kind of gesture step this is + + + - + - Describes sound step of a gesture + + + - + - Text to output in chat + + + + - + - Returns what kind of gesture step this is + - + - Describes sound step of a gesture + + + - + - If true in this step we wait for all animations to finish + + + - + - If true gesture player should wait for the specified amount of time + + + + + Positional vector of the users position + + + Velocity vector of the position + + + At Orientation (X axis) of the position + + + Up Orientation (Y axis) of the position + + + Left Orientation (Z axis) of the position - + - Time in seconds to wait if WaitForAnimation is false + Image width - + - Returns what kind of gesture step this is + Image height - + - Describes the final step of a gesture + Image channel flags - + - Returns what kind of gesture step this is + Red channel data - + - Represents a sequence of animations, sounds, and chat actions + Green channel data - + - Constructs guesture asset + Blue channel data - + - Constructs guesture asset + Alpha channel data - A unique specific to this asset - A byte array containing the raw asset data - + - Keyboard key that triggers the gestyre + Bump channel data - + - Modifier to the trigger key + Create a new blank image + width + height + channel flags - + - String that triggers playing of the gesture sequence + + - + - Text that replaces trigger in chat once gesture is triggered + Convert the channels in the image. Channels are created or destroyed as required. + new channel flags - + - Sequence of gesture steps + Resize or stretch the image using nearest neighbor (ugly) resampling + new width + new height - + - Returns asset type + Create a byte array containing 32-bit RGBA data with a bottom-left + origin, suitable for feeding directly into OpenGL + A byte array containing raw texture data - + - Encodes gesture asset suitable for uplaod + pre-defined built in sounds - - - Decodes gesture assset into play sequence - - true if the asset data was decoded successfully + + - - - Represents a Landmark with RegionID and Position vector - + + - - Construct an Asset of type Landmark + + - - - Construct an Asset object of type Landmark - - A unique specific to this asset - A byte array containing the raw asset data + + - - UUID of the Landmark target region + + - - Local position of the target + + - - Override the base classes AssetType + + - - - Encode the raw contents of a string with the specific Landmark format - + + - - - Decode the raw asset data, populating the RegionID and Position - - true if the AssetData was successfully decoded to a UUID and Vector + + coins - - - Represents a string of characters encoded with specific formatting properties - + + cash register bell - - Construct an Asset of type Notecard + + - - - Construct an Asset object of type Notecard - - A unique specific to this asset - A byte array containing the raw asset data + + - - A text string containing main text of the notecard + + rubber - - List of s embedded on the notecard + + plastic - - Override the base classes AssetType + + flesh - - - Encode the raw contents of a string with the specific Linden Text properties - + + wood splintering? - - - Decode the raw asset data including the Linden Text properties - - true if the AssetData was successfully decoded + + glass break - - - A linkset asset, containing a parent primitive and zero or more children - + + metal clunk - - Initializes a new instance of an AssetPrim object + + whoosh - - - Initializes a new instance of an AssetPrim object - - A unique specific to this asset - A byte array containing the raw asset data + + shake - - - Only used internally for XML serialization/deserialization - + + - - Override the base classes AssetType + + ding - - - + + - - - - - + + - - - The deserialized form of a single primitive in a linkset asset - + + - - - Represents an AssetScriptBinary object containing the - LSO compiled bytecode of an LSL script - + + - - Initializes a new instance of an AssetScriptBinary object + + - - Initializes a new instance of an AssetScriptBinary object with parameters - A unique specific to this asset - A byte array containing the raw asset data + + - - Override the base classes AssetType + + - - - TODO: Encodes a scripts contents into a LSO Bytecode file - + + - - - TODO: Decode LSO Bytecode into a string - - true + + - + + + + + + + + + + + + + + + + - Represents an LSL Text object containing a string of UTF encoded characters + A dictionary containing all pre-defined sounds + A dictionary containing the pre-defined sounds, + where the key is the sounds ID, and the value is a string + containing a name to identify the purpose of the sound - - Initializes a new AssetScriptText object - - + - Initializes a new AssetScriptText object with parameters + - A unique specific to this asset - A byte array containing the raw asset data - - A string of characters represting the script contents + + The avatar has no rights - - Override the base classes AssetType + + The avatar can see the online status of the target avatar - - - Encode a string containing the scripts contents into byte encoded AssetData - + + The avatar can see the location of the target avatar on the map - + + The avatar can modify the ojects of the target avatar + + - Decode a byte array containing the scripts contents into a string + This class holds information about an avatar in the friends list. There are two ways + to interface to this class. The first is through the set of boolean properties. This is the typical + way clients of this class will use it. The second interface is through two bitflag properties, + TheirFriendsRights and MyFriendsRights - true if decoding is successful - + - Represents a Sound Asset + Used internally when building the initial list of friends at login time + System ID of the avatar being prepesented + Rights the friend has to see you online and to modify your objects + Rights you have to see your friend online and to modify their objects - - Initializes a new instance of an AssetSound object - - - Initializes a new instance of an AssetSound object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - Override the base classes AssetType - - + - TODO: Encodes a sound file + FriendInfo represented as a string + A string reprentation of both my rights and my friends rights - + - TODO: Decode a sound file + System ID of the avatar - true - + - Represents a texture + full name of the avatar - - Initializes a new instance of an AssetTexture object - - + - Initializes a new instance of an AssetTexture object + True if the avatar is online - A unique specific to this asset - A byte array containing the raw asset data - + - Initializes a new instance of an AssetTexture object + True if the friend can see if I am online - A object containing texture data - - A object containing image data - - + + True if the friend can see me on the map - + + True if the freind can modify my objects - - Override the base classes AssetType - - + - Populates the byte array with a JPEG2000 - encoded image created from the data in + True if I can see if my friend is online + - + - Decodes the JPEG2000 data in AssetData to the - object - True if the decoding was successful, otherwise false + True if I can see if my friend is on the map + - + - Decodes the begin and end byte positions for each quality layer in - the image + True if I can modify my friend's objects - - - + - Represents a Wearable Asset, Clothing, Hair, Skin, Etc + My friend's rights represented as bitmapped flags - - Initializes a new instance of an AssetWearable object - - - Initializes a new instance of an AssetWearable object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - A string containing the name of the asset - - - A string containing a short description of the asset - - - The Assets WearableType - - - The For-Sale status of the object - - - An Integer representing the purchase price of the asset - - - The of the assets creator - - - The of the assets current owner - - - The of the assets prior owner - - - The of the Group this asset is set to - - - True if the asset is owned by a - - - The Permissions mask of the asset - - - A Dictionary containing Key/Value pairs of the objects parameters - - - A Dictionary containing Key/Value pairs where the Key is the textures Index and the Value is the Textures - - + - Decode an assets byte encoded data to a string + My rights represented as bitmapped flags - true if the asset data was decoded successfully - + - Encode the assets string represantion into a format consumable by the asset server + This class is used to add and remove avatars from your friends list and to manage their permission. - - = + + The event subscribers. null if no subcribers - - Number of times we've received an unknown CAPS exception in series. + + Raises the FriendOnline event + A FriendInfoEventArgs object containing the + data returned from the data server - - For exponential backoff on error. + + Thread sync lock object - - - A set of textures that are layered on texture of each other and "baked" - in to a single texture, for avatar appearances - + + The event subscribers. null if no subcribers - - - Default constructor - - Bake type + + Raises the FriendOffline event + A FriendInfoEventArgs object containing the + data returned from the data server - - Final baked texture + + Thread sync lock object - - Component layers + + The event subscribers. null if no subcribers - - Width of the final baked image and scratchpad + + Raises the FriendRightsUpdate event + A FriendInfoEventArgs object containing the + data returned from the data server - - Height of the final baked image and scratchpad + + Thread sync lock object - - Bake type + + The event subscribers. null if no subcribers - - Final baked texture + + Raises the FriendNames event + A FriendNamesEventArgs object containing the + data returned from the data server - - Component layers + + Thread sync lock object - - Width of the final baked image and scratchpad + + The event subscribers. null if no subcribers - - Height of the final baked image and scratchpad + + Raises the FriendshipOffered event + A FriendshipOfferedEventArgs object containing the + data returned from the data server - - Bake type + + Thread sync lock object - - Is this one of the 3 skin bakes + + The event subscribers. null if no subcribers - - - Adds layer for baking - - TexturaData struct that contains texture and its params + + Raises the FriendshipResponse event + A FriendshipResponseEventArgs object containing the + data returned from the data server - - - Converts avatar texture index (face) to Bake type - - Face number (AvatarTextureIndex) - BakeType, layer to which this texture belongs to + + Thread sync lock object - - - Make sure images exist, resize source if needed to match the destination - - Destination image - Source image - Sanitization was succefull + + The event subscribers. null if no subcribers - - - Fills a baked layer as a solid *appearing* color. The colors are - subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from - compressing it too far since it seems to cause upload failures if - the image is a pure solid color - - Color of the base of this layer + + Raises the FriendshipTerminated event + A FriendshipTerminatedEventArgs object containing the + data returned from the data server - - - Fills a baked layer as a solid *appearing* color. The colors are - subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from - compressing it too far since it seems to cause upload failures if - the image is a pure solid color - - Red value - Green value - Blue value + + Thread sync lock object + + + The event subscribers. null if no subcribers + + + Raises the FriendFoundReply event + A FriendFoundReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object - + - Create a new blank image + A dictionary of key/value pairs containing known friends of this avatar. + + The Key is the of the friend, the value is a + object that contains detailed information including permissions you have and have given to the friend - width - height - channel flags - + + A Dictionary of key/value pairs containing current pending frienship offers. + + The key is the of the avatar making the request, + the value is the of the request which is used to accept + or decline the friendship offer - - - + - Image width + Internal constructor + A reference to the GridClient Object - + - Image height + Accept a friendship request + agentID of avatatar to form friendship with + imSessionID of the friendship request message - + - Image channel flags + Decline a friendship request + of friend + imSessionID of the friendship request message - + - Red channel data + Overload: Offer friendship to an avatar. + System ID of the avatar you are offering friendship to - + - Green channel data + Offer friendship to an avatar. + System ID of the avatar you are offering friendship to + A message to send with the request - + - Blue channel data + Terminate a friendship with an avatar + System ID of the avatar you are terminating the friendship with - - - Alpha channel data - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - Bump channel data + Change the rights of a friend avatar. + the of the friend + the new rights to give the friend + This method will implicitly set the rights to those passed in the rights parameter. - + - Convert the channels in the image. Channels are created or destroyed as required. + Use to map a friends location on the grid. - new channel flags + Friends UUID to find + - + - Resize or stretch the image using nearest neighbor (ugly) resampling + Use to track a friends movement on the grid - new width - new height + Friends Key - + - Create a byte array containing 32-bit RGBA data with a bottom-left - origin, suitable for feeding directly into OpenGL + Ask for a notification of friend's online status - A byte array containing raw texture data + Friend's UUID - + - A Wrapper around openjpeg to encode and decode images to and from byte arrays + This handles the asynchronous response of a RequestAvatarNames call. + + names cooresponding to the the list of IDs sent the the RequestAvatarNames call. - - - Defines the beginning and ending file positions of a layer in an - LRCP-progression JPEG2000 file - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - This structure is used to marshal both encoded and decoded images. - MUST MATCH THE STRUCT IN dotnet.h! - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data + + - Information about a single packet in a JPEG2000 stream + Populate FriendList with data from the login reply + true if login was successful + true if login request is requiring a redirect + A string containing the response to the login request + A string containing the reason for the request + A object containing the decoded + reply from the login server - - Packet start position - - - Packet header end position + + Raised when the simulator sends notification one of the members in our friends list comes online - - Packet end position + + Raised when the simulator sends notification one of the members in our friends list goes offline - - TGA Header size + + Raised when the simulator sends notification one of the members in our friends list grants or revokes permissions - - OpenJPEG is not threadsafe, so this object is used to lock - during calls into unmanaged code + + Raised when the simulator sends us the names on our friends list - - - Encode a object into a byte array - - The object to encode - true to enable lossless conversion, only useful for small images ie: sculptmaps - A byte array containing the encoded Image object + + Raised when the simulator sends notification another agent is offering us friendship - - - Encode a object into a byte array - - The object to encode - a byte array of the encoded image + + Raised when a request we sent to friend another agent is accepted or declined - - - Decode JPEG2000 data to an and - - JPEG2000 encoded data - ManagedImage object to decode to - Image object to decode to - True if the decode succeeds, otherwise false + + Raised when the simulator sends notification one of the members in our friends list has terminated + our friendship - - - - - - - - - + + Raised when the simulator sends the location of a friend we have + requested map location info for - - - - - - - - - - - + + Contains information on a member of our friends list - + - Encode a object into a byte array + Construct a new instance of the FriendInfoEventArgs class - The source object to encode - true to enable lossless decoding - A byte array containing the source Bitmap object + The FriendInfo - - - Capability to load TGAs to Bitmap - + + Get the FriendInfo - - - Interface requirements for Messaging system - + + Contains Friend Names - + - Abstract base for rendering plugins + Construct a new instance of the FriendNamesEventArgs class + A dictionary where the Key is the ID of the Agent, + and the Value is a string containing their name - - - Generates a basic mesh structure from a primitive - - Primitive to generate the mesh from - Level of detail to generate the mesh at - The generated mesh + + A dictionary where the Key is the ID of the Agent, + and the Value is a string containing their name - - - Generates a basic mesh structure from a sculpted primitive and - texture - - Sculpted primitive to generate the mesh from - Sculpt texture - Level of detail to generate the mesh at - The generated mesh + + Sent when another agent requests a friendship with our agent - + - Generates a series of faces, each face containing a mesh and - metadata + Construct a new instance of the FriendshipOfferedEventArgs class - Primitive to generate the mesh from - Level of detail to generate the mesh at - The generated mesh + The ID of the agent requesting friendship + The name of the agent requesting friendship + The ID of the session, used in accepting or declining the + friendship offer - - - Generates a series of faces for a sculpted prim, each face - containing a mesh and metadata - - Sculpted primitive to generate the mesh from - Sculpt texture - Level of detail to generate the mesh at - The generated mesh + + Get the ID of the agent requesting friendship - - - Apply texture coordinate modifications from a - to a list of vertices - - Vertex list to modify texture coordinates for - Center-point of the face - Face texture parameters + + Get the name of the agent requesting friendship - - - Sent to the client to indicate a teleport request has completed - + + Get the ID of the session, used in accepting or declining the + friendship offer - - The of the agent + + A response containing the results of our request to form a friendship with another agent - + + Construct a new instance of the FriendShipResponseEventArgs class + The ID of the agent we requested a friendship with + The name of the agent we requested a friendship with + true if the agent accepted our friendship offer - - The simulators handle the agent teleported to - - - A Uri which contains a list of Capabilities the simulator supports - - - Indicates the level of access required - to access the simulator, or the content rating, or the simulators - map status - - - The IP Address of the simulator + + Get the ID of the agent we requested a friendship with - - The UDP Port the simulator will listen for UDP traffic on + + Get the name of the agent we requested a friendship with - - Status flags indicating the state of the Agent upon arrival, Flying, etc. + + true if the agent accepted our friendship offer - - - Serialize the object - - An containing the objects data + + Contains data sent when a friend terminates a friendship with us - + - Deserialize the message + Construct a new instance of the FrindshipTerminatedEventArgs class - An containing the data + The ID of the friend who terminated the friendship with us + The name of the friend who terminated the friendship with us - - - Sent to the viewer when a neighboring simulator is requesting the agent make a connection to it. - + + Get the ID of the agent that terminated the friendship with us - - - Serialize the object - - An containing the objects data + + Get the name of the agent that terminated the friendship with us - + - Deserialize the message + Data sent in response to a request which contains the information to allow us to map the friends location - An containing the data - + - Serialize the object + Construct a new instance of the FriendFoundReplyEventArgs class - An containing the objects data + The ID of the agent we have requested location information for + The region handle where our friend is located + The simulator local position our friend is located - - - Deserialize the message - - An containing the data + + Get the ID of the agent we have received location information for - - - Serialize the object - - An containing the objects data + + Get the region handle where our mapped friend is located - - - Deserialize the message - - An containing the data + + Get the simulator local position where our friend is located - + - A message sent to the client which indicates a teleport request has failed - and contains some information on why it failed + Return a decoded capabilities message as a strongly typed object + A string containing the name of the capabilities message key + An to decode + A strongly typed object containing the decoded information from the capabilities message, or null + if no existing Message object exists for the specified event - + + Represents an that represents an avatars body ie: Hair, Etc. - - A string key of the reason the teleport failed e.g. CouldntTPCloser - Which could be used to look up a value in a dictionary or enum + + Initializes a new instance of an AssetBodyPart object - - The of the Agent + + Initializes a new instance of an AssetBodyPart object with parameters + A unique specific to this asset + A byte array containing the raw asset data - - A string human readable message containing the reason - An example: Could not teleport closer to destination + + Override the base classes AssetType - + - Serialize the object + Archives assets - An containing the objects data - + - Deserialize the message + Archive assets - An containing the data - + - Serialize the object + Archive the assets given to this archiver to the given archive. - An containing the objects data + - + - Deserialize the message + Write an assets metadata file to the given archive - An containing the data + - + - Contains a list of prim owner information for a specific parcel in a simulator + Write asset data files to the given archive - - A Simulator will always return at least 1 entry - If agent does not have proper permission the OwnerID will be UUID.Zero - If agent does not have proper permission OR there are no primitives on parcel - the DataBlocksExtended map will not be sent from the simulator - + - + - Prim ownership information for a specified owner on a single parcel + - - The of the prim owner, - UUID.Zero if agent has no permission to view prim owner information - - - The total number of prims - - - True if the OwnerID is a - - - True if the owner is online - This is no longer used by the LL Simulators - - - The date the most recent prim was rezzed - - - An Array of objects - - + - Serialize the object + An instance of DelegateWrapper which calls InvokeWrappedDelegate, + which in turn calls the DynamicInvoke method of the wrapped + delegate - An containing the objects data - + - Deserialize the message + Callback used to call EndInvoke on the asynchronously + invoked DelegateWrapper - An containing the data - + - The details of a single parcel in a region, also contains some regionwide globals + Executes the specified delegate with the specified arguments + asynchronously on a thread pool thread + + - - Simulator-local ID of this parcel - - - Maximum corner of the axis-aligned bounding box for this - parcel - - - Minimum corner of the axis-aligned bounding box for this - parcel - - - Total parcel land area - - + + Invokes the wrapped delegate synchronously + + - - Key of authorized buyer - - - Bitmap describing land layout in 4x4m squares across the - entire region - - + + Calls EndInvoke on the wrapper and Close on the resulting WaitHandle + to prevent resource leaks + - - Date land was claimed - - - Appears to always be zero - - - Parcel Description - - + + Delegate to wrap another delegate and its arguments + + - - - + + The event subscribers. null if no subcribers - - Total number of primitives owned by the parcel group on - this parcel + + Raises the LandPatchReceived event + A LandPatchReceivedEventArgs object containing the + data returned from the simulator - - Whether the land is deeded to a group or not + + Thread sync lock object - + + Default constructor + - - Maximum number of primitives this parcel supports - - - The Asset UUID of the Texture which when applied to a - primitive will display the media + + Raised when the simulator responds sends - - A URL which points to any Quicktime supported media type + + Simulator from that sent tha data - - A byte, if 0x1 viewer should auto scale media to fit object + + Sim coordinate of the patch - - URL For Music Stream + + Sim coordinate of the patch - - Parcel Name + + Size of tha patch - - Autoreturn value in minutes for others' objects + + Heightmap for the patch - - - + + Size of the byte array used to store raw packet data - - Total number of other primitives on this parcel + + Raw packet data buffer - - UUID of the owner of this parcel + + Length of the data to transmit - - Total number of primitives owned by the parcel owner on - this parcel + + EndPoint of the remote host - + + Create an allocated UDP packet buffer for receiving a packet - - How long is pass valid for - - - Price for a temporary pass - - + + Create an allocated UDP packet buffer for sending a packet + EndPoint of the remote host - + + Create an allocated UDP packet buffer for sending a packet + EndPoint of the remote host + Size of the buffer to allocate for packet data - + + Object pool for packet buffers. This is used to allocate memory for all + incoming and outgoing packets, and zerocoding buffers for those packets - + + Initialize the object pool in client mode + Server to connect to + + - - True if the region denies access to age unverified users - - + + Initialize the object pool in server mode + + - - This field is no longer used - - - The result of a request for parcel properties - - Sale price of the parcel, only useful if ForSale is set - The SalePrice will remain the same after an ownership - transfer (sale), so it can be used to see the purchase price after - a sale if the new owner has not changed it - - + - Number of primitives your avatar is currently - selecting and sitting on in this parcel + Returns a packet buffer with EndPoint set if the buffer is in + client mode, or with EndPoint set to null in server mode + Initialized UDPPacketBuffer object - + + Default constructor - + - A number which increments by 1, starting at 0 for each ParcelProperties request. - Can be overriden by specifying the sequenceID with the ParcelPropertiesRequest being sent. - a Negative number indicates the action in has occurred. + Check a packet buffer out of the pool + A packet buffer object - - Maximum primitives across the entire simulator - - - Total primitives across the entire simulator + + + + + Looking direction, must be a normalized vector + Up direction, must be a normalized vector - + + Align the coordinate frame X and Y axis with a given rotation + around the Z axis in radians + Absolute rotation around the Z axis in + radians - - Key of parcel snapshot + + Origin position of this coordinate frame - - Parcel ownership status + + X axis of this coordinate frame, or Forward/At in grid terms - - Total number of primitives on this parcel + + Y axis of this coordinate frame, or Left in grid terms - - - + + Z axis of this coordinate frame, or Up in grid terms - + + Static pre-defined animations available to all agents - - A description of the media + + Agent with afraid expression on face - - An Integer which represents the height of the media + + Agent aiming a bazooka (right handed) - - An integer which represents the width of the media + + Agent aiming a bow (left handed) - - A boolean, if true the viewer should loop the media + + Agent aiming a hand gun (right handed) - - A string which contains the mime type of the media + + Agent aiming a rifle (right handed) - - true to obscure (hide) media url + + Agent with angry expression on face - - true to obscure (hide) music url + + Agent hunched over (away) - - - Serialize the object - - An containing the objects data + + Agent doing a backflip - - - Deserialize the message - - An containing the data + + Agent laughing while holding belly - - A message sent from the viewer to the simulator to updated a specific parcels settings + + Agent blowing a kiss - - The of the agent authorized to purchase this - parcel of land or a NULL if the sale is authorized to anyone + + Agent with bored expression on face - - true to enable auto scaling of the parcel media + + Agent bowing to audience - - The category of this parcel used when search is enabled to restrict - search results + + Agent brushing himself/herself off - - A string containing the description to set + + Agent in busy mode - - The of the which allows for additional - powers and restrictions. + + Agent clapping hands - - The which specifies how avatars which teleport - to this parcel are handled + + Agent doing a curtsey bow - - The LocalID of the parcel to update settings on + + Agent crouching - - A string containing the description of the media which can be played - to visitors + + Agent crouching while walking - - - + + Agent crying - - - + + Agent unanimated with arms out (e.g. setting appearance) - - - + + Agent re-animated after set appearance finished - - - + + Agent dancing - - - + + Agent dancing - - - + + Agent dancing - - - + + Agent dancing - - - + + Agent dancing - - - + + Agent dancing - - - + + Agent dancing - - - + + Agent dancing - - - + + Agent on ground unanimated - - - + + Agent boozing it up - - - + + Agent with embarassed expression on face + + + Agent with afraid expression on face + + + Agent with angry expression on face + + + Agent with bored expression on face - - - + + Agent crying - - - + + Agent showing disdain (dislike) for something - - - + + Agent with embarassed expression on face - - - Deserialize the message - - An containing the data + + Agent with frowning expression on face - - - Serialize the object - - An containing the objects data + + Agent with kissy face - - Base class used for the RemoteParcelRequest message + + Agent expressing laughgter - - - A message sent from the viewer to the simulator to request information - on a remote parcel - + + Agent with open mouth - - Local sim position of the parcel we are looking up + + Agent with repulsed expression on face - - Region handle of the parcel we are looking up + + Agent expressing sadness - - Region of the parcel we are looking up + + Agent shrugging shoulders - - - Serialize the object - - An containing the objects data + + Agent with a smile - - - Deserialize the message - - An containing the data + + Agent expressing surprise - - - A message sent from the simulator to the viewer in response to a - which will contain parcel information - + + Agent sticking tongue out - - The grid-wide unique parcel ID + + Agent with big toothy smile - - - Serialize the object - - An containing the objects data + + Agent winking - - - Deserialize the message - - An containing the data + + Agent expressing worry - - - A message containing a request for a remote parcel from a viewer, or a response - from the simulator to that request - + + Agent falling down - - The request or response details block + + Agent walking (feminine version) - - - Serialize the object - - An containing the objects data + + Agent wagging finger (disapproval) - - - Deserialize the message - - An containing the data + + I'm not sure I want to know - - - Serialize the object - - An containing the objects data + + Agent in superman position - - - Deserialize the message - - An containing the data + + Agent in superman position - - - Serialize the object - - An containing the objects data + + Agent greeting another - - - Deserialize the message - - An containing the data + + Agent holding bazooka (right handed) - - - A message sent from the simulator to an agent which contains - the groups the agent is in - + + Agent holding a bow (left handed) - - Group Details specific to the agent + + Agent holding a handgun (right handed) - - true of the agent accepts group notices + + Agent holding a rifle (right handed) - - The agents tier contribution to the group + + Agent throwing an object (right handed) - - The Groups + + Agent in static hover - - The of the groups insignia + + Agent hovering downward - - The name of the group + + Agent hovering upward - - The aggregate permissions the agent has in the group for all roles the agent - is assigned + + Agent being impatient - - An optional block containing additional agent specific information + + Agent jumping - - true of the agent allows this group to be - listed in their profile + + Agent jumping with fervor - - The Agent receiving the message + + Agent point to lips then rear end - - An array containing information - for each the agent is a member of + + Agent landing from jump, finished flight, etc - - An array containing information - for each the agent is a member of + + Agent laughing - - - Serialize the object - - An containing the objects data + + Agent landing from jump, finished flight, etc - - - Deserialize the message - - An containing the data + + Agent sitting on a motorcycle - - - A message sent from the viewer to the simulator which - specifies the language and permissions for others to detect - the language specified - + + - - A string containng the default language - to use for the agent + + Agent moving head side to side - - true of others are allowed to - know the language setting + + Agent moving head side to side with unhappy expression - - - Serialize the object - - An containing the objects data + + Agent taunting another - - - Deserialize the message - - An containing the data + + - - - An EventQueue message sent from the simulator to an agent when the agent - leaves a group - + + Agent giving peace sign - - An object containing the Agents UUID, and the Groups UUID + + Agent pointing at self - - The ID of the Agent leaving the group + + Agent pointing at another - - The GroupID the Agent is leaving + + Agent preparing for jump (bending knees) - - - An Array containing the AgentID and GroupID - + + Agent punching with left hand - - - Serialize the object - - An containing the objects data + + Agent punching with right hand + + + Agent acting repulsed - - - Deserialize the message - - An containing the data + + Agent trying to be Chuck Norris - - Base class for Asset uploads/results via Capabilities + + Rocks, Paper, Scissors 1, 2, 3 - - - The request state - + + Agent with hand flat over other hand - - - Serialize the object - - An containing the objects data + + Agent with fist over other hand - - - Deserialize the message - - An containing the data + + Agent with two fingers spread over other hand - - - A message sent from the viewer to the simulator to request a temporary upload capability - which allows an asset to be uploaded - + + Agent running - - The Capability URL sent by the simulator to upload the baked texture to + + Agent appearing sad - - - A message sent from the simulator that will inform the agent the upload is complete, - and the UUID of the uploaded asset - + + Agent saluting - - The uploaded texture asset ID + + Agent shooting bow (left handed) - - - A message sent from the viewer to the simulator to request a temporary - capability URI which is used to upload an agents baked appearance textures - + + Agent cupping mouth as if shouting - - Object containing request or response + + Agent shrugging shoulders - - - Serialize the object - - An containing the objects data + + Agent in sit position - - - Deserialize the message - - An containing the data + + Agent in sit position (feminine) - - - A message sent from the simulator which indicates the minimum version required for - using voice chat - + + Agent in sit position (generic) - - Major Version Required + + Agent sitting on ground - - Minor version required + + Agent sitting on ground - - The name of the region sending the version requrements + + - - - Serialize the object - - An containing the objects data + + Agent sleeping on side - - - Deserialize the message - - An containing the data + + Agent smoking - - - A message sent from the simulator to the viewer containing the - voice server URI - + + Agent inhaling smoke - - The Parcel ID which the voice server URI applies + + - - The name of the region + + Agent taking a picture - - A uri containing the server/channel information - which the viewer can utilize to participate in voice conversations + + Agent standing - - - Serialize the object - - An containing the objects data + + Agent standing up - - - Deserialize the message - - An containing the data + + Agent standing - - - + + Agent standing - - - + + Agent standing - - - + + Agent standing - - - Serialize the object - - An containing the objects data + + Agent stretching - - - Deserialize the message - - An containing the data + + Agent in stride (fast walk) - - - A message sent by the viewer to the simulator to request a temporary - capability for a script contained with in a Tasks inventory to be updated - + + Agent surfing - - Object containing request or response + + Agent acting surprised - - - Serialize the object - - An containing the objects data + + Agent striking with a sword - - - Deserialize the message - - An containing the data + + Agent talking (lips moving) - - - A message sent from the simulator to the viewer to indicate - a Tasks scripts status. - + + Agent throwing a tantrum - - The Asset ID of the script + + Agent throwing an object (right handed) - - True of the script is compiled/ran using the mono interpreter, false indicates it - uses the older less efficient lsl2 interprter + + Agent trying on a shirt - - The Task containing the scripts + + Agent turning to the left - - true of the script is in a running state + + Agent turning to the right - - - Serialize the object - - An containing the objects data + + Agent typing - - - Deserialize the message - - An containing the data + + Agent walking - - - A message containing the request/response used for updating a gesture - contained with an agents inventory - + + Agent whispering - - Object containing request or response + + Agent whispering with fingers in mouth - - - Serialize the object - - An containing the objects data + + Agent winking - - - Deserialize the message - - An containing the data + + Agent winking - - - A message request/response which is used to update a notecard contained within - a tasks inventory - + + Agent worried - - The of the Task containing the notecard asset to update + + Agent nodding yes - - The notecard assets contained in the tasks inventory + + Agent nodding yes with happy face - + + Agent floating with legs and arms crossed + + - Serialize the object + A dictionary containing all pre-defined animations - An containing the objects data + A dictionary containing the pre-defined animations, + where the key is the animations ID, and the value is a string + containing a name to identify the purpose of the animation - + - Deserialize the message + Type of gesture step - An containing the data - + - A reusable class containing a message sent from the viewer to the simulator to request a temporary uploader capability - which is used to update an asset in an agents inventory + Base class for gesture steps - + - The Notecard AssetID to replace + Retururns what kind of gesture step this is - + - Serialize the object + Describes animation step of a gesture - An containing the objects data - + - Deserialize the message + If true, this step represents start of animation, otherwise animation stop - An containing the data - + - A message containing the request/response used for updating a notecard - contained with an agents inventory + Animation asset - - Object containing request or response - - + - Serialize the object + Animation inventory name - An containing the objects data - + - Deserialize the message + Returns what kind of gesture step this is - An containing the data - + - Serialize the object + Describes sound step of a gesture - An containing the objects data - + - Deserialize the message + Sound asset - An containing the data - + - A message sent from the simulator to the viewer which indicates - an error occurred while attempting to update a script in an agents or tasks - inventory + Sound inventory name - - true of the script was successfully compiled by the simulator - - - A string containing the error which occured while trying - to update the script - - - A new AssetID assigned to the script - - + - A message sent from the viewer to the simulator - requesting the update of an existing script contained - within a tasks inventory + Returns what kind of gesture step this is - - if true, set the script mode to running - - - The scripts InventoryItem ItemID to update - - - A lowercase string containing either "mono" or "lsl2" which - specifies the script is compiled and ran on the mono runtime, or the older - lsl runtime - - - The tasks which contains the script to update - - + - Serialize the object + Describes sound step of a gesture - An containing the objects data - + - Deserialize the message + Text to output in chat - An containing the data - + - A message containing either the request or response used in updating a script inside - a tasks inventory + Returns what kind of gesture step this is - - Object containing request or response - - + - Serialize the object + Describes sound step of a gesture - An containing the objects data - + - Deserialize the message + If true in this step we wait for all animations to finish - An containing the data - + - Response from the simulator to notify the viewer the upload is completed, and - the UUID of the script asset and its compiled status + If true gesture player should wait for the specified amount of time - - The uploaded texture asset ID - - - true of the script was compiled successfully - - + - A message sent from a viewer to the simulator requesting a temporary uploader capability - used to update a script contained in an agents inventory + Time in seconds to wait if WaitForAnimation is false - - The existing asset if of the script in the agents inventory to replace - - - The language of the script - Defaults to lsl version 2, "mono" might be another possible option - - + - Serialize the object + Returns what kind of gesture step this is - An containing the objects data - + - Deserialize the message + Describes the final step of a gesture - An containing the data - + - A message containing either the request or response used in updating a script inside - an agents inventory + Returns what kind of gesture step this is - - Object containing request or response + + + Represents a sequence of animations, sounds, and chat actions + - + - Serialize the object + Keyboard key that triggers the gestyre - An containing the objects data - + - Deserialize the message + Modifier to the trigger key - An containing the data - + - Serialize the object + String that triggers playing of the gesture sequence - An containing the objects data - + - Deserialize the message + Text that replaces trigger in chat once gesture is triggered - An containing the data - - Base class for Map Layers via Capabilities + + + Sequence of gesture steps + - + + Constructs guesture asset - + - Serialize the object + Constructs guesture asset - An containing the objects data + A unique specific to this asset + A byte array containing the raw asset data - + - Deserialize the message + Encodes gesture asset suitable for uplaod - An containing the data - + - Sent by an agent to the capabilities server to request map layers + Decodes gesture assset into play sequence + true if the asset data was decoded successfully - + - A message sent from the simulator to the viewer which contains an array of map images and their grid coordinates + Returns asset type - + - An object containing map location details + Simulator (region) properties - - The Asset ID of the regions tile overlay + + No flags set - - The grid location of the southern border of the map tile + + Agents can take damage and be killed - - The grid location of the western border of the map tile + + Landmarks can be created here - - The grid location of the eastern border of the map tile + + Home position can be set in this sim - - The grid location of the northern border of the map tile + + Home position is reset when an agent teleports away - - An array containing LayerData items + + Sun does not move - - - Serialize the object - - An containing the objects data + + No object, land, etc. taxes - - - Deserialize the message - - An containing the data + + Disable heightmap alterations (agents can still plant + foliage) - - Object containing request or response + + Land cannot be released, sold, or purchased - - - Serialize the object - - An containing the objects data + + All content is wiped nightly - - - Deserialize the message - - An containing the data + + Unknown: Related to the availability of an overview world map tile.(Think mainland images when zoomed out.) - - - New as of 1.23 RC1, no details yet. - + + Unknown: Related to region debug flags. Possibly to skip processing of agent interaction with world. - - - Serialize the object - - An containing the objects data + + Region does not update agent prim interest lists. Internal debugging option. - - - Deserialize the message - - An containing the data + + No collision detection for non-agent objects - - - Serialize the object - - An containing the objects data + + No scripts are ran - - - Deserialize the message - - An containing the data + + All physics processing is turned off - - A string containing the method used + + Region can be seen from other regions on world map. (Legacy world map option?) - - - A request sent from an agent to the Simulator to begin a new conference. - Contains a list of Agents which will be included in the conference - + + Region can be seen from mainland on world map. (Legacy world map option?) - - An array containing the of the agents invited to this conference + + Agents not explicitly on the access list can visit the region. - - The conferences Session ID + + Traffic calculations are not run across entire region, overrides parcel settings. - - - Serialize the object - - An containing the objects data + + Flight is disabled (not currently enforced by the sim) - - - Deserialize the message - - An containing the data + + Allow direct (p2p) teleporting - - - A moderation request sent from a conference moderator - Contains an agent and an optional action to take - + + Estate owner has temporarily disabled scripting - - The Session ID + + Restricts the usage of the LSL llPushObject function, applies to whole region. - - - + + Deny agents with no payment info on file - - A list containing Key/Value pairs, known valid values: - key: text value: true/false - allow/disallow specified agents ability to use text in session - key: voice value: true/false - allow/disallow specified agents ability to use voice in session - - "text" or "voice" + + Deny agents with payment info on file - - - + + Deny agents who have made a monetary transaction - - - Serialize the object - - An containing the objects data + + Parcels within the region may be joined or divided by anyone, not just estate owners/managers. - - - Deserialize the message - - An containing the data + + Abuse reports sent from within this region are sent to the estate owner defined email. - - - A message sent from the agent to the simulator which tells the - simulator we've accepted a conference invitation - + + Region is Voice Enabled - - The conference SessionID + + Removes the ability from parcel owners to set their parcels to show in search. - - - Serialize the object - - An containing the objects data + + Deny agents who have not been age verified from entering the region. - + - Deserialize the message + Access level for a simulator - An containing the data - - - Serialize the object - - An containing the objects data + + Unknown or invalid access level - - - Deserialize the message - - An containing the data + + Trial accounts allowed - - - Serialize the object - - An containing the objects data + + PG rating - - - Deserialize the message - - An containing the data + + Mature rating - - - Serialize the object - - An containing the objects data + + Adult rating - + + Simulator is offline + + + Simulator does not exist + + - Deserialize the message + - An containing the data - - - Key of sender - - Name of sender + + A public reference to the client that this Simulator object + is attached to - - Key of destination avatar + + A Unique Cache identifier for this simulator - - ID of originating estate + + The capabilities for this simulator - - Key of originating region + + - - Coordinates in originating region + + The current version of software this simulator is running - - Instant message type + + - - Group IM session toggle + + A 64x64 grid of parcel coloring values. The values stored + in this array are of the type - - Key of IM session, for Group Messages, the groups UUID + + - - Timestamp of the instant message + + - - Instant message text + + - - Whether this message is held for offline avatars + + - - Context specific packed data + + - - Is this invitation for voice group/conference chat + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - Sent from the simulator to the viewer. - When an agent initially joins a session the AgentUpdatesBlock object will contain a list of session members including - a boolean indicating they can use voice chat in this session, a boolean indicating they are allowed to moderate - this session, and lastly a string which indicates another agent is entering the session with the Transition set to "ENTER" - During the session lifetime updates on individuals are sent. During the update the booleans sent during the initial join are - excluded with the exception of the Transition field. This indicates a new user entering or exiting the session with - the string "ENTER" or "LEAVE" respectively. - + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - An EventQueue message sent when the agent is forcibly removed from a chatterbox session - + + - - - A string containing the reason the agent was removed - + + - - - The ChatterBoxSession's SessionID - + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + true if your agent has Estate Manager rights on this region - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + - - - Serialize the object - - An containing the objects data + + - - - Deserialize the message - - An containing the data + + Statistics information for this simulator and the + connection to the simulator, calculated by the simulator itself + and the library - - - + + The regions Unique ID - - - Serialize the object - - An containing the objects data + + The physical data center the simulator is located + Known values are: + + Dallas + Chandler + SF + + - - - Deserialize the message - - An containing the data + + The CPU Class of the simulator + Most full mainland/estate sims appear to be 5, + Homesteads and Openspace appear to be 501 - - - Serialize the object - - An containing the objects data + + The number of regions sharing the same CPU as this one + "Full Sims" appear to be 1, Homesteads appear to be 4 - - - Deserialize the message - - An containing the data + + The billing product name + Known values are: + + Mainland / Full Region (Sku: 023) + Estate / Full Region (Sku: 024) + Estate / Openspace (Sku: 027) + Estate / Homestead (Sku: 029) + Mainland / Homestead (Sku: 129) (Linden Owned) + Mainland / Linden Homes (Sku: 131) + + - - - Serialize the object - - An containing the objects data + + The billing product SKU + Known values are: + + 023 Mainland / Full Region + 024 Estate / Full Region + 027 Estate / Openspace + 029 Estate / Homestead + 129 Mainland / Homestead (Linden Owned) + 131 Linden Homes / Full Region + + - - - Deserialize the message - - An containing the data + + The current sequence number for packets sent to this + simulator. Must be Interlocked before modifying. Only + useful for applications manipulating sequence numbers - + - A message sent from the viewer to the simulator which - specifies that the user has changed current URL - of the specific media on a prim face + A thread-safe dictionary containing avatars in a simulator - + - New URL + A thread-safe dictionary containing primitives in a simulator - + - Prim UUID where navigation occured + Provides access to an internal thread-safe dictionary containing parcel + information found in this simulator - + - Face index + Checks simulator parcel map to make sure it has downloaded all data successfully + true if map is full (contains no 0's) - - - Serialize the object - - An containing the objects data + + Used internally to track sim disconnections - - - Deserialize the message - - An containing the data + + Event that is triggered when the simulator successfully + establishes a connection - - Base class used for the ObjectMedia message + + Whether this sim is currently connected or not. Hooked up + to the property Connected - - - Message used to retrive prim media data - + + Coarse locations of avatars in this simulator - - - Prim UUID - + + AvatarPositions key representing TrackAgent target - - - Requested operation, either GET or UPDATE - + + Sequence numbers of packets we've received + (for duplicate checking) - - - Serialize object - - Serialized object as OSDMap + + Packets we sent out that need ACKs from the simulator - - - Deserialize the message - - An containing the data + + Sequence number for pause/resume - - - Message used to update prim media data - + + Indicates if UDP connection to the sim is fully established - + - Prim UUID + + Reference to the GridClient object + IPEndPoint of the simulator + handle of the simulator - + - Array of media entries indexed by face number + Called when this Simulator object is being destroyed - + - Media version string + Attempt to connect to this simulator + Whether to move our agent in to this sim or not + True if the connection succeeded or connection status is + unknown, false if there was a failure - + - Serialize object + Initiates connection to the simulator - Serialized object as OSDMap - + - Deserialize the message + Disconnect from this simulator - An containing the data - + - Message used to update prim media data + Instructs the simulator to stop sending update (and possibly other) packets - + - Prim UUID + Instructs the simulator to resume sending update packets (unpause) - + - Array of media entries indexed by face number + Retrieve the terrain height at a given coordinate + Sim X coordinate, valid range is from 0 to 255 + Sim Y coordinate, valid range is from 0 to 255 + The terrain height at the given point if the + lookup was successful, otherwise 0.0f + True if the lookup was successful, otherwise false - + - Requested operation, either GET or UPDATE + Sends a packet + Packet to be sent - + - Serialize object + - Serialized object as OSDMap - + - Deserialize the message + Returns Simulator Name as a String - An containing the data + - + - Message for setting or getting per face MediaEntry + + - - The request or response details block - - + - Serialize the object + - An containing the objects data + + - + - Deserialize the message + Sends out pending acknowledgements - An containing the data - - - Details about object resource usage - - - Object UUID - - - Object name - - - Indicates if object is group owned - - - Locatio of the object - - - Object owner - - - Resource usage, keys are resource names, values are resource usage for that specific resource + Number of ACKs sent - + - Deserializes object from OSD + Resend unacknowledged packets - An containing the data - + - Makes an instance based on deserialized data + Provides access to an internal thread-safe multidimensional array containing a x,y grid mapped + to each 64x64 parcel's LocalID. - - serialized data - Instance containg deserialized data - - - Details about parcel resource usage - - - Parcel UUID - - Parcel local ID + + The IP address and port of the server - - Parcel name + + Whether there is a working connection to the simulator or + not - - Indicates if parcel is group owned + + Coarse locations of avatars in this simulator - - Parcel owner + + AvatarPositions key representing TrackAgent target - - Array of containing per object resource usage + + Indicates if UDP connection to the sim is fully established - + - Deserializes object from OSD + Simulator Statistics - An containing the data - - - Makes an instance based on deserialized data - - - serialized data - Instance containg deserialized data + + Total number of packets sent by this simulator to this agent - - Resource usage base class, both agent and parcel resource - usage contains summary information + + Total number of packets received by this simulator to this agent - - Summary of available resources, keys are resource names, - values are resource usage for that specific resource + + Total number of bytes sent by this simulator to this agent - - Summary resource usage, keys are resource names, - values are resource usage for that specific resource + + Total number of bytes received by this simulator to this agent - - - Serializes object - - - serialized data + + Time in seconds agent has been connected to simulator - - - Deserializes object from OSD - - An containing the data + + Total number of packets that have been resent - - Agent resource usage + + Total number of resent packets recieved - - Per attachment point object resource usage + + Total number of pings sent to this simulator by this agent - - - Deserializes object from OSD - - An containing the data + + Total number of ping replies sent to this agent by this simulator - + - Makes an instance based on deserialized data + Incoming bytes per second - - serialized data - Instance containg deserialized data + It would be nice to have this claculated on the fly, but + this is far, far easier - + - Detects which class handles deserialization of this message + Outgoing bytes per second - An containing the data - Object capable of decoding this message + It would be nice to have this claculated on the fly, but + this is far, far easier - - Request message for parcel resource usage + + Time last ping was sent - - UUID of the parel to request resource usage info + + ID of last Ping sent - - - Serializes object - - - serialized data + + - - - Deserializes object from OSD - - An containing the data + + - - Response message for parcel resource usage + + Current time dilation of this simulator - - URL where parcel resource usage details can be retrieved + + Current Frames per second of simulator - - URL where parcel resource usage summary can be retrieved + + Current Physics frames per second of simulator - - - Serializes object - - - serialized data + + - - - Deserializes object from OSD - - An containing the data + + - - - Detects which class handles deserialization of this message - - An containing the data - Object capable of decoding this message + + - - Parcel resource usage + + - - Array of containing per percal resource usage + + - - - Deserializes object from OSD - - An containing the data + + - - - Return a decoded capabilities message as a strongly typed object - - A string containing the name of the capabilities message key - An to decode - A strongly typed object containing the decoded information from the capabilities message, or null - if no existing Message object exists for the specified event + + - - - Permissions for control of object media - + + - - - Style of cotrols that shold be displayed to the user - + + Total number of objects Simulator is simulating - - - Class representing media data for a single face - + + Total number of Active (Scripted) objects running - - Is display of the alternative image enabled + + Number of agents currently in this simulator - - Should media auto loop + + Number of agents in neighbor simulators - - Shoule media be auto played + + Number of Active scripts running in this simulator - - Auto scale media to prim face + + - - Should viewer automatically zoom in on the face when clicked + + - - Should viewer interpret first click as interaction with the media - or when false should the first click be treated as zoom in commadn + + - - Style of controls viewer should display when - viewer media on this face + + Number of downloads pending - - Starting URL for the media + + Number of uploads pending - - Currently navigated URL + + - - Media height in pixes + + - - Media width in pixels + + Number of local uploads pending - - Who can controls the media + + Unacknowledged bytes in queue + + + + Exception class to identify inventory exceptions + + + + + Responsible for maintaining inventory structure. Inventory constructs nodes + and manages node children as is necessary to maintain a coherant hirarchy. + Other classes should not manipulate or create InventoryNodes explicitly. When + A node's parent changes (when a folder is moved, for example) simply pass + Inventory the updated InventoryFolder and it will make the appropriate changes + to its internal representation. + + + + The event subscribers, null of no subscribers + + + Raises the InventoryObjectUpdated Event + A InventoryObjectUpdatedEventArgs object containing + the data sent from the simulator + + + Thread sync lock object + + + The event subscribers, null of no subscribers + + + Raises the InventoryObjectRemoved Event + A InventoryObjectRemovedEventArgs object containing + the data sent from the simulator - - Who can interact with the media + + Thread sync lock object - - Is URL whitelist enabled + + The event subscribers, null of no subscribers - - Array of URLs that are whitelisted + + Raises the InventoryObjectAdded Event + A InventoryObjectAddedEventArgs object containing + the data sent from the simulator - - - Serialize to OSD - - OSDMap with the serialized data + + Thread sync lock object - + - Deserialize from OSD data + Returns the contents of the specified folder - Serialized OSD data - Deserialized object + A folder's UUID + The contents of the folder corresponding to folder + When folder does not exist in the inventory - + - Particle system specific enumerators, flags and methods. + Updates the state of the InventoryNode and inventory data structure that + is responsible for the InventoryObject. If the item was previously not added to inventory, + it adds the item, and updates structure accordingly. If it was, it updates the + InventoryNode, changing the parent node if item.parentUUID does + not match node.Parent.Data.UUID. + + You can not set the inventory root folder using this method + The InventoryObject to store - + - Default constructor + Removes the InventoryObject and all related node data from Inventory. + The InventoryObject to remove. - + - Complete structure for the particle system + Used to find out if Inventory contains the InventoryObject + specified by uuid. + The UUID to check. + true if inventory contains uuid, false otherwise - + - Decodes a byte[] array into a ParticleSystem Object + Saves the current inventory structure to a cache file - ParticleSystem object - Start position for BitPacker + Name of the cache file to save to - + - Particle source pattern + Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful. + Name of the cache file to load + The number of inventory items sucessfully reconstructed into the inventory node tree - - None - - - Drop particles from source position with no force - - - "Explode" particles in all directions + + Raised when the simulator sends us data containing + ... - - Particles shoot across a 2D area + + Raised when the simulator sends us data containing + ... - - Particles shoot across a 3D Cone + + Raised when the simulator sends us data containing + ... - - Inverse of AngleCone (shoot particles everywhere except the 3D cone defined + + + The root folder of this avatars inventory + - + - Particle Data Flags + The default shared library folder - - None + + + The root node of the avatars inventory + - - Interpolate color and alpha from start to end + + + The root node of the default shared library + - - Interpolate scale from start to end + + + By using the bracket operator on this class, the program can get the + InventoryObject designated by the specified uuid. If the value for the corresponding + UUID is null, the call is equivelant to a call to RemoveNodeFor(this[uuid]). + If the value is non-null, it is equivelant to a call to UpdateNodeFor(value), + the uuid parameter is ignored. + + The UUID of the InventoryObject to get or set, ignored if set to non-null value. + The InventoryObject corresponding to uuid. - - Bounce particles off particle sources Z height + + + Holds group information for Avatars such as those you might find in a profile + - - velocity of particles is dampened toward the simulators wind + + true of Avatar accepts group notices - - Particles follow the source + + Groups Key - - Particles point towards the direction of source's velocity + + Texture Key for groups insignia - - Target of the particles + + Name of the group - - Particles are sent in a straight line + + Powers avatar has in the group - - Particles emit a glow + + Avatars Currently selected title - - used for point/grab/touch + + true of Avatar has chosen to list this in their profile - + - Particle Flags Enum + Contains an animation currently being played by an agent - - None - - - Acceleration and velocity for particles are - relative to the object rotation + + The ID of the animation asset - - Particles use new 'correct' angle parameters + + A number to indicate start order of currently playing animations + On Linden Grids this number is unique per region, with OpenSim it is per client - - Particle Flags - There appears to be more data packed in to this area - for many particle systems. It doesn't appear to be flag values - and serialization breaks unless there is a flag for every - possible bit so it is left as an unsigned integer + + - + - pattern of particles - - - A representing the maximimum age (in seconds) particle will be displayed - Maximum value is 30 seconds - - - A representing the number of seconds, - from when the particle source comes into view, - or the particle system's creation, that the object will emits particles; - after this time period no more particles are emitted - - - A in radians that specifies where particles will not be created + Holds group information on an individual profile pick + - - A in radians that specifies where particles will be created + + + Retrieve friend status notifications, and retrieve avatar names and + profiles + - - A representing the number of seconds between burts. + + The event subscribers, null of no subscribers - - A representing the number of meters - around the center of the source where particles will be created. + + Raises the AvatarAnimation Event + An AvatarAnimationEventArgs object containing + the data sent from the simulator - - A representing in seconds, the minimum speed between bursts of new particles - being emitted + + Thread sync lock object - - A representing in seconds the maximum speed of new particles being emitted. + + The event subscribers, null of no subscribers - - A representing the maximum number of particles emitted per burst + + Raises the AvatarAppearance Event + A AvatarAppearanceEventArgs object containing + the data sent from the simulator - - A which represents the velocity (speed) from the source which particles are emitted + + Thread sync lock object - - A which represents the Acceleration from the source which particles are emitted + + The event subscribers, null of no subscribers - - The Key of the texture displayed on the particle + + Raises the UUIDNameReply Event + A UUIDNameReplyEventArgs object containing + the data sent from the simulator - - The Key of the specified target object or avatar particles will follow + + Thread sync lock object - - Flags of particle from + + The event subscribers, null of no subscribers - - Max Age particle system will emit particles for + + Raises the AvatarInterestsReply Event + A AvatarInterestsReplyEventArgs object containing + the data sent from the simulator - - The the particle has at the beginning of its lifecycle + + Thread sync lock object - - The the particle has at the ending of its lifecycle + + The event subscribers, null of no subscribers - - A that represents the starting X size of the particle - Minimum value is 0, maximum value is 4 + + Raises the AvatarPropertiesReply Event + A AvatarPropertiesReplyEventArgs object containing + the data sent from the simulator - - A that represents the starting Y size of the particle - Minimum value is 0, maximum value is 4 + + Thread sync lock object - - A that represents the ending X size of the particle - Minimum value is 0, maximum value is 4 + + The event subscribers, null of no subscribers - - A that represents the ending Y size of the particle - Minimum value is 0, maximum value is 4 + + Raises the AvatarGroupsReply Event + A AvatarGroupsReplyEventArgs object containing + the data sent from the simulator - - - Generate byte[] array from particle data - - Byte array + + Thread sync lock object - - - Parameters used to construct a visual representation of a primitive - + + The event subscribers, null of no subscribers - - - + + Raises the AvatarPickerReply Event + A AvatarPickerReplyEventArgs object containing + the data sent from the simulator - - - + + Thread sync lock object - - - + + The event subscribers, null of no subscribers - - - + + Raises the ViewerEffectPointAt Event + A ViewerEffectPointAtEventArgs object containing + the data sent from the simulator - - - + + Thread sync lock object - - - + + The event subscribers, null of no subscribers - - - + + Raises the ViewerEffectLookAt Event + A ViewerEffectLookAtEventArgs object containing + the data sent from the simulator - - - + + Thread sync lock object - - - + + The event subscribers, null of no subscribers - - - + + Raises the ViewerEffect Event + A ViewerEffectEventArgs object containing + the data sent from the simulator - - - + + Thread sync lock object - - - + + The event subscribers, null of no subscribers - - - + + Raises the AvatarPicksReply Event + A AvatarPicksReplyEventArgs object containing + the data sent from the simulator - - - + + Thread sync lock object - - - + + The event subscribers, null of no subscribers - - - + + Raises the PickInfoReply Event + A PickInfoReplyEventArgs object containing + the data sent from the simulator - - - + + Thread sync lock object - - - + + The event subscribers, null of no subscribers - - - + + Raises the AvatarClassifiedReply Event + A AvatarClassifiedReplyEventArgs object containing + the data sent from the simulator - - - + + Thread sync lock object - - - + + The event subscribers, null of no subscribers - - Attachment point to an avatar + + Raises the ClassifiedInfoReply Event + A ClassifiedInfoReplyEventArgs object containing + the data sent from the simulator - - - + + Thread sync lock object - + + Represents other avatars + - - - + + Tracks the specified avatar on your map + Avatar ID to track - + + Request a single avatar name + The avatar key to retrieve a name for - + - Information on the flexible properties of a primitive + Request a list of avatar names + The avatar keys to retrieve names for - + - Default constructor + Start a request for Avatar Properties + - + + Search for an avatar (first name, last name) - - - - + The name to search for + An ID to associate with this query - + + Start a request for Avatar Picks + UUID of the avatar - + + Start a request for Avatar Classifieds + UUID of the avatar - + + Start a request for details of a specific profile pick + UUID of the avatar + UUID of the profile pick - + + Start a request for details of a specific profile classified + UUID of the avatar + UUID of the profile classified - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - Information on the light properties of a primitive - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - + - Default constructor + Crossed region handler for message that comes across the EventQueue. Sent to an agent + when the agent crosses a sim border into a new region. + The message key + the IMessage object containing the deserialized data sent from the simulator + The which originated the packet - - - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - - - + + Raised when the simulator sends us data containing + an agents animation playlist - - - Information on the sculpt properties of a sculpted primitive - + + Raised when the simulator sends us data containing + the appearance information for an agent - - - Default constructor - + + Raised when the simulator sends us data containing + agent names/id values - - - - - - - + + Raised when the simulator sends us data containing + the interests listed in an agents profile - - - Render inside out (inverts the normals). - + + Raised when the simulator sends us data containing + profile property information for an agent - - - Render an X axis mirror of the sculpty. - + + Raised when the simulator sends us data containing + the group membership an agent is a member of - - - Extended properties to describe an object - + + Raised when the simulator sends us data containing + name/id pair - - - Default constructor - + + Raised when the simulator sends us data containing + the objects and effect when an agent is pointing at - - - + + Raised when the simulator sends us data containing + the objects and effect when an agent is looking at - - - + + Raised when the simulator sends us data containing + an agents viewer effect information - - - + + Raised when the simulator sends us data containing + the top picks from an agents profile - - - + + Raised when the simulator sends us data containing + the Pick details - - - + + Raised when the simulator sends us data containing + the classified ads an agent has placed - - - + + Raised when the simulator sends us data containing + the details of a classified ad - - - + + Provides data for the event + The event occurs when the simulator sends + the animation playlist for an agent + + The following code example uses the and + properties to display the animation playlist of an avatar on the window. + + // subscribe to the event + Client.Avatars.AvatarAnimation += Avatars_AvatarAnimation; + + private void Avatars_AvatarAnimation(object sender, AvatarAnimationEventArgs e) + { + // create a dictionary of "known" animations from the Animations class using System.Reflection + Dictionary<UUID, string> systemAnimations = new Dictionary<UUID, string>(); + Type type = typeof(Animations); + System.Reflection.FieldInfo[] fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + foreach (System.Reflection.FieldInfo field in fields) + { + systemAnimations.Add((UUID)field.GetValue(type), field.Name); + } + + // find out which animations being played are known animations and which are assets + foreach (Animation animation in e.Animations) + { + if (systemAnimations.ContainsKey(animation.AnimationID)) + { + Console.WriteLine("{0} is playing {1} ({2}) sequence {3}", e.AvatarID, + systemAnimations[animation.AnimationID], animation.AnimationSequence); + } + else + { + Console.WriteLine("{0} is playing {1} (Asset) sequence {2}", e.AvatarID, + animation.AnimationID, animation.AnimationSequence); + } + } + } + + - + + Construct a new instance of the AvatarAnimationEventArgs class + The ID of the agent + The list of animations to start - - - + + Get the ID of the agent - - - + + Get the list of animations to start - - - + + Provides data for the event + The event occurs when the simulator sends + the appearance data for an avatar + + The following code example uses the and + properties to display the selected shape of an avatar on the window. + + // subscribe to the event + Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; + + // handle the data when the event is raised + void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) + { + Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") + } + + - + + Construct a new instance of the AvatarAppearanceEventArgs class + The simulator request was from + The ID of the agent + true of the agent is a trial account + The default agent texture + The agents appearance layer textures + The for the agent - - - + + Get the Simulator this request is from of the agent - - - + + Get the ID of the agent - - - + + true if the agent is a trial account - - - + + Get the default agent texture - - - + + Get the agents appearance layer textures - - - + + Get the for the agent - - - + + Represents the interests from the profile of an agent - - - + + Get the ID of the agent - - - + + The properties of an agent - - - + + Get the ID of the agent - - - + + Get the ID of the agent - - - Set the properties that are set in an ObjectPropertiesFamily packet - - - that has - been partially filled by an ObjectPropertiesFamily packet + + Get the ID of the agent - + + Get the ID of the avatar + + - Texture animation mode + - - Disable texture animation + + OK - - Enable texture animation + + Transfer completed - - Loop when animating textures + + - - Animate in reverse direction + + - - Animate forward then reverse + + Unknown error occurred - - Slide texture smoothly instead of frame-stepping + + Equivalent to a 404 error - - Rotate texture instead of using frames + + Client does not have permission for that resource - - Scale texture instead of using frames + + Unknown status - + - A single textured face. Don't instantiate this class yourself, use the - methods in TextureEntry + - + + + + + Unknown + + + Virtually all asset transfers use this channel + + - Contains the definition for individual faces + - - - - - + + + + + Asset from the asset server + + + Inventory item + + + Estate asset, such as an estate covenant - + + - - - + + - - - + + - - - + + - + + - - - + + - - - + + - + + Image file format - + + - - In the future this will specify whether a webpage is - attached to this face + + Number of milliseconds passed since the last transfer + packet was received - + + - + + - - - + - Represents all of the texturable faces for an object + - Grid objects have infinite faces, with each face - using the properties of the default face unless set otherwise. So if - you have a TextureEntry with a default texture uuid of X, and face 18 - has a texture UUID of Y, every face would be textured with X except for - face 18 that uses Y. In practice however, primitives utilize a maximum - of nine faces - + - Constructor that takes a default texture UUID + - Texture UUID to use as the default texture - + - Constructor that takes a TextureEntryFace for the - default face + - Face to use as the default face - + - Constructor that creates the TextureEntry class from a byte array + - Byte array containing the TextureEntry field - Starting position of the TextureEntry field in - the byte array - Length of the TextureEntry field, in bytes + + + + - + + - - - + + Number of milliseconds to wait for a transfer header packet if out of order data was received - - - This will either create a new face if a custom face for the given - index is not defined, or return the custom face for that index if - it already exists - - The index number of the face to create or - retrieve - A TextureEntryFace containing all the properties for that - face + + The event subscribers. null if no subcribers - - - - - - - + + Raises the XferReceived event + A XferReceivedEventArgs object containing the + data returned from the simulator - - - - - + + Thread sync lock object - - - - - + + The event subscribers. null if no subcribers - - - - - + + Raises the AssetUploaded event + A AssetUploadedEventArgs object containing the + data returned from the simulator - - - Controls the texture animation of a particular prim - + + Thread sync lock object - - - - - - - + + The event subscribers. null if no subcribers - - - + + Raises the UploadProgress event + A UploadProgressEventArgs object containing the + data returned from the simulator - - - + + Thread sync lock object - - - + + The event subscribers. null if no subcribers - - - + + Raises the InitiateDownload event + A InitiateDownloadEventArgs object containing the + data returned from the simulator - - - + + Thread sync lock object - - - + + The event subscribers. null if no subcribers - - - + + Raises the ImageReceiveProgress event + A ImageReceiveProgressEventArgs object containing the + data returned from the simulator - - - - - + + Thread sync lock object - + + Texture download cache + + - Current version of the media data for the prim + Default constructor + A reference to the GridClient object - + - Array of media entries indexed by face number + Request an asset download + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + The callback to fire when the simulator responds with the asset data - + + Request an asset download + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + Source location of the requested asset + The callback to fire when the simulator responds with the asset data - + + Request an asset download + Asset UUID + Asset type, must be correct for the transfer to succeed + Whether to give this transfer an elevated priority + Source location of the requested asset + UUID of the transaction + The callback to fire when the simulator responds with the asset data - + + Request an asset download through the almost deprecated Xfer system + Filename of the asset to request + Whether or not to delete the asset + off the server after it is retrieved + Use large transfer packets or not + UUID of the file to request, if filename is + left empty + Asset type of vFileID, or + AssetType.Unknown if filename is not empty + Sets the FilePath in the request to Cache + (4) if true, otherwise Unknown (0) is used + - + + + Use UUID.Zero if you do not have the + asset ID but have all the necessary permissions + The item ID of this asset in the inventory + Use UUID.Zero if you are not requesting an + asset from an object inventory + The owner of this asset + Asset type + Whether to prioritize this asset download or not + - + + Used to force asset data into the PendingUpload property, ie: for raw terrain uploads + An AssetUpload object containing the data to upload to the simulator - + + Request an asset be uploaded to the simulator + The Object containing the asset data + If True, the asset once uploaded will be stored on the simulator + in which the client was connected in addition to being stored on the asset server + The of the transfer, can be used to correlate the upload with + events being fired - + + Request an asset be uploaded to the simulator + The of the asset being uploaded + A byte array containing the encoded asset data + If True, the asset once uploaded will be stored on the simulator + in which the client was connected in addition to being stored on the asset server + The of the transfer, can be used to correlate the upload with + events being fired - - Foliage type for this primitive. Only applicable if this - primitive is foliage - - - Unknown - - + + Request an asset be uploaded to the simulator + + Asset type to upload this data as + A byte array containing the encoded asset data + If True, the asset once uploaded will be stored on the simulator + in which the client was connected in addition to being stored on the asset server + The of the transfer, can be used to correlate the upload with + events being fired - + + Initiate an asset upload + The ID this asset will have if the + upload succeeds + Asset type to upload this data as + Raw asset data to upload + Whether to store this asset on the local + simulator or the grid-wide asset server + The tranaction id for the upload + The transaction ID of this transfer - - - + + + Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + A float indicating the requested priority for the transfer. Higher priority values tell the simulator + to prioritize the request before lower valued requests. An image already being transferred using the can have + its priority changed by resending the request with the new priority value + Number of quality layers to discard. + This controls the end marker of the data sent. Sending with value -1 combined with priority of 0 cancels an in-progress + transfer. + A bug exists in the Linden Simulator where a -1 will occasionally be sent with a non-zero priority + indicating an off-by-one error. + The packet number to begin the request at. A value of 0 begins the request + from the start of the asset texture + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + If true, the callback will be fired for each chunk of the downloaded image. + The callback asset parameter will contain all previously received chunks of the texture asset starting + from the beginning of the request + + Request an image and fire a callback when the request is complete + + Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); + + private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) + { + if(state == TextureRequestState.Finished) + { + Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", + asset.AssetID, + asset.AssetData.Length); + } + } + + Request an image and use an inline anonymous method to handle the downloaded texture data + + Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, delegate(TextureRequestState state, AssetTexture asset) + { + if(state == TextureRequestState.Finished) + { + Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", + asset.AssetID, + asset.AssetData.Length); + } + } + ); + + Request a texture, decode the texture to a bitmap image and apply it to a imagebox + + Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); + + private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) + { + if(state == TextureRequestState.Finished) + { + ManagedImage imgData; + Image bitmap; + + if (state == TextureRequestState.Finished) + { + OpenJPEG.DecodeToImage(assetTexture.AssetData, out imgData, out bitmap); + picInsignia.Image = bitmap; + } + } + } + + - + + Overload: Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + The of the texture asset to download + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data - + + Overload: Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data - + + Overload: Request a texture asset from the simulator using the system to + manage the requests and re-assemble the image from the packets received from the simulator + The of the texture asset to download + The of the texture asset. + Use for most textures, or for baked layer texture assets + The callback to fire when the image is retrieved. The callback + will contain the result of the request and the texture asset data + If true, the callback will be fired for each chunk of the downloaded image. + The callback asset parameter will contain all previously received chunks of the texture asset starting + from the beginning of the request - + + Cancel a texture request + The texture assets - + + Lets TexturePipeline class fire the progress event + The texture ID currently being downloaded + the number of bytes transferred + the total number of bytes expected - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - Identifies the owner if audio or a particle system is - active + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Process an incoming packet and raise the appropriate events + The sender + The EventArgs object containing the packet data - - - + + Raised when the simulator responds sends - - - + + Raised during upload completes - - - + + Raised during upload with progres update - - - + + Fired when the simulator sends an InitiateDownloadPacket, used to download terrain .raw files - - - + + Fired when a texture is in the process of being downloaded by the TexturePipeline class - + + Callback used for various asset download requests + Transfer information + Downloaded asset, null on fail - + + Callback used upon competition of baked texture upload + Asset UUID of the newly uploaded baked texture - - - + + Xfer data - - - + + Upload data - - - + + Filename used on the simulator - - - + + Filename used by the client - - Uses basic heuristics to estimate the primitive shape + + UUID of the image that is in progress - - - Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew - parameters in to signed eight bit values - - Floating point parameter to pack - Signed eight bit value containing the packed parameter + + Number of bytes received so far - - - Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew - parameters from signed eight bit integers to floating point values - - Signed eight bit value to unpack - Unpacked floating point value + + Image size in bytes - + - The type of bump-mapping applied to a face + A set of textures that are layered on texture of each other and "baked" + in to a single texture, for avatar appearances - - - + + Final baked texture - - - + + Component layers - - - + + Width of the final baked image and scratchpad - - - + + Height of the final baked image and scratchpad - - - + + Bake type - + + Default constructor + Bake type - + + Adds layer for baking + TexturaData struct that contains texture and its params - + + Converts avatar texture index (face) to Bake type + Face number (AvatarTextureIndex) + BakeType, layer to which this texture belongs to - + + Make sure images exist, resize source if needed to match the destination + Destination image + Source image + Sanitization was succefull - + + Fills a baked layer as a solid *appearing* color. The colors are + subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from + compressing it too far since it seems to cause upload failures if + the image is a pure solid color + Color of the base of this layer - + + Fills a baked layer as a solid *appearing* color. The colors are + subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from + compressing it too far since it seems to cause upload failures if + the image is a pure solid color + Red value + Green value + Blue value - + + Final baked texture + + + Component layers + + + Width of the final baked image and scratchpad + + + Height of the final baked image and scratchpad + + + Bake type + + + Is this one of the 3 skin bakes + + + Represents a string of characters encoded with specific formatting properties - + + A text string containing main text of the notecard + + + List of s embedded on the notecard + + + Construct an Asset of type Notecard + + + Construct an Asset object of type Notecard + A unique specific to this asset + A byte array containing the raw asset data - + + Encode the raw contents of a string with the specific Linden Text properties - + + Decode the raw asset data including the Linden Text properties + true if the AssetData was successfully decoded - - - + + Override the base classes AssetType - + + Add a custom decoder callback + The key of the field to decode + The custom decode handler - + + Remove a custom decoder callback + The key of the field to decode + The custom decode handler - + - The level of shininess applied to a face + Creates a formatted string containing the values of a Packet + The Packet + A formatted string of values of the nested items in the Packet object - + + Decode an IMessage object into a beautifully formatted string + The IMessage object + Recursion level (used for indenting) + A formatted string containing the names and values of the source object - + + A custom decoder callback + The key of the object + the data to decode + A string represending the fieldData - + + Registers, unregisters, and fires events generated by incoming packets - - - + + Reference to the GridClient object - + - The texture mapping style used for a face + Default constructor + - + + Register an event handler + Use PacketType.Default to fire this event on every + incoming packet + Packet type to register the handler for + Callback to be fired + True if this callback should be ran + asynchronously, false to run it synchronous - + + Unregister an event handler + Packet type to unregister the handler for + Callback to be unregistered - + + Fire the events registered for this packet type + Incoming packet type + Incoming packet + Simulator this packet was received from - + + Object that is passed to worker threads in the ThreadPool for + firing packet callbacks - - - Flags in the TextureEntry block that describe which properties are - set - + + Callback to fire for this packet - + + Reference to the simulator that this packet came from + + + The packet that needs to be processed + + + Registers, unregisters, and fires events generated by the Capabilities + event queue - + + Reference to the GridClient object + + + Default constructor + Reference to the GridClient object - + + Register an new event handler for a capabilities event sent via the EventQueue + Use String.Empty to fire this event on every CAPS event + Capability event name to register the + handler for + Callback to fire - + + Unregister a previously registered capabilities handler + Capability event name unregister the + handler for + Callback to unregister - + + Fire the events registered for this event type synchronously + Capability name + Decoded event body + Reference to the simulator that + generated this event - + + Fire the events registered for this event type asynchronously + Capability name + Decoded event body + Reference to the simulator that + generated this event - + + Object that is passed to worker threads in the ThreadPool for + firing CAPS callbacks - + + Callback to fire for this packet + + + Name of the CAPS event + + + Strongly typed decoded data + + + Reference to the simulator that generated this event + + + Represends individual HTTP Download request - + + URI of the item to fetch + + + Timout specified in milliseconds + + + Download progress callback + + + Download completed callback + + + Accept the following content type + + + Default constructor + + + Constructor + + + Manages async HTTP downloads with a limit on maximum + concurrent downloads - + + Default constructor + + + Cleanup method + + + Setup http download request + + + Check the queue for pending work + + + Enqueue a new HTPP download + + + Maximum number of parallel downloads from a single endpoint + + + Client certificate + + + Index of TextureEntry slots for avatar appearances - + + Bake layers for avatar appearance - - - + + Maximum number of concurrent downloads for wearable assets and textures + + + Maximum number of concurrent uploads for baked textures + + + Timeout for fetching inventory listings + + + Timeout for fetching a single wearable, or receiving a single packet response + + + Timeout for fetching a single texture + + + Timeout for uploading a single baked texture + + + Number of times to retry bake upload + + + When changing outfit, kick off rebake after + 20 seconds has passed since the last change + + + Total number of wearables for each avatar + + + Total number of baked textures on each avatar + + + Total number of wearables per bake layer + + + Total number of textures on an avatar, baked or not + + + Mapping between BakeType and AvatarTextureIndex + + + Map of what wearables are included in each bake + + + Magic values to finalize the cache check hashes for each + bake + + + Default avatar texture, used to detect when a custom + texture is not set for a face + + + The event subscribers. null if no subcribers + + + Raises the AgentWearablesReply event + An AgentWearablesReplyEventArgs object containing the + data returned from the data server + + + Thread sync lock object + + + The event subscribers. null if no subcribers - - - Level of Detail mesh - + + Raises the CachedBakesReply event + An AgentCachedBakesReplyEventArgs object containing the + data returned from the data server AgentCachedTextureResponse - - - Constructor for default logging settings - + + Thread sync lock object - - Enable logging + + The event subscribers. null if no subcribers - - The folder where any logs will be created + + Raises the AppearanceSet event + An AppearanceSetEventArgs object indicating if the operatin was successfull - - This will be prepended to beginning of each log file + + Thread sync lock object - - The suffix or extension to be appended to each log file + + The event subscribers. null if no subcribers - - - 0: NONE - No logging - 1: ERROR - Log errors only - 2: WARNING - Log errors and warnings - 3: INFO - Log errors, warnings and info - 4: DEBUG - Log errors, warnings, info and debug - + + Raises the RebakeAvatarRequested event + An RebakeAvatarTexturesEventArgs object containing the + data returned from the data server - - Audio Properties Events are sent after audio capture is started. These events are used to display a microphone VU meter - - - Event for most mundane request reposnses. - + + Thread sync lock object - - Response to Connector.Create request + + A cache of wearables currently being worn - - Response to Aux.GetCaptureDevices request + + A cache of textures currently being worn - - Response to Aux.GetRenderDevices request + + Incrementing serial number for AgentCachedTexture packets - - Audio Properties Events are sent after audio capture is started. - These events are used to display a microphone VU meter + + Incrementing serial number for AgentSetAppearance packets - - Response to Account.Login request + + Indicates whether or not the appearance thread is currently + running, to prevent multiple appearance threads from running + simultaneously - - This event message is sent whenever the login state of the - particular Account has transitioned from one value to another + + Reference to our agent - + - List of audio input devices + Timer used for delaying rebake on changing outfit - + - List of audio output devices + Main appearance thread - + - Set audio test mode + Default constructor + A reference to our agent - + - This is used to login a specific user account(s). It may only be called after - Connector initialization has completed successfully + Obsolete method for setting appearance. This function no longer does anything. + Use RequestSetAppearance() to manually start the appearance thread - Handle returned from successful Connector �create� request - User's account name - User's account password - Values may be �AutoAnswer� or �VerifyAnswer� - "" - This is an integer that specifies how often - the daemon will send participant property events while in a channel. If this is not set - the default will be �on state change�, which means that the events will be sent when - the participant starts talking, stops talking, is muted, is unmuted. - The valid values are: - 0 � Never - 5 � 10 times per second - 10 � 5 times per second - 50 � 1 time per second - 100 � on participant state change (this is the default) - false - - - + - This is used to logout a user session. It should only be called with a valid AccountHandle. + Obsolete method for setting appearance. This function no longer does anything. + Use RequestSetAppearance() to manually start the appearance thread - Handle returned from successful Connector �login� request - - + Unused parameter - + - This is used to get a list of audio devices that can be used for capture (input) of voice. + Starts the appearance setting thread - - - + - This is used to get a list of audio devices that can be used for render (playback) of voice. + Starts the appearance setting thread + True to force rebaking, otherwise false - + - This command is used to select the render device. + Ask the server what textures our agent is currently wearing - The name of the device as returned by the Aux.GetRenderDevices command. - + - This command is used to select the capture device. + Build hashes out of the texture assetIDs for each baking layer to + ask the simulator whether it has cached copies of each baked texture - The name of the device as returned by the Aux.GetCaptureDevices command. - + - This command is used to start the audio capture process which will cause - AuxAudioProperty Events to be raised. These events can be used to display a - microphone VU meter for the currently selected capture device. This command - should not be issued if the user is on a call. + Returns the AssetID of the asset that is currently being worn in a + given WearableType slot - (unused but required) - - + WearableType slot to get the AssetID for + The UUID of the asset being worn in the given slot, or + UUID.Zero if no wearable is attached to the given slot or wearables + have not been downloaded yet - + - This command is used to stop the audio capture process. + Add a wearable to the current outfit and set appearance - - + Wearable to be added to the outfit - + - This command is used to set the mic volume while in the audio tuning process. - Once an acceptable mic level is attained, the application must issue a - connector set mic volume command to have that level be used while on voice - calls. + Add a list of wearables to the current outfit and set appearance - the microphone volume (-100 to 100 inclusive) - - + List of wearable inventory items to + be added to the outfit - + - This command is used to set the speaker volume while in the audio tuning - process. Once an acceptable speaker level is attained, the application must - issue a connector set speaker volume command to have that level be used while - on voice calls. + Remove a wearable from the current outfit and set appearance - the speaker volume (-100 to 100 inclusive) - - + Wearable to be removed from the outfit - + - This is used to initialize and stop the Connector as a whole. The Connector - Create call must be completed successfully before any other requests are made - (typically during application initialization). The shutdown should be called - when the application is shutting down to gracefully release resources + Removes a list of wearables from the current outfit and set appearance - A string value indicting the Application name - URL for the management server - LoggingSettings - - - - + List of wearable inventory items to + be removed from the outfit - + - Shutdown Connector -- Should be called when the application is shutting down - to gracefully release resources + Replace the current outfit with a list of wearables and set appearance - Handle returned from successful Connector �create� request + List of wearable inventory items that + define a new outfit - + - Mute or unmute the microphone + Checks if an inventory item is currently being worn - Handle returned from successful Connector �create� request - true (mute) or false (unmute) + The inventory item to check against the agent + wearables + The WearableType slot that the item is being worn in, + or WearbleType.Invalid if it is not currently being worn - + - Mute or unmute the speaker + Returns a copy of the agents currently worn wearables - Handle returned from successful Connector �create� request - true (mute) or false (unmute) + A copy of the agents currently worn wearables + Avoid calling this function multiple times as it will make + a copy of all of the wearable data each time - + - Set microphone volume + Calls either or + depending on the value of + replaceItems - Handle returned from successful Connector �create� request - The level of the audio, a number between -100 and 100 where - 0 represents �normal� speaking volume + List of wearable inventory items to add + to the outfit or become a new outfit + True to replace existing items with the + new list of items, false to add these items to the existing outfit - + - Set local speaker volume + Adds a list of attachments to our agent - Handle returned from successful Connector �create� request - The level of the audio, a number between -100 and 100 where - 0 represents �normal� speaking volume + A List containing the attachments to add + If true, tells simulator to remove existing attachment + first - + - Start up the Voice service. + Attach an item to our agent at a specific attach point + A to attach + the on the avatar + to attach the item to - - - Handle miscellaneous request status - - - - - - ///If something goes wrong, we log it. - + - Cleanup oject resources + Attach an item to our agent specifying attachment details + The of the item to attach + The attachments owner + The name of the attachment + The description of the attahment + The to apply when attached + The of the attachment + The on the agent + to attach the item to - + - Request voice cap when changing regions + Detach an item from our agent using an object + An object - + - Handle a change in session state + Detach an item from our agent + The inventory itemID of the item to detach - + - Close a voice session + Inform the sim which wearables are part of our current outfit - - - + - Locate a Session context from its handle + Replaces the Wearables collection with a list of new wearable items - Creates the session context if it does not exist. + Wearable items to replace the Wearables collection with - + - Handle completion of main voice cap request. + Calculates base color/tint for a specific wearable + based on its params - - - - - - + All the color info gathered from wearable's VisualParams + passed as list of ColorParamInfo tuples + Base color/tint for the wearable - + - Daemon has started so connect to it. + Blocking method to populate the Wearables dictionary + True on success, otherwise false - + - The daemon TCP connection is open. + Blocking method to populate the Textures array with cached bakes + True on success, otherwise false - + - Handle creation of the Connector. + Populates textures and visual params from a decoded asset + Wearable to decode - + - Handle response to audio output device query + Blocking method to download and parse currently worn wearable assets + True on success, otherwise false - + - Handle response to audio input device query + Get a list of all of the textures that need to be downloaded for a + single bake layer + Bake layer to get texture AssetIDs for + A list of texture AssetIDs to download - + - Set voice channel for new parcel + Helper method to lookup the TextureID for a single layer and add it + to a list if it is not already present + + - + - Request info from a parcel capability Uri. + Blocking method to download all of the textures needed for baking + the given bake layers - - + A list of layers that need baking + No return value is given because the baking will happen + whether or not all textures are successfully downloaded - + - Receive parcel voice cap + Blocking method to create and upload baked textures for all of the + missing bakes - - - - - - + True on success, otherwise false - + - Tell Vivox where we are standing + Blocking method to create and upload a baked texture for a single + bake layer - This has to be called when we move or turn. + Layer to bake + True on success, otherwise false - + - Start and stop updating out position. + Blocking method to upload a baked texture - - + Five channel JPEG2000 texture data to upload + UUID of the newly created asset on success, otherwise UUID.Zero - + - Starts a thread that keeps the daemon running + Creates a dictionary of visual param values from the downloaded wearables - - - - + A dictionary of visual param indices mapping to visual param + values for our agent that can be fed to the Baker class - + - Stops the daemon and the thread keeping it running + Create an AgentSetAppearance packet from Wearables data and the + Textures array and send it - + + Converts a WearableType to a bodypart or clothing WearableType - - - - - - + A WearableType + AssetType.Bodypart or AssetType.Clothing or AssetType.Unknown - + - Create a Session - Sessions typically represent a connection to a media session with one or more - participants. This is used to generate an �outbound� call to another user or - channel. The specifics depend on the media types involved. A session handle is - required to control the local user functions within the session (or remote - users if the current account has rights to do so). Currently creating a - session automatically connects to the audio media, there is no need to call - Session.Connect at this time, this is reserved for future use. + Converts a BakeType to the corresponding baked texture slot in AvatarTextureIndex - Handle returned from successful Connector �create� request - This is the URI of the terminating point of the session (ie who/what is being called) - This is the display name of the entity being called (user or channel) - Only needs to be supplied when the target URI is password protected - This indicates the format of the password as passed in. This can either be - �ClearText� or �SHA1UserName�. If this element does not exist, it is assumed to be �ClearText�. If it is - �SHA1UserName�, the password as passed in is the SHA1 hash of the password and username concatenated together, - then base64 encoded, with the final �=� character stripped off. - - - - - - + A BakeType + The AvatarTextureIndex slot that holds the given BakeType - + - Used to accept a call + Gives the layer number that is used for morph mask - SessionHandle such as received from SessionNewEvent - "default" - - + >A BakeType + Which layer number as defined in BakeTypeToTextures is used for morph mask - + - This command is used to start the audio render process, which will then play - the passed in file through the selected audio render device. This command - should not be issued if the user is on a call. + Converts a BakeType to a list of the texture slots that make up that bake - The fully qualified path to the sound file. - True if the file is to be played continuously and false if it is should be played once. - - + A BakeType + A list of texture slots that are inputs for the given bake - + + Triggered when an AgentWearablesUpdate packet is received, + telling us what our avatar is currently wearing + request. + + + Raised when an AgentCachedTextureResponse packet is + received, giving a list of cached bakes that were found on the + simulator + request. + + - This command is used to stop the audio render process. + Raised when appearance data is sent to the simulator, also indicates + the main appearance thread is finished. - The fully qualified path to the sound file issued in the start render command. - - + request. - + - This is used to �end� an established session (i.e. hang-up or disconnect). + Triggered when the simulator requests the agent rebake its appearance. - Handle returned from successful Session �create� request or a SessionNewEvent - - + - + - Set the combined speaking and listening position in 3D space. + Returns true if AppearanceManager is busy and trying to set or change appearance will fail - Handle returned from successful Session �create� request or a SessionNewEvent - Speaking position - Listening position - - - + - Set User Volume for a particular user. Does not affect how other users hear that user. + Contains information about a wearable inventory item - Handle returned from successful Session �create� request or a SessionNewEvent - - - The level of the audio, a number between -100 and 100 where 0 represents �normal� speaking volume - - - - Positional vector of the users position + + Inventory ItemID of the wearable - - Velocity vector of the position + + AssetID of the wearable asset - - At Orientation (X axis) of the position + + WearableType of the wearable - - Up Orientation (Y axis) of the position + + AssetType of the wearable - - Left Orientation (Z axis) of the position + + Asset data for the wearable - + - Extract the avatar UUID encoded in a SIP URI + Data collected from visual params for each wearable + needed for the calculation of the color - - - - - + - Represents a single Voice Session to the Vivox service. + Holds a texture assetID and the data needed to bake this layer into + an outfit texture. Used to keep track of currently worn textures + and baking data - - - Close this session. - + + A texture AssetID - - - Look up an existing Participants in this session - - - - - + + Asset data for the texture - + + Collection of alpha masks that needs applying + + + Tint that should be applied to the texture + + + Contains the Event data returned from the data server from an AgentWearablesRequest + + + Construct a new instance of the AgentWearablesReplyEventArgs class + + + Contains the Event data returned from the data server from an AgentCachedTextureResponse + + + Construct a new instance of the AgentCachedBakesReplyEventArgs class + + + Contains the Event data returned from an AppearanceSetRequest + + - - - - - + Triggered when appearance data is sent to the sim and + the main appearance thread is done. + Indicates whether appearance setting was successful - + + Indicates whether appearance setting was successful + + + Contains the Event data returned from the data server from an RebakeAvatarTextures + + - A callback fired to indicate the status or final state of the requested texture. For progressive - downloads this will fire each time new asset data is returned from the simulator. + Triggered when the simulator sends a request for this agent to rebake + its appearance - The indicating either Progress for textures not fully downloaded, - or the final result of the request after it has been processed through the TexturePipeline - The object containing the Assets ID, raw data - and other information. For progressive rendering the will contain - the data from the beginning of the file. For failed, aborted and timed out requests it will contain - an empty byte array. + The ID of the Texture Layer to bake + + + The ID of the Texture Layer to bake diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index b9c73b7..8f02186 100644 Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ diff --git a/bin/OpenMetaverse.dll.config b/bin/OpenMetaverse.dll.config index dc36a45..13fdc11 100644 --- a/bin/OpenMetaverse.dll.config +++ b/bin/OpenMetaverse.dll.config @@ -1,7 +1,7 @@ - - - - - - - + + + + + + + diff --git a/bin/OpenMetaverseTypes.XML b/bin/OpenMetaverseTypes.XML index 69e5c1b..9b19851 100644 --- a/bin/OpenMetaverseTypes.XML +++ b/bin/OpenMetaverseTypes.XML @@ -1,239 +1,23 @@ - /home/root/libopenmetaverse/bin/OpenMetaverseTypes + OpenMetaverseTypes - - - Same as Queue except Dequeue function blocks until there is an object to return. - Note: This class does not need to be synchronized - - - - - Create new BlockingQueue. - - The System.Collections.ICollection to copy elements from - - - - Create new BlockingQueue. - - The initial number of elements that the queue can contain - - - - Create new BlockingQueue. - - - - - Gets flag indicating if queue has been closed. - - - - - BlockingQueue Destructor (Close queue, resume any waiting thread). - - - - - Remove all objects from the Queue. - - - - - Remove all objects from the Queue, resume all dequeue threads. - - - - - Removes and returns the object at the beginning of the Queue. - - Object in queue. - - - - Removes and returns the object at the beginning of the Queue. - - time to wait before returning - Object in queue. - - - - Removes and returns the object at the beginning of the Queue. - - time to wait before returning (in milliseconds) - Object in queue. - - - - Adds an object to the end of the Queue - - Object to put in queue - - - - Open Queue. - - - - - Copy constructor - - Circular queue to copy - - - - An 8-bit color structure including an alpha channel - - - - - - - - - - - - - - - - - Builds a color from a byte array - - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - - - - Returns the raw bytes for this vector - - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - True if the alpha value is inverted in - addition to whatever the inverted parameter is. Setting inverted true - and alphaInverted true will flip the alpha value back to non-inverted, - but keep the other color bytes inverted - A 16 byte array containing R, G, B, and A - - - - Copy constructor - - Color to copy - - - Red - - - Green - - - Blue - - - Alpha - - - A Color4 with zero RGB values and fully opaque (alpha 1.0) - - - A Color4 with full RGB values (1.0) and fully opaque (alpha 1.0) - - - - IComparable.CompareTo implementation - - Sorting ends up like this: |--Grayscale--||--Color--|. - Alpha is only used when the colors are otherwise equivalent - - - - Builds a color from a byte array - - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - True if the alpha value is inverted in - addition to whatever the inverted parameter is. Setting inverted true - and alphaInverted true will flip the alpha value back to non-inverted, - but keep the other color bytes inverted - - - - Writes the raw bytes for this color to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array - - - - Serializes this color into four bytes in a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 4 bytes before the end of the array - True to invert the output (1.0 becomes 0 - instead of 255) - - - - Writes the raw bytes for this color to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array - - - - Ensures that values are in range 0-1 - - - - - Create an RGB color from a hue, saturation, value combination - - Hue - Saturation - Value - An fully opaque RGB color (alpha is 1.0) - - - - Performs linear interpolation between two colors - - Color to start at - Color to end at - Amount to interpolate - The interpolated color - Attribute class that allows extra attributes to be attached to ENUMs + + Text used when presenting ENUM to user + Default initializer Text used when presenting ENUM to user - - Text used when presenting ENUM to user - The different types of grid assets @@ -255,11 +39,11 @@ Link to a location in world - Collection of textures and parameters that can be + Collection of textures and parameters that can be worn by an avatar - Primitive that can contain textures, sounds, + Primitive that can contain textures, sounds, scripts and more @@ -367,42 +151,34 @@ Notecard - - + Folder - - + an LSL Script - - + - - + - - + - - + - - + - - + @@ -474,1830 +250,1734 @@ Invalid wearable asset - + - Identifier code for primitive types + Copy constructor + Circular queue to copy - - None - - - A Primitive + + X value - - A Avatar + + Y value - - Linden grass + + Z value - - Linden tree + + W value - - A primitive that acts as the source for a particle stream - - - A Linden tree - - + - Primary parameters for primitives such as Physics Enabled or Phantom + Build a quaternion from normalized float values + X value from -1.0 to 1.0 + Y value from -1.0 to 1.0 + Z value from -1.0 to 1.0 - - Deprecated - - - Whether physics are enabled for this object - - + + Constructor, builds a quaternion object from a byte array + Byte array containing four four-byte floats + Offset in the byte array to start reading at + Whether the source data is normalized or + not. If this is true 12 bytes will be read, otherwise 16 bytes will + be read. - + + Normalizes the quaternion - + + Builds a quaternion object from a byte array + The source byte array + Offset in the byte array to start reading at + Whether the source data is normalized or + not. If this is true 12 bytes will be read, otherwise 16 bytes will + be read. - + + Normalize this quaternion and serialize it to a byte array + A 12 byte array containing normalized X, Y, and Z floating + point values in order using little endian byte ordering - + + Writes the raw bytes for this quaternion to a byte array + Destination byte array + Position in the destination array to start + writing. Must be at least 12 bytes before the end of the array - + + Convert this quaternion to euler angles + X euler angle + Y euler angle + Z euler angle - - Whether this object contains an active touch script - - + + Convert this quaternion to an angle around an axis + Unit vector describing the axis + Angle around the axis, in radians - - Whether this object can receive payments - - - Whether this object is phantom (no collisions) - - + + Returns the conjugate (spatial inverse) of a quaternion - + + Build a quaternion from an axis and an angle of rotation around + that axis - + + Build a quaternion from an axis and an angle of rotation around + that axis + Axis of rotation + Angle of rotation - + + Creates a quaternion from a vector containing roll, pitch, and yaw + in radians + Vector representation of the euler angles in + radians + Quaternion representation of the euler angles - - Deprecated - - + + Creates a quaternion from roll, pitch, and yaw euler angles in + radians + X angle in radians + Y angle in radians + Z angle in radians + Quaternion representation of the euler angles - + + Conjugates and renormalizes a vector - + + Spherical linear interpolation between two quaternions - - Deprecated - - + + Get a string representation of the quaternion elements with up to three + decimal digits and separated by spaces only + Raw string representation of the quaternion - - - + + A quaternion with a value of 0,0,0,1 - + + A hierarchical token bucket for bandwidth throttling. See + http://en.wikipedia.org/wiki/Token_bucket for more information - - - + + Parent bucket to this bucket, or null if this is a root + bucket - - Server flag, will not be sent to clients. Specifies that - the object is destroyed when it touches a simulator edge + + Size of the bucket in bytes. If zero, the bucket has + infinite capacity - - Server flag, will not be sent to clients. Specifies that - the object will be returned to the owner's inventory when it - touches a simulator edge + + Rate that the bucket fills, in bytes per millisecond. If + zero, the bucket always remains full - - Server flag, will not be sent to clients. + + Number of tokens currently in the bucket - - Server flag, will not be sent to client. Specifies that - the object is hovering/flying + + Time of the last drip, in system ticks - + + Default constructor + Parent bucket if this is a child bucket, or + null if this is a root bucket + Maximum size of the bucket in bytes, or + zero if this bucket has no maximum capacity + Rate that the bucket fills, in bytes per + second. If zero, the bucket always remains full - + + Remove a given number of tokens from the bucket + Number of tokens to remove from the bucket + True if the requested number of tokens were removed from + the bucket, otherwise false - + + Remove a given number of tokens from the bucket + Number of tokens to remove from the bucket + True if tokens were added to the bucket + during this call, otherwise false + True if the requested number of tokens were removed from + the bucket, otherwise false - + + Add tokens to the bucket over time. The number of tokens added each + call depends on the length of time that has passed since the last + call to Drip + True if tokens were added to the bucket, otherwise false - + - Sound flags for sounds attached to primitives + The parent bucket of this bucket, or null if this bucket has no + parent. The parent bucket will limit the aggregate bandwidth of all + of its children buckets - + + Maximum burst rate in bytes per second. This is the maximum number + of tokens that can accumulate in the bucket at any one time - + + The speed limit of this bucket in bytes per second. This is the + number of tokens that are added to the bucket per second + Tokens are added to the bucket any time + is called, at the granularity of + the system tick interval (typically around 15-22ms) - + + The number of bytes that can be sent at this moment. This is the + current number of tokens in the bucket + If this bucket has a parent bucket that does not have + enough tokens for a request, will + return false regardless of the content of this bucket - + + Same as Queue except Dequeue function blocks until there is an object to return. + Note: This class does not need to be synchronized - + + Create new BlockingQueue. + The System.Collections.ICollection to copy elements from - + + Create new BlockingQueue. + The initial number of elements that the queue can contain - + + Create new BlockingQueue. - + - Material type for a primitive + BlockingQueue Destructor (Close queue, resume any waiting thread). - + + Remove all objects from the Queue. - + + Remove all objects from the Queue, resume all dequeue threads. - + + Removes and returns the object at the beginning of the Queue. + Object in queue. - + + Removes and returns the object at the beginning of the Queue. + time to wait before returning + Object in queue. - + + Removes and returns the object at the beginning of the Queue. + time to wait before returning (in milliseconds) + Object in queue. - + + Adds an object to the end of the Queue + Object to put in queue - + + Open Queue. - + + Gets flag indicating if queue has been closed. - + - Used in a helper function to roughly determine prim shape + Determines the appropriate events to set, leaves the locks, and sets the events. - + - Extra parameters for primitives, these flags are for features that have - been added after the original ObjectFlags that has all eight bits - reserved already + A routine for lazily creating a event outside the lock (so if errors + happen they are outside the lock and that we don't do much work + while holding a spin lock). If all goes well, reenter the lock and + set 'waitEvent' - - Whether this object has flexible parameters + + + Waits on 'waitEvent' with a timeout of 'millisceondsTimeout. + Before the wait 'numWaiters' is incremented and is restored before leaving this routine. + - - Whether this object has light parameters + + Used for converting degrees to radians - - Whether this object is a sculpted prim + + Used for converting radians to degrees - + + Convert the first two bytes starting in the byte array in + little endian ordering to a signed short integer + An array two bytes or longer + A signed short integer, will be zero if a short can't be + read at the given position - + + Convert the first two bytes starting at the given position in + little endian ordering to a signed short integer + An array two bytes or longer + Position in the array to start reading + A signed short integer, will be zero if a short can't be + read at the given position - + + Convert the first four bytes starting at the given position in + little endian ordering to a signed integer + An array four bytes or longer + Position to start reading the int from + A signed integer, will be zero if an int can't be read + at the given position - + + Convert the first four bytes of the given array in little endian + ordering to a signed integer + An array four bytes or longer + A signed integer, will be zero if the array contains + less than four bytes - + + Convert the first eight bytes of the given array in little endian + ordering to a signed long integer + An array eight bytes or longer + A signed long integer, will be zero if the array contains + less than eight bytes - + + Convert the first eight bytes starting at the given position in + little endian ordering to a signed long integer + An array eight bytes or longer + Position to start reading the long from + A signed long integer, will be zero if a long can't be read + at the given position - + + Convert the first two bytes starting at the given position in + little endian ordering to an unsigned short + Byte array containing the ushort + Position to start reading the ushort from + An unsigned short, will be zero if a ushort can't be read + at the given position - + + Convert two bytes in little endian ordering to an unsigned short + Byte array containing the ushort + An unsigned short, will be zero if a ushort can't be + read - + + Convert the first four bytes starting at the given position in + little endian ordering to an unsigned integer + Byte array containing the uint + Position to start reading the uint from + An unsigned integer, will be zero if a uint can't be read + at the given position - + + Convert the first four bytes of the given array in little endian + ordering to an unsigned integer + An array four bytes or longer + An unsigned integer, will be zero if the array contains + less than four bytes - + + Convert the first eight bytes of the given array in little endian + ordering to an unsigned 64-bit integer + An array eight bytes or longer + An unsigned 64-bit integer, will be zero if the array + contains less than eight bytes - + + Convert four bytes in little endian ordering to a floating point + value + Byte array containing a little ending floating + point value + Starting position of the floating point value in + the byte array + Single precision value - + + Convert an integer to a byte array in little endian format + The integer to convert + A four byte little endian array - + + Convert an integer to a byte array in big endian format + The integer to convert + A four byte big endian array - + + Convert a 64-bit integer to a byte array in little endian format + The value to convert + An 8 byte little endian array - + + Convert a 64-bit unsigned integer to a byte array in little endian + format + The value to convert + An 8 byte little endian array - + + Convert a floating point value to four bytes in little endian + ordering + A floating point value + A four byte array containing the value in little endian + ordering - + + Converts an unsigned integer to a hexadecimal string + An unsigned integer to convert to a string + A hexadecimal string 10 characters long + 0x7fffffff - + + Convert a variable length UTF8 byte array to a string + The UTF8 encoded byte array to convert + The decoded string - + + Converts a byte array to a string containing hexadecimal characters + The byte array to convert to a string + The name of the field to prepend to each + line of the string + A string containing hexadecimal characters on multiple + lines. Each line is prepended with the field name - + + Converts a byte array to a string containing hexadecimal characters + The byte array to convert to a string + Number of bytes in the array to parse + A string to prepend to each line of the hex + dump + A string containing hexadecimal characters on multiple + lines. Each line is prepended with the field name - + + Convert a string to a UTF8 encoded byte array + The string to convert + A null-terminated UTF8 byte array - + + Converts a string containing hexadecimal characters to a byte array + String containing hexadecimal characters + If true, gracefully handles null, empty and + uneven strings as well as stripping unconvertable characters + The converted byte array - + + Returns true is c is a hexadecimal digit (A-F, a-f, 0-9) + Character to test + true if hex digit, false if not - + + Converts 1 or 2 character string into equivalant byte value + 1 or 2 character string + byte - + + Convert a float value to a byte given a minimum and maximum range + Value to convert to a byte + Minimum value range + Maximum value range + A single byte representing the original float value - + + Convert a byte to a float value given a minimum and maximum range + Byte array to get the byte from + Position in the byte array the desired byte is at + Minimum value range + Maximum value range + A float value inclusively between lower and upper - + + Convert a byte to a float value given a minimum and maximum range + Byte to convert to a float value + Minimum value range + Maximum value range + A float value inclusively between lower and upper - + + Attempts to parse a floating point value from a string, using an + EN-US number format + String to parse + Resulting floating point number + True if the parse was successful, otherwise false - + + Attempts to parse a floating point value from a string, using an + EN-US number format + String to parse + Resulting floating point number + True if the parse was successful, otherwise false - + + Tries to parse an unsigned 32-bit integer from a hexadecimal string + String to parse + Resulting integer + True if the parse was successful, otherwise false - + - Attachment points for objects on avatar bodies + Returns text specified in EnumInfo attribute of the enumerator + To add the text use [EnumInfo(Text = "Some nice text here")] before declaration + of enum values - - Both InventoryObject and InventoryAttachment types can be attached - - - - Right hand if object was not previously attached + Enum value + Text representation of the enum - - Chest + + + Takes an AssetType and returns the string representation + + The source + The string version of the AssetType - - Skull + + + Translate a string name of an AssetType into the proper Type + + A string containing the AssetType name + The AssetType which matches the string name, or AssetType.Unknown if no match was found - - Left shoulder + + + Convert an InventoryType to a string + + The to convert + A string representation of the source - - Right shoulder - - - Left hand - - - Right hand - - - Left foot - - - Right foot - - - Spine - - - Pelvis - - - Mouth - - - Chin - - - Left ear - - - Right ear - - - Left eyeball - - - Right eyeball - - - Nose - - - Right upper arm - - - Right forearm - - - Left upper arm - - - Left forearm - - - Right hip - - - Right upper leg - - - Right lower leg - - - Left hip - - - Left upper leg - - - Left lower leg - - - Stomach - - - Left pectoral - - - Right pectoral - - - HUD Center position 2 - - - HUD Top-right - - - HUD Top - - - HUD Top-left - - - HUD Center - - - HUD Bottom-left - - - HUD Bottom - - - HUD Bottom-right - - + - Tree foliage types + Convert a string into a valid InventoryType + A string representation of the InventoryType to convert + A InventoryType object which matched the type - - Pine1 tree - - - Oak tree - - - Tropical Bush1 - - - Palm1 tree - - - Dogwood tree - - - Tropical Bush2 - - - Palm2 tree - - - Cypress1 tree - - - Cypress2 tree - - - Pine2 tree - - - Plumeria - - - Winter pinetree1 - - - Winter Aspen tree - - - Winter pinetree2 - - - Eucalyptus tree - - - Fern - - - Eelgrass + + + Convert a SaleType to a string + + The to convert + A string representation of the source - - Sea Sword + + + Convert a string into a valid SaleType + + A string representation of the SaleType to convert + A SaleType object which matched the type - - Kelp1 plant + + + Converts a string used in LLSD to AttachmentPoint type + + String representation of AttachmentPoint to convert + AttachmentPoint enum - - Beach grass + + + Copy a byte array + + Byte array to copy + A copy of the given byte array - - Kelp2 plant + + + Packs to 32-bit unsigned integers in to a 64-bit unsigned integer + + The left-hand (or X) value + The right-hand (or Y) value + A 64-bit integer containing the two 32-bit input values - + - Grass foliage types + Unpacks two 32-bit unsigned integers from a 64-bit unsigned integer + The 64-bit input integer + The left-hand (or X) output value + The right-hand (or Y) output value - + + Convert an IP address object to an unsigned 32-bit integer + IP address to convert + 32-bit unsigned integer holding the IP address bits - + + Gets a unix timestamp for the current time + An unsigned integer representing a unix timestamp for now - + + Convert a UNIX timestamp to a native DateTime object + An unsigned integer representing a UNIX + timestamp + A DateTime object containing the same time specified in + the given timestamp - + + Convert a UNIX timestamp to a native DateTime object + A signed integer representing a UNIX + timestamp + A DateTime object containing the same time specified in + the given timestamp - + + Convert a native DateTime object to a UNIX timestamp + A DateTime object you want to convert to a + timestamp + An unsigned integer representing a UNIX timestamp - + + Swap two values + Type of the values to swap + First value + Second value - + - Action associated with clicking on an object + Try to parse an enumeration value from a string + Enumeration type + String value to parse + Enumeration value on success + True if the parsing succeeded, otherwise false - - Touch object + + + Swaps the high and low words in a byte. Converts aaaabbbb to bbbbaaaa + + Byte to swap the words in + Byte value with the words swapped - - Sit on object - - - Purchase object or contents - - - Pay the object + + + Attempts to convert a string representation of a hostname or IP + address to a + + Hostname to convert to an IPAddress + Converted IP address object, or null if the conversion + failed - - Open task inventory + + Provide a single instance of the CultureInfo class to + help parsing in situations where the grid assumes an en-us + culture - - Play parcel media + + UNIX epoch in DateTime format - - Open parcel media + + Provide a single instance of the MD5 class to avoid making + duplicate copies and handle thread safety - - For thread safety + + Provide a single instance of the SHA-1 class to avoid + making duplicate copies and handle thread safety - - For thread safety + + Provide a single instance of a random number generator + to avoid making duplicate copies and handle thread safety - + - Purges expired objects from the cache. Called automatically by the purge timer. + Clamp a given value between a range + Value to clamp + Minimum allowable value + Maximum allowable value + A value inclusively between lower and upper - + - A thread-safe lockless queue that supports multiple readers and - multiple writers + Clamp a given value between a range + Value to clamp + Minimum allowable value + Maximum allowable value + A value inclusively between lower and upper - + - Constructor + Clamp a given value between a range + Value to clamp + Minimum allowable value + Maximum allowable value + A value inclusively between lower and upper - + - Provides a node container for data in a singly linked list + Round a floating-point value to the nearest integer + Floating point number to round + Integer - + - Constructor + Test if a single precision float is a finite number - + - Constructor + Test if a double precision float is a finite number - - Pointer to the next node in list - - - The data contained by the node - - - Queue head - - - Queue tail - - - Queue item count - - - Gets the current number of items in the queue. Since this - is a lockless collection this value should be treated as a close - estimate - - + - Enqueue an item + Get the distance between two floating-point values - Item to enqeue + First value + Second value + The distance between the two values - + - Try to dequeue an item + Compute the MD5 hash for a byte array - Dequeued item if the dequeue was successful - True if an item was successfully deqeued, otherwise false - - - A 4x4 matrix containing all zeroes - - - A 4x4 identity matrix + Byte array to compute the hash for + MD5 hash of the input data - + - Convert this matrix to euler rotations + Compute the SHA1 hash for a byte array - X euler angle - Y euler angle - Z euler angle + Byte array to compute the hash for + SHA1 hash of the input data - + - Convert this matrix to a quaternion rotation + Calculate the SHA1 hash of a given string - A quaternion representation of this rotation matrix + The string to hash + The SHA1 hash as a string - + - Construct a matrix from euler rotation values in radians + Compute the SHA256 hash for a byte array - X euler angle in radians - Y euler angle in radians - Z euler angle in radians + Byte array to compute the hash for + SHA256 hash of the input data - + - Get a formatted string representation of the vector + Calculate the SHA256 hash of a given string - A string representation of the vector + The string to hash + The SHA256 hash as a string - + - Provides helper methods for parallelizing loops + Calculate the MD5 hash of a given string + The password to hash + An MD5 hash in string format, with $1$ prepended - + - Executes a for loop in which iterations may run in parallel + Calculate the MD5 hash of a given string - The loop will be started at this index - The loop will be terminated before this index is reached - Method body to run for each iteration of the loop + The string to hash + The MD5 hash as a string - + - Executes a for loop in which iterations may run in parallel + Generate a random double precision floating point value - The number of concurrent execution threads to run - The loop will be started at this index - The loop will be terminated before this index is reached - Method body to run for each iteration of the loop + Random value of type double - + - Executes a foreach loop in which iterations may run in parallel + Get the current running platform - Object type that the collection wraps - An enumerable collection to iterate over - Method body to run for each object in the collection + Enumeration of the current platform we are running on - + - Executes a foreach loop in which iterations may run in parallel + Get the current running runtime - Object type that the collection wraps - The number of concurrent execution threads to run - An enumerable collection to iterate over - Method body to run for each object in the collection + Enumeration of the current runtime we are running on - + - Executes a series of tasks in parallel + Operating system - A series of method bodies to execute - - - Executes a series of tasks in parallel - - The number of concurrent execution threads to run - A series of method bodies to execute + + Unknown - - - Build a quaternion from normalized float values - - X value from -1.0 to 1.0 - Y value from -1.0 to 1.0 - Z value from -1.0 to 1.0 + + Microsoft Windows - - - Constructor, builds a quaternion object from a byte array - - Byte array containing four four-byte floats - Offset in the byte array to start reading at - Whether the source data is normalized or - not. If this is true 12 bytes will be read, otherwise 16 bytes will - be read. + + Microsoft Windows CE - - X value + + Linux - - Y value + + Apple OSX - - Z value + + + Runtime platform + - - W value + + .NET runtime - - A quaternion with a value of 0,0,0,1 + + Mono runtime: http://www.mono-project.com/ - + - Normalizes the quaternion + An 8-bit color structure including an alpha channel - - - Builds a quaternion object from a byte array - - The source byte array - Offset in the byte array to start reading at - Whether the source data is normalized or - not. If this is true 12 bytes will be read, otherwise 16 bytes will - be read. + + Red - + + Green + + + Blue + + + Alpha + + - Normalize this quaternion and serialize it to a byte array + - A 12 byte array containing normalized X, Y, and Z floating - point values in order using little endian byte ordering + + + + - + - Writes the raw bytes for this quaternion to a byte array + Builds a color from a byte array - Destination byte array - Position in the destination array to start - writing. Must be at least 12 bytes before the end of the array + Byte array containing a 16 byte color + Beginning position in the byte array + True if the byte array stores inverted values, + otherwise false. For example the color black (fully opaque) inverted + would be 0xFF 0xFF 0xFF 0x00 - + - Convert this quaternion to euler angles + Returns the raw bytes for this vector - X euler angle - Y euler angle - Z euler angle + Byte array containing a 16 byte color + Beginning position in the byte array + True if the byte array stores inverted values, + otherwise false. For example the color black (fully opaque) inverted + would be 0xFF 0xFF 0xFF 0x00 + True if the alpha value is inverted in + addition to whatever the inverted parameter is. Setting inverted true + and alphaInverted true will flip the alpha value back to non-inverted, + but keep the other color bytes inverted + A 16 byte array containing R, G, B, and A - + - Convert this quaternion to an angle around an axis + Copy constructor - Unit vector describing the axis - Angle around the axis, in radians + Color to copy - + - Returns the conjugate (spatial inverse) of a quaternion + IComparable.CompareTo implementation + Sorting ends up like this: |--Grayscale--||--Color--|. + Alpha is only used when the colors are otherwise equivalent - + - Build a quaternion from an axis and an angle of rotation around - that axis + Builds a color from a byte array + Byte array containing a 16 byte color + Beginning position in the byte array + True if the byte array stores inverted values, + otherwise false. For example the color black (fully opaque) inverted + would be 0xFF 0xFF 0xFF 0x00 + True if the alpha value is inverted in + addition to whatever the inverted parameter is. Setting inverted true + and alphaInverted true will flip the alpha value back to non-inverted, + but keep the other color bytes inverted - + - Build a quaternion from an axis and an angle of rotation around - that axis + Writes the raw bytes for this color to a byte array - Axis of rotation - Angle of rotation + Destination byte array + Position in the destination array to start + writing. Must be at least 16 bytes before the end of the array - + - Creates a quaternion from a vector containing roll, pitch, and yaw - in radians + Serializes this color into four bytes in a byte array - Vector representation of the euler angles in - radians - Quaternion representation of the euler angles + Destination byte array + Position in the destination array to start + writing. Must be at least 4 bytes before the end of the array + True to invert the output (1.0 becomes 0 + instead of 255) - + - Creates a quaternion from roll, pitch, and yaw euler angles in - radians + Writes the raw bytes for this color to a byte array - X angle in radians - Y angle in radians - Z angle in radians - Quaternion representation of the euler angles + Destination byte array + Position in the destination array to start + writing. Must be at least 16 bytes before the end of the array - + - Conjugates and renormalizes a vector + Ensures that values are in range 0-1 - + - Spherical linear interpolation between two quaternions + Create an RGB color from a hue, saturation, value combination + Hue + Saturation + Value + An fully opaque RGB color (alpha is 1.0) - + - Get a string representation of the quaternion elements with up to three - decimal digits and separated by spaces only + Performs linear interpolation between two colors - Raw string representation of the quaternion + Color to start at + Color to end at + Amount to interpolate + The interpolated color - + + A Color4 with zero RGB values and fully opaque (alpha 1.0) + + + A Color4 with full RGB values (1.0) and fully opaque (alpha 1.0) + + + For thread safety + + + For thread safety + + - Determines the appropriate events to set, leaves the locks, and sets the events. + Purges expired objects from the cache. Called automatically by the purge timer. - + - A routine for lazily creating a event outside the lock (so if errors - happen they are outside the lock and that we don't do much work - while holding a spin lock). If all goes well, reenter the lock and - set 'waitEvent' + Provides helper methods for parallelizing loops - + - Waits on 'waitEvent' with a timeout of 'millisceondsTimeout. - Before the wait 'numWaiters' is incremented and is restored before leaving this routine. + Executes a for loop in which iterations may run in parallel + The loop will be started at this index + The loop will be terminated before this index is reached + Method body to run for each iteration of the loop - + - A hierarchical token bucket for bandwidth throttling. See - http://en.wikipedia.org/wiki/Token_bucket for more information + Executes a for loop in which iterations may run in parallel + The number of concurrent execution threads to run + The loop will be started at this index + The loop will be terminated before this index is reached + Method body to run for each iteration of the loop - + - Default constructor + Executes a foreach loop in which iterations may run in parallel - Parent bucket if this is a child bucket, or - null if this is a root bucket - Maximum size of the bucket in bytes, or - zero if this bucket has no maximum capacity - Rate that the bucket fills, in bytes per - second. If zero, the bucket always remains full - - - Parent bucket to this bucket, or null if this is a root - bucket - - - Size of the bucket in bytes. If zero, the bucket has - infinite capacity - - - Rate that the bucket fills, in bytes per millisecond. If - zero, the bucket always remains full - - - Number of tokens currently in the bucket - - - Time of the last drip, in system ticks + Object type that the collection wraps + An enumerable collection to iterate over + Method body to run for each object in the collection - + - The parent bucket of this bucket, or null if this bucket has no - parent. The parent bucket will limit the aggregate bandwidth of all - of its children buckets + Executes a foreach loop in which iterations may run in parallel + Object type that the collection wraps + The number of concurrent execution threads to run + An enumerable collection to iterate over + Method body to run for each object in the collection - + - Maximum burst rate in bytes per second. This is the maximum number - of tokens that can accumulate in the bucket at any one time + Executes a series of tasks in parallel + A series of method bodies to execute - + - The speed limit of this bucket in bytes per second. This is the - number of tokens that are added to the bucket per second + Executes a series of tasks in parallel - Tokens are added to the bucket any time - is called, at the granularity of - the system tick interval (typically around 15-22ms) + The number of concurrent execution threads to run + A series of method bodies to execute - + - The number of bytes that can be sent at this moment. This is the - current number of tokens in the bucket - If this bucket has a parent bucket that does not have - enough tokens for a request, will - return false regardless of the content of this bucket + Convert this matrix to euler rotations + + X euler angle + Y euler angle + Z euler angle - + - Remove a given number of tokens from the bucket + Convert this matrix to a quaternion rotation - Number of tokens to remove from the bucket - True if the requested number of tokens were removed from - the bucket, otherwise false + A quaternion representation of this rotation matrix - + - Remove a given number of tokens from the bucket + Construct a matrix from euler rotation values in radians - Number of tokens to remove from the bucket - True if tokens were added to the bucket - during this call, otherwise false - True if the requested number of tokens were removed from - the bucket, otherwise false + X euler angle in radians + Y euler angle in radians + Z euler angle in radians - + - Add tokens to the bucket over time. The number of tokens added each - call depends on the length of time that has passed since the last - call to Drip + Get a formatted string representation of the vector - True if tokens were added to the bucket, otherwise false + A string representation of the vector - - - A 128-bit Universally Unique Identifier, used throughout the Second - Life networking protocol - + + A 4x4 matrix containing all zeroes - - - Constructor that takes a string UUID representation - - A string representation of a UUID, case - insensitive and can either be hyphenated or non-hyphenated - UUID("11f8aa9c-b071-4242-836b-13b7abe0d489") + + A 4x4 identity matrix - + - Constructor that takes a System.Guid object + Identifier code for primitive types - A Guid object that contains the unique identifier - to be represented by this UUID - - - Constructor that takes a byte array containing a UUID - - Byte array containing a 16 byte UUID - Beginning offset in the array + + None - - - Constructor that takes an unsigned 64-bit unsigned integer to - convert to a UUID - - 64-bit unsigned integer to convert to a UUID + + A Primitive - - - Copy constructor - - UUID to copy + + A Avatar - - The System.Guid object this struct wraps around + + Linden grass - - An UUID with a value of all zeroes + + Linden tree - - A cache of UUID.Zero as a string to optimize a common path + + A primitive that acts as the source for a particle stream - - - IComparable.CompareTo implementation - + + A Linden tree - + - Assigns this UUID from 16 bytes out of a byte array + Primary parameters for primitives such as Physics Enabled or Phantom - Byte array containing the UUID to assign this UUID to - Starting position of the UUID in the byte array - - - Returns a copy of the raw bytes for this UUID - - A 16 byte array containing this UUID + + Deprecated - - - Writes the raw bytes for this UUID to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array + + Whether physics are enabled for this object - - - Calculate an LLCRC (cyclic redundancy check) for this UUID - - The CRC checksum for this UUID + + - - - Create a 64-bit integer representation from the second half of this UUID - - An integer created from the last eight bytes of this UUID + + - - - Generate a UUID from a string - - A string representation of a UUID, case - insensitive and can either be hyphenated or non-hyphenated - UUID.Parse("11f8aa9c-b071-4242-836b-13b7abe0d489") + + - - - Generate a UUID from a string - - A string representation of a UUID, case - insensitive and can either be hyphenated or non-hyphenated - Will contain the parsed UUID if successful, - otherwise null - True if the string was successfully parse, otherwise false - UUID.TryParse("11f8aa9c-b071-4242-836b-13b7abe0d489", result) + + - - - Combine two UUIDs together by taking the MD5 hash of a byte array - containing both UUIDs - - First UUID to combine - Second UUID to combine - The UUID product of the combination + + - - - - - + + - - - Return a hash code for this UUID, used by .NET for hash tables - - An integer composed of all the UUID bytes XORed together + + Whether this object contains an active touch script - - - Comparison function - - An object to compare to this UUID - True if the object is a UUID and both UUIDs are equal + + - - - Comparison function - - UUID to compare to - True if the UUIDs are equal, otherwise false + + Whether this object can receive payments - - - Get a hyphenated string representation of this UUID - - A string representation of this UUID, lowercase and - with hyphens - 11f8aa9c-b071-4242-836b-13b7abe0d489 + + Whether this object is phantom (no collisions) - - - Equals operator - - First UUID for comparison - Second UUID for comparison - True if the UUIDs are byte for byte equal, otherwise false + + - - - Not equals operator - - First UUID for comparison - Second UUID for comparison - True if the UUIDs are not equal, otherwise true + + - - - XOR operator - - First UUID - Second UUID - A UUID that is a XOR combination of the two input UUIDs + + - - - String typecasting operator - - A UUID in string form. Case insensitive, - hyphenated or non-hyphenated - A UUID built from the string representation + + - - - Operating system - + + Deprecated - - Unknown + + - - Microsoft Windows + + - - Microsoft Windows CE + + - - Linux + + Deprecated - - Apple OSX + + - - - Runtime platform - + + - - .NET runtime + + - - Mono runtime: http://www.mono-project.com/ + + - - Used for converting degrees to radians + + Server flag, will not be sent to clients. Specifies that + the object is destroyed when it touches a simulator edge - - Used for converting radians to degrees + + Server flag, will not be sent to clients. Specifies that + the object will be returned to the owner's inventory when it + touches a simulator edge - - Provide a single instance of the CultureInfo class to - help parsing in situations where the grid assumes an en-us - culture + + Server flag, will not be sent to clients. - - UNIX epoch in DateTime format + + Server flag, will not be sent to client. Specifies that + the object is hovering/flying - - Provide a single instance of the MD5 class to avoid making - duplicate copies and handle thread safety + + - - Provide a single instance of the SHA-1 class to avoid - making duplicate copies and handle thread safety + + - - Provide a single instance of a random number generator - to avoid making duplicate copies and handle thread safety + + - - - Clamp a given value between a range - - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper + + - + - Clamp a given value between a range + Sound flags for sounds attached to primitives - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper - - - Clamp a given value between a range - - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper + + - - - Round a floating-point value to the nearest integer - - Floating point number to round - Integer + + - - - Test if a single precision float is a finite number - + + - - - Test if a double precision float is a finite number - + + - - - Get the distance between two floating-point values - - First value - Second value - The distance between the two values + + - - - Compute the MD5 hash for a byte array - - Byte array to compute the hash for - MD5 hash of the input data + + - - - Compute the SHA1 hash for a byte array - - Byte array to compute the hash for - SHA1 hash of the input data + + - + - Calculate the SHA1 hash of a given string + Material type for a primitive - The string to hash - The SHA1 hash as a string - - - Compute the SHA256 hash for a byte array - - Byte array to compute the hash for - SHA256 hash of the input data + + - - - Calculate the SHA256 hash of a given string - - The string to hash - The SHA256 hash as a string + + - - - Calculate the MD5 hash of a given string - - The password to hash - An MD5 hash in string format, with $1$ prepended + + - - - Calculate the MD5 hash of a given string - - The string to hash - The MD5 hash as a string + + - - - Generate a random double precision floating point value - - Random value of type double + + - - - Get the current running platform - - Enumeration of the current platform we are running on + + - - - Get the current running runtime - - Enumeration of the current runtime we are running on + + - - - Convert the first two bytes starting in the byte array in - little endian ordering to a signed short integer - - An array two bytes or longer - A signed short integer, will be zero if a short can't be - read at the given position + + - + - Convert the first two bytes starting at the given position in - little endian ordering to a signed short integer + Used in a helper function to roughly determine prim shape - An array two bytes or longer - Position in the array to start reading - A signed short integer, will be zero if a short can't be - read at the given position - + - Convert the first four bytes starting at the given position in - little endian ordering to a signed integer + Extra parameters for primitives, these flags are for features that have + been added after the original ObjectFlags that has all eight bits + reserved already - An array four bytes or longer - Position to start reading the int from - A signed integer, will be zero if an int can't be read - at the given position - - - Convert the first four bytes of the given array in little endian - ordering to a signed integer - - An array four bytes or longer - A signed integer, will be zero if the array contains - less than four bytes + + Whether this object has flexible parameters - - - Convert the first eight bytes of the given array in little endian - ordering to a signed long integer - - An array eight bytes or longer - A signed long integer, will be zero if the array contains - less than eight bytes + + Whether this object has light parameters - - - Convert the first eight bytes starting at the given position in - little endian ordering to a signed long integer - - An array eight bytes or longer - Position to start reading the long from - A signed long integer, will be zero if a long can't be read - at the given position + + Whether this object is a sculpted prim - + - Convert the first two bytes starting at the given position in - little endian ordering to an unsigned short + - Byte array containing the ushort - Position to start reading the ushort from - An unsigned short, will be zero if a ushort can't be read - at the given position - - - Convert two bytes in little endian ordering to an unsigned short - - Byte array containing the ushort - An unsigned short, will be zero if a ushort can't be - read + + - - - Convert the first four bytes starting at the given position in - little endian ordering to an unsigned integer - - Byte array containing the uint - Position to start reading the uint from - An unsigned integer, will be zero if a uint can't be read - at the given position + + - - - Convert the first four bytes of the given array in little endian - ordering to an unsigned integer - - An array four bytes or longer - An unsigned integer, will be zero if the array contains - less than four bytes + + - + - Convert the first eight bytes of the given array in little endian - ordering to an unsigned 64-bit integer + - An array eight bytes or longer - An unsigned 64-bit integer, will be zero if the array - contains less than eight bytes - - - Convert four bytes in little endian ordering to a floating point - value - - Byte array containing a little ending floating - point value - Starting position of the floating point value in - the byte array - Single precision value + + - - - Convert an integer to a byte array in little endian format - - The integer to convert - A four byte little endian array + + - - - Convert an integer to a byte array in big endian format - - The integer to convert - A four byte big endian array + + - - - Convert a 64-bit integer to a byte array in little endian format - - The value to convert - An 8 byte little endian array + + - - - Convert a 64-bit unsigned integer to a byte array in little endian - format - - The value to convert - An 8 byte little endian array + + - - - Convert a floating point value to four bytes in little endian - ordering - - A floating point value - A four byte array containing the value in little endian - ordering + + - - - Converts an unsigned integer to a hexadecimal string - - An unsigned integer to convert to a string - A hexadecimal string 10 characters long - 0x7fffffff + + - - - Convert a variable length UTF8 byte array to a string - - The UTF8 encoded byte array to convert - The decoded string + + - + - Converts a byte array to a string containing hexadecimal characters + - The byte array to convert to a string - The name of the field to prepend to each - line of the string - A string containing hexadecimal characters on multiple - lines. Each line is prepended with the field name - - - Converts a byte array to a string containing hexadecimal characters - - The byte array to convert to a string - Number of bytes in the array to parse - A string to prepend to each line of the hex - dump - A string containing hexadecimal characters on multiple - lines. Each line is prepended with the field name + + - - - Convert a string to a UTF8 encoded byte array - - The string to convert - A null-terminated UTF8 byte array + + - - - Converts a string containing hexadecimal characters to a byte array - - String containing hexadecimal characters - If true, gracefully handles null, empty and - uneven strings as well as stripping unconvertable characters - The converted byte array + + - + + + + + + + + + + + + + + + + + + + - Returns true is c is a hexadecimal digit (A-F, a-f, 0-9) + - Character to test - true if hex digit, false if not - - - Converts 1 or 2 character string into equivalant byte value - - 1 or 2 character string - byte + + + + + + + + + + + + + + + + + + + + + + + + Attachment points for objects on avatar bodies + + + Both InventoryObject and InventoryAttachment types can be attached + + + + Right hand if object was not previously attached + + + Chest + + + Skull + + + Left shoulder + + + Right shoulder + + + Left hand + + + Right hand + + + Left foot + + + Right foot + + + Spine + + + Pelvis + + + Mouth + + + Chin + + + Left ear + + + Right ear + + + Left eyeball + + + Right eyeball + + + Nose + + + Right upper arm + + + Right forearm + + + Left upper arm + + + Left forearm + + + Right hip + + + Right upper leg + + + Right lower leg + + + Left hip + + + Left upper leg + + + Left lower leg + + + Stomach + + + Left pectoral + + + Right pectoral + + + HUD Center position 2 + + + HUD Top-right + + + HUD Top + + + HUD Top-left + + + HUD Center + + + HUD Bottom-left + + + HUD Bottom + + + HUD Bottom-right - + - Convert a float value to a byte given a minimum and maximum range + Tree foliage types - Value to convert to a byte - Minimum value range - Maximum value range - A single byte representing the original float value - - - Convert a byte to a float value given a minimum and maximum range - - Byte array to get the byte from - Position in the byte array the desired byte is at - Minimum value range - Maximum value range - A float value inclusively between lower and upper + + Pine1 tree - - - Convert a byte to a float value given a minimum and maximum range - - Byte to convert to a float value - Minimum value range - Maximum value range - A float value inclusively between lower and upper + + Oak tree - - - Attempts to parse a floating point value from a string, using an - EN-US number format - - String to parse - Resulting floating point number - True if the parse was successful, otherwise false + + Tropical Bush1 - - - Attempts to parse a floating point value from a string, using an - EN-US number format - - String to parse - Resulting floating point number - True if the parse was successful, otherwise false + + Palm1 tree - - - Tries to parse an unsigned 32-bit integer from a hexadecimal string - - String to parse - Resulting integer - True if the parse was successful, otherwise false + + Dogwood tree - - - Returns text specified in EnumInfo attribute of the enumerator - To add the text use [EnumInfo(Text = "Some nice text here")] before declaration - of enum values - - Enum value - Text representation of the enum + + Tropical Bush2 - - - Takes an AssetType and returns the string representation - - The source - The string version of the AssetType + + Palm2 tree - - - Translate a string name of an AssetType into the proper Type - - A string containing the AssetType name - The AssetType which matches the string name, or AssetType.Unknown if no match was found + + Cypress1 tree - - - Convert an InventoryType to a string - - The to convert - A string representation of the source + + Cypress2 tree - - - Convert a string into a valid InventoryType - - A string representation of the InventoryType to convert - A InventoryType object which matched the type + + Pine2 tree - - - Convert a SaleType to a string - - The to convert - A string representation of the source + + Plumeria - - - Convert a string into a valid SaleType - - A string representation of the SaleType to convert - A SaleType object which matched the type + + Winter pinetree1 - - - Converts a string used in LLSD to AttachmentPoint type - - String representation of AttachmentPoint to convert - AttachmentPoint enum + + Winter Aspen tree - - - Copy a byte array - - Byte array to copy - A copy of the given byte array + + Winter pinetree2 - - - Packs to 32-bit unsigned integers in to a 64-bit unsigned integer - - The left-hand (or X) value - The right-hand (or Y) value - A 64-bit integer containing the two 32-bit input values + + Eucalyptus tree - - - Unpacks two 32-bit unsigned integers from a 64-bit unsigned integer - - The 64-bit input integer - The left-hand (or X) output value - The right-hand (or Y) output value + + Fern - - - Convert an IP address object to an unsigned 32-bit integer - - IP address to convert - 32-bit unsigned integer holding the IP address bits + + Eelgrass - - - Gets a unix timestamp for the current time - - An unsigned integer representing a unix timestamp for now + + Sea Sword - - - Convert a UNIX timestamp to a native DateTime object - - An unsigned integer representing a UNIX - timestamp - A DateTime object containing the same time specified in - the given timestamp + + Kelp1 plant - - - Convert a UNIX timestamp to a native DateTime object - - A signed integer representing a UNIX - timestamp - A DateTime object containing the same time specified in - the given timestamp + + Beach grass - - - Convert a native DateTime object to a UNIX timestamp - - A DateTime object you want to convert to a - timestamp - An unsigned integer representing a UNIX timestamp + + Kelp2 plant - + - Swap two values + Grass foliage types - Type of the values to swap - First value - Second value - - - Try to parse an enumeration value from a string - - Enumeration type - String value to parse - Enumeration value on success - True if the parsing succeeded, otherwise false + + - - - Swaps the high and low words in a byte. Converts aaaabbbb to bbbbaaaa - - Byte to swap the words in - Byte value with the words swapped + + - - - Attempts to convert a string representation of a hostname or IP - address to a - Hostname to convert to an IPAddress - Converted IP address object, or null if the conversion - failed + + - + + + + + + + + + + - A two-dimensional vector with floating-point values + Action associated with clicking on an object - + + Touch object + + + Sit on object + + + Purchase object or contents + + + Pay the object + + + Open task inventory + + + Play parcel media + + + Open parcel media + + X value - + Y value - - A vector with a value of 0,0 - - - A vector with a value of 1,1 + + Z value - - A vector with a value of 1,0 + + W value - - A vector with a value of 0,1 + + + Constructor, builds a vector from a byte array + + Byte array containing four four-byte floats + Beginning position in the byte array - + Test if this vector is equal to another vector, within a given tolerance range @@ -2308,74 +1988,67 @@ True if the magnitude of difference between the two vectors is less than the given tolerance, otherwise false - + - Test if this vector is composed of all finite numbers + IComparable.CompareTo implementation - + - IComparable.CompareTo implementation + Test if this vector is composed of all finite numbers - + Builds a vector from a byte array - Byte array containing two four-byte floats + Byte array containing a 16 byte vector Beginning position in the byte array - + Returns the raw bytes for this vector - An eight-byte array containing X and Y + A 16 byte array containing X, Y, Z, and W - + Writes the raw bytes for this vector to a byte array Destination byte array Position in the destination array to start - writing. Must be at least 8 bytes before the end of the array - - - - Parse a vector from a string - - A string representation of a 2D vector, enclosed - in arrow brackets and separated by commas - - - - Interpolates between two vectors using a cubic equation - - - - - Get a formatted string representation of the vector - - A string representation of the vector + writing. Must be at least 16 bytes before the end of the array - + Get a string representation of the vector elements with up to three decimal digits and separated by spaces only Raw string representation of the vector + + A vector with a value of 0,0,0,0 + + + A vector with a value of 1,1,1,1 + + + A vector with a value of 1,0,0,0 + + + A vector with a value of 0,1,0,0 + + + A vector with a value of 0,0,1,0 + + + A vector with a value of 0,0,0,1 + A three-dimensional vector with floating-point values - - - Constructor, builds a vector from a byte array - - Byte array containing three four-byte floats - Beginning position in the byte array - X value @@ -2385,20 +2058,12 @@ Z value - - A vector with a value of 0,0,0 - - - A vector with a value of 1,1,1 - - - A unit vector facing forward (X axis), value 1,0,0 - - - A unit vector facing left (Y axis), value 0,1,0 - - - A unit vector facing up (Z axis), value 0,0,1 + + + Constructor, builds a vector from a byte array + + Byte array containing three four-byte floats + Beginning position in the byte array @@ -2446,7 +2111,7 @@ Parse a vector from a string - A string representation of a 3D vector, enclosed + A string representation of a 3D vector, enclosed in arrow brackets and separated by commas @@ -2479,11 +2144,94 @@ Cross product between two vectors + + A vector with a value of 0,0,0 + + + A vector with a value of 1,1,1 + + + A unit vector facing forward (X axis), value 1,0,0 + + + A unit vector facing left (Y axis), value 0,1,0 + + + A unit vector facing up (Z axis), value 0,0,1 + + + + A thread-safe lockless queue that supports multiple readers and + multiple writers + + + + Queue head + + + Queue tail + + + Queue item count + + + + Constructor + + + + + Enqueue an item + + Item to enqeue + + + + Try to dequeue an item + + Dequeued item if the dequeue was successful + True if an item was successfully deqeued, otherwise false + + + Gets the current number of items in the queue. Since this + is a lockless collection this value should be treated as a close + estimate + + + + Provides a node container for data in a singly linked list + + + + Pointer to the next node in list + + + The data contained by the node + + + + Constructor + + + + + Constructor + + A three-dimensional vector with doubleing-point values + + X value + + + Y value + + + Z value + Constructor, builds a vector from a byte array @@ -2491,14 +2239,77 @@ Byte array containing three eight-byte doubles Beginning position in the byte array - - X value + + + Test if this vector is equal to another vector, within a given + tolerance range + + Vector to test against + The acceptable magnitude of difference + between the two vectors + True if the magnitude of difference between the two vectors + is less than the given tolerance, otherwise false - - Y value + + + IComparable.CompareTo implementation + + + + + Test if this vector is composed of all finite numbers + + + + + Builds a vector from a byte array + + Byte array containing a 24 byte vector + Beginning position in the byte array + + + + Returns the raw bytes for this vector + + A 24 byte array containing X, Y, and Z + + + + Writes the raw bytes for this vector to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 24 bytes before the end of the array + + + + Parse a vector from a string + + A string representation of a 3D vector, enclosed + in arrow brackets and separated by commas + + + + Interpolates between two vectors using a cubic equation + + + + + Get a formatted string representation of the vector + + A string representation of the vector + + + + Get a string representation of the vector elements with up to three + decimal digits and separated by spaces only + + Raw string representation of the vector - - Z value + + + Cross product between two vectors + A vector with a value of 0,0,0 @@ -2515,7 +2326,18 @@ A unit vector facing up (Z axis), value of 0,0,1 - + + + A two-dimensional vector with floating-point values + + + + X value + + + Y value + + Test if this vector is equal to another vector, within a given tolerance range @@ -2526,152 +2348,255 @@ True if the magnitude of difference between the two vectors is less than the given tolerance, otherwise false - + - IComparable.CompareTo implementation + Test if this vector is composed of all finite numbers - + - Test if this vector is composed of all finite numbers + IComparable.CompareTo implementation - + Builds a vector from a byte array - Byte array containing a 24 byte vector + Byte array containing two four-byte floats Beginning position in the byte array - + Returns the raw bytes for this vector - A 24 byte array containing X, Y, and Z + An eight-byte array containing X and Y - + Writes the raw bytes for this vector to a byte array Destination byte array Position in the destination array to start - writing. Must be at least 24 bytes before the end of the array + writing. Must be at least 8 bytes before the end of the array - + Parse a vector from a string - A string representation of a 3D vector, enclosed + A string representation of a 2D vector, enclosed in arrow brackets and separated by commas - + Interpolates between two vectors using a cubic equation - + Get a formatted string representation of the vector A string representation of the vector - + Get a string representation of the vector elements with up to three decimal digits and separated by spaces only Raw string representation of the vector - + + A vector with a value of 0,0 + + + A vector with a value of 1,1 + + + A vector with a value of 1,0 + + + A vector with a value of 0,1 + + - Cross product between two vectors + A 128-bit Universally Unique Identifier, used throughout the Second + Life networking protocol - + + The System.Guid object this struct wraps around + + - Constructor, builds a vector from a byte array + Constructor that takes a string UUID representation - Byte array containing four four-byte floats - Beginning position in the byte array + A string representation of a UUID, case + insensitive and can either be hyphenated or non-hyphenated + UUID("11f8aa9c-b071-4242-836b-13b7abe0d489") - - X value + + + Constructor that takes a System.Guid object + + A Guid object that contains the unique identifier + to be represented by this UUID - - Y value + + + Constructor that takes a byte array containing a UUID + + Byte array containing a 16 byte UUID + Beginning offset in the array - - Z value + + + Constructor that takes an unsigned 64-bit unsigned integer to + convert to a UUID + + 64-bit unsigned integer to convert to a UUID - - W value + + + Copy constructor + + UUID to copy - - A vector with a value of 0,0,0,0 + + + IComparable.CompareTo implementation + - - A vector with a value of 1,1,1,1 + + + Assigns this UUID from 16 bytes out of a byte array + + Byte array containing the UUID to assign this UUID to + Starting position of the UUID in the byte array - - A vector with a value of 1,0,0,0 + + + Returns a copy of the raw bytes for this UUID + + A 16 byte array containing this UUID - - A vector with a value of 0,1,0,0 + + + Writes the raw bytes for this UUID to a byte array + + Destination byte array + Position in the destination array to start + writing. Must be at least 16 bytes before the end of the array - - A vector with a value of 0,0,1,0 + + + Calculate an LLCRC (cyclic redundancy check) for this UUID + + The CRC checksum for this UUID - - A vector with a value of 0,0,0,1 + + + Create a 64-bit integer representation from the second half of this UUID + + An integer created from the last eight bytes of this UUID - + - Test if this vector is equal to another vector, within a given - tolerance range + Generate a UUID from a string - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false + A string representation of a UUID, case + insensitive and can either be hyphenated or non-hyphenated + UUID.Parse("11f8aa9c-b071-4242-836b-13b7abe0d489") - + - IComparable.CompareTo implementation + Generate a UUID from a string + A string representation of a UUID, case + insensitive and can either be hyphenated or non-hyphenated + Will contain the parsed UUID if successful, + otherwise null + True if the string was successfully parse, otherwise false + UUID.TryParse("11f8aa9c-b071-4242-836b-13b7abe0d489", result) - + - Test if this vector is composed of all finite numbers + Combine two UUIDs together by taking the MD5 hash of a byte array + containing both UUIDs + First UUID to combine + Second UUID to combine + The UUID product of the combination - + - Builds a vector from a byte array + - Byte array containing a 16 byte vector - Beginning position in the byte array + - + - Returns the raw bytes for this vector + Return a hash code for this UUID, used by .NET for hash tables - A 16 byte array containing X, Y, Z, and W + An integer composed of all the UUID bytes XORed together - + - Writes the raw bytes for this vector to a byte array + Comparison function - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array + An object to compare to this UUID + True if the object is a UUID and both UUIDs are equal - + - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only + Comparison function - Raw string representation of the vector + UUID to compare to + True if the UUIDs are equal, otherwise false + + + + Get a hyphenated string representation of this UUID + + A string representation of this UUID, lowercase and + with hyphens + 11f8aa9c-b071-4242-836b-13b7abe0d489 + + + + Equals operator + + First UUID for comparison + Second UUID for comparison + True if the UUIDs are byte for byte equal, otherwise false + + + + Not equals operator + + First UUID for comparison + Second UUID for comparison + True if the UUIDs are not equal, otherwise true + + + + XOR operator + + First UUID + Second UUID + A UUID that is a XOR combination of the two input UUIDs + + + + String typecasting operator + + A UUID in string form. Case insensitive, + hyphenated or non-hyphenated + A UUID built from the string representation + + + An UUID with a value of all zeroes + + + A cache of UUID.Zero as a string to optimize a common path diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index b989bad..7ebf45e 100644 Binary files a/bin/OpenMetaverseTypes.dll and b/bin/OpenMetaverseTypes.dll differ -- cgit v1.1 From e55e93c994befde561c467b40768a21dcf72892e Mon Sep 17 00:00:00 2001 From: Latif Khalifa Date: Mon, 4 Oct 2010 07:37:22 +0200 Subject: Avoid throwing errors when adding existing meshes to the render scene --- OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs index a99b20c..49b4364 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs @@ -352,6 +352,12 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap Face face = renderMesh.Faces[i]; string meshName = primID + "-Face-" + i.ToString(); + // Avoid adding duplicate meshes to the scene + if (renderer.Scene.objectData.ContainsKey(meshName)) + { + continue; + } + warp_Object faceObj = new warp_Object(face.Vertices.Count, face.Indices.Count / 3); for (int j = 0; j < face.Vertices.Count; j++) -- cgit v1.1 From 1a47ec082ed541a3af0b7e8bb7d18f564f64335d Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 6 Oct 2010 05:15:47 +0200 Subject: Convert worldview to GET --- .../World/WorldView/WorldViewRequestHandler.cs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs index 5e744bf..bfdcdb4 100644 --- a/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs +++ b/OpenSim/Region/OptionalModules/World/WorldView/WorldViewRequestHandler.cs @@ -50,7 +50,7 @@ namespace OpenSim.Region.OptionalModules.World.WorldView protected Object m_RequestLock = new Object(); public WorldViewRequestHandler(WorldViewModule fmodule, string rid) - : base("POST", "/worldview/" + rid) + : base("GET", "/worldview/" + rid) { m_WorldViewModule = fmodule; } @@ -58,24 +58,28 @@ namespace OpenSim.Region.OptionalModules.World.WorldView public override byte[] Handle(string path, Stream requestData, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); - body = body.Trim(); + httpResponse.ContentType = "image/jpeg"; + +// StreamReader sr = new StreamReader(requestData); +// string body = sr.ReadToEnd(); +// sr.Close(); +// body = body.Trim(); try { lock (m_RequestLock) { Dictionary request = - ServerUtils.ParseQueryString(body); + new Dictionary(); + foreach (string name in httpRequest.QueryString) + request[name] = httpRequest.QueryString[name]; return SendWorldView(request); } } catch (Exception e) { - m_log.Debug("[WORLDVIEW]: Exception {0}" + e.ToString()); + m_log.Debug("[WORLDVIEW]: Exception: " + e.ToString()); } return new Byte[0]; -- cgit v1.1 From 42f76773a15d83fd31f249cc4a21985184b0cdbf Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 6 Oct 2010 19:59:30 +0200 Subject: Plumb the path for multiple object deletes --- .../InventoryAccess/InventoryAccessModule.cs | 31 ++++++++++++--- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 44 +++++----------------- OpenSim/Region/Framework/Scenes/Scene.cs | 4 +- .../Region/Framework/Scenes/SceneObjectGroup.cs | 8 +++- .../Scenes/Tests/SceneObjectBasicTests.cs | 2 +- OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs | 2 +- 6 files changed, 45 insertions(+), 46 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 42e3359..9ccf5a0 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -196,13 +196,24 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // currently calls this with multiple items. UUID ret = UUID.Zero; + Dictionary> deletes = + new Dictionary>(); + foreach (SceneObjectGroup g in objectGroups) - ret = DeleteToInventory(action, folderID, g, remoteClient); + { + if (!deletes.ContainsKey(g.OwnerID)) + deletes[g.OwnerID] = new List(); + + deletes[g.OwnerID].Add(g); + } + + foreach (List objlist in deletes.Values) + ret = DeleteToInventory(action, folderID, objlist, remoteClient); return ret; } - public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, + private UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) { UUID assetID = UUID.Zero; @@ -320,10 +331,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } else { - // Catch all. Use lost & found - // + if (remoteClient == null || + objectGroup.OwnerID != remoteClient.AgentId) + { + // Taking copy of another person's item. Take to + // Objects folder. + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); + } + else + { + // Catch all. Use lost & found + // - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); + } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 9a33993..8b5316a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1688,37 +1688,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Called when one or more objects are removed from the environment into inventory. - /// - /// - /// - /// - /// - /// - public virtual void DeRezObject(IClientAPI remoteClient, List localIDs, - UUID groupID, DeRezAction action, UUID destinationID) - { - foreach (uint localID in localIDs) - { - DeRezObject(remoteClient, localID, groupID, action, destinationID); - } - } - - /// - /// Called when an object is removed from the environment into inventory. - /// - /// - /// - /// - /// - /// - public virtual void DeRezObject(IClientAPI remoteClient, uint localID, - UUID groupID, DeRezAction action, UUID destinationID) - { - DeRezObjects(remoteClient, new List() { localID }, groupID, action, destinationID); - } - public virtual void DeRezObjects(IClientAPI remoteClient, List localIDs, UUID groupID, DeRezAction action, UUID destinationID) { @@ -2003,14 +1972,19 @@ namespace OpenSim.Region.Framework.Scenes return group; } - public virtual bool returnObjects(SceneObjectGroup[] returnobjects, UUID AgentId) + public virtual bool returnObjects(SceneObjectGroup[] returnobjects, + UUID AgentId) { + List localIDs = new List(); + foreach (SceneObjectGroup grp in returnobjects) { - AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return"); - DeRezObject(null, grp.RootPart.LocalId, - grp.RootPart.GroupID, DeRezAction.Return, UUID.Zero); + AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, + "parcel owner return"); + localIDs.Add(grp.RootPart.LocalId); } + DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, + UUID.Zero); return true; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e835281..bcc439c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2823,7 +2823,7 @@ namespace OpenSim.Region.Framework.Scenes client.OnGrabUpdate += m_sceneGraph.MoveObject; client.OnSpinStart += m_sceneGraph.SpinStart; client.OnSpinUpdate += m_sceneGraph.SpinObject; - client.OnDeRezObject += DeRezObject; + client.OnDeRezObject += DeRezObjects; client.OnObjectName += m_sceneGraph.PrimName; client.OnObjectClickAction += m_sceneGraph.PrimClickAction; @@ -2953,7 +2953,7 @@ namespace OpenSim.Region.Framework.Scenes client.OnGrabUpdate -= m_sceneGraph.MoveObject; client.OnSpinStart -= m_sceneGraph.SpinStart; client.OnSpinUpdate -= m_sceneGraph.SpinObject; - client.OnDeRezObject -= DeRezObject; + client.OnDeRezObject -= DeRezObjects; client.OnObjectName -= m_sceneGraph.PrimName; client.OnObjectClickAction -= m_sceneGraph.PrimClickAction; client.OnObjectMaterial -= m_sceneGraph.PrimMaterial; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a00a7c4..a6d89cf 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1569,6 +1569,8 @@ namespace OpenSim.Region.Framework.Scenes ILandObject parcel = m_scene.LandChannel.GetLandObject( m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); + List returns = new List(); + if (parcel != null && parcel.LandData != null && parcel.LandData.OtherCleanTime != 0) { @@ -1582,13 +1584,15 @@ namespace OpenSim.Region.Framework.Scenes DetachFromBackup(); m_log.InfoFormat("[SCENE]: Returning object {0} due to parcel auto return", RootPart.UUID.ToString()); m_scene.AddReturn(OwnerID, Name, AbsolutePosition, "parcel auto return"); - m_scene.DeRezObject(null, RootPart.LocalId, - RootPart.GroupID, DeRezAction.Return, UUID.Zero); + returns.Add(RootPart.LocalId); return; } } } + + m_scene.DeRezObjects(null, returns, UUID.Zero, + DeRezAction.Return, UUID.Zero); } if (HasGroupChanged) diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs index 5616a4e..4969b09 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs @@ -142,7 +142,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests SceneObjectPart part = SceneSetupHelpers.AddSceneObject(scene); IClientAPI client = SceneSetupHelpers.AddRootAgent(scene, agentId); - scene.DeRezObject(client, part.LocalId, UUID.Zero, DeRezAction.Delete, UUID.Zero); + scene.DeRezObjects(client, new System.Collections.Generic.List() { part.LocalId }, UUID.Zero, DeRezAction.Delete, UUID.Zero); SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); diff --git a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs index fc9db03..9d7733e 100644 --- a/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs +++ b/OpenSim/Tests/Common/Setup/SceneSetupHelpers.cs @@ -556,7 +556,7 @@ namespace OpenSim.Tests.Common.Setup AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; sogd.Enabled = false; - scene.DeRezObject(client, part.LocalId, UUID.Zero, action, destinationId); + scene.DeRezObjects(client, new List() { part.LocalId }, UUID.Zero, action, destinationId); sogd.InventoryDeQueueAndDelete(); } } -- cgit v1.1 From 2db0ac74c72f18d1bceb15b8a368777e42b366c0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 7 Oct 2010 01:13:17 +0200 Subject: Implement taking of coalesced objects. WARNING!!!!! You can TAKE them, but you can't REZ them again. Only the first of the contained objects will rez, the rest is inaccessible until rezzing them is implemented. Also, rotations are not explicitly stored. This MAY work. Or not. --- .../InventoryAccess/InventoryAccessModule.cs | 463 ++++++++++++--------- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 4 +- OpenSim/Region/Framework/Scenes/Scene.cs | 9 + .../Region/Framework/Scenes/SceneObjectGroup.cs | 7 +- 4 files changed, 276 insertions(+), 207 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 9ccf5a0..753aada 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -28,6 +28,7 @@ using System; using System.Collections.Generic; using System.Net; +using System.Xml; using System.Reflection; using System.Threading; @@ -191,11 +192,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, List objectGroups, IClientAPI remoteClient) { - // HACK: This is only working for lists containing a single item! - // It's just a hack to make this WIP compile and run. Nothing - // currently calls this with multiple items. UUID ret = UUID.Zero; + // The following code groups the SOG's by owner. No objects + // belonging to different people can be coalesced, for obvious + // reasons. Dictionary> deletes = new Dictionary>(); @@ -207,266 +208,328 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess deletes[g.OwnerID].Add(g); } - foreach (List objlist in deletes.Values) - ret = DeleteToInventory(action, folderID, objlist, remoteClient); + // This is pethod scoped and will be returned. It will be the + // last created asset id + UUID assetID = UUID.Zero; - return ret; - } + // Each iteration is really a separate asset being created, + // with distinct destinations as well. + foreach (List objlist in deletes.Values) + { + Dictionary xmlStrings = + new Dictionary(); - private UUID DeleteToInventory(DeRezAction action, UUID folderID, - SceneObjectGroup objectGroup, IClientAPI remoteClient) - { - UUID assetID = UUID.Zero; + foreach (SceneObjectGroup objectGroup in objlist) + { + Vector3 inventoryStoredPosition = new Vector3 + (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) + ? 250 + : objectGroup.AbsolutePosition.X) + , + (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) + ? 250 + : objectGroup.AbsolutePosition.X, + objectGroup.AbsolutePosition.Z); - Vector3 inventoryStoredPosition = new Vector3 - (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) - ? 250 - : objectGroup.AbsolutePosition.X) - , - (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize) - ? 250 - : objectGroup.AbsolutePosition.X, - objectGroup.AbsolutePosition.Z); + Vector3 originalPosition = objectGroup.AbsolutePosition; - Vector3 originalPosition = objectGroup.AbsolutePosition; + // Restore attachment data after trip through the sim + if (objectGroup.RootPart.AttachPoint > 0) + inventoryStoredPosition = objectGroup.RootPart.AttachOffset; + objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint; - // Restore attachment data after trip through the sim - if (objectGroup.RootPart.AttachPoint > 0) - inventoryStoredPosition = objectGroup.RootPart.AttachOffset; - objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint; + objectGroup.AbsolutePosition = inventoryStoredPosition; - objectGroup.AbsolutePosition = inventoryStoredPosition; + // Make sure all bits but the ones we want are clear + // on take. + // This will be applied to the current perms, so + // it will do what we want. + objectGroup.RootPart.NextOwnerMask &= + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify); + objectGroup.RootPart.NextOwnerMask |= + (uint)PermissionMask.Move; - string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup); + string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup); - objectGroup.AbsolutePosition = originalPosition; + objectGroup.AbsolutePosition = originalPosition; - // Get the user info of the item destination - // - UUID userID = UUID.Zero; + xmlStrings[objectGroup.UUID] = sceneObjectXml; + } - if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || - action == DeRezAction.SaveToExistingUserInventoryItem) - { - // Take or take copy require a taker - // Saving changes requires a local user - // - if (remoteClient == null) - return UUID.Zero; + string itemXml; - userID = remoteClient.AgentId; - } - else - { - // All returns / deletes go to the object owner - // + if (objlist.Count > 1) + { + float minX, minY, minZ; + float maxX, maxY, maxZ; - userID = objectGroup.RootPart.OwnerID; - } + Vector3[] offsets = m_Scene.GetCombinedBoundingBox(objlist, + out minX, out maxX, out minY, out maxY, + out minZ, out maxZ); - if (userID == UUID.Zero) // Can't proceed - { - return UUID.Zero; - } + // CreateWrapper + XmlDocument itemDoc = new XmlDocument(); + XmlElement root = itemDoc.CreateElement("", "CoalescedObject", ""); + itemDoc.AppendChild(root); - // If we're returning someone's item, it goes back to the - // owner's Lost And Found folder. - // Delete is treated like return in this case - // Deleting your own items makes them go to trash - // + // Embed the offsets into the group XML + for ( int i = 0 ; i < objlist.Count ; i++ ) + { + XmlDocument doc = new XmlDocument(); + SceneObjectGroup g = objlist[i]; + doc.LoadXml(xmlStrings[g.UUID]); + XmlElement e = (XmlElement)doc.SelectSingleNode("/SceneObjectGroup"); + e.SetAttribute("offsetx", offsets[i].X.ToString()); + e.SetAttribute("offsety", offsets[i].Y.ToString()); + e.SetAttribute("offsetz", offsets[i].Z.ToString()); - InventoryFolderBase folder = null; - InventoryItemBase item = null; + XmlNode objectNode = itemDoc.ImportNode(e, true); + root.AppendChild(objectNode); + } - if (DeRezAction.SaveToExistingUserInventoryItem == action) - { - item = new InventoryItemBase(objectGroup.RootPart.FromUserInventoryItemID, userID); - item = m_Scene.InventoryService.GetItem(item); + float sizeX = maxX - minX; + float sizeY = maxY - minY; + float sizeZ = maxZ - minZ; - //item = userInfo.RootFolder.FindItem( - // objectGroup.RootPart.FromUserInventoryItemID); + root.SetAttribute("x", sizeX.ToString()); + root.SetAttribute("y", sizeY.ToString()); + root.SetAttribute("z", sizeZ.ToString()); - if (null == item) + itemXml = itemDoc.InnerXml; + } + else { - m_log.DebugFormat( - "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", - objectGroup.Name, objectGroup.UUID); - return UUID.Zero; + itemXml = xmlStrings[objlist[0].UUID]; } - } - else - { - // Folder magic + + // Get the user info of the item destination // - if (action == DeRezAction.Delete) + UUID userID = UUID.Zero; + + if (action == DeRezAction.Take || action == DeRezAction.TakeCopy || + action == DeRezAction.SaveToExistingUserInventoryItem) { - // Deleting someone else's item + // Take or take copy require a taker + // Saving changes requires a local user // - if (remoteClient == null || - objectGroup.OwnerID != remoteClient.AgentId) - { + if (remoteClient == null) + return UUID.Zero; - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); - } - else - { - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); - } + userID = remoteClient.AgentId; } - else if (action == DeRezAction.Return) + else { - - // Dump to lost + found unconditionally + // All returns / deletes go to the object owner // - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); + + userID = objlist[0].RootPart.OwnerID; } - if (folderID == UUID.Zero && folder == null) + if (userID == UUID.Zero) // Can't proceed { - if (action == DeRezAction.Delete) + return UUID.Zero; + } + + // If we're returning someone's item, it goes back to the + // owner's Lost And Found folder. + // Delete is treated like return in this case + // Deleting your own items makes them go to trash + // + + InventoryFolderBase folder = null; + InventoryItemBase item = null; + + if (DeRezAction.SaveToExistingUserInventoryItem == action) + { + item = new InventoryItemBase(objlist[0].RootPart.FromUserInventoryItemID, userID); + item = m_Scene.InventoryService.GetItem(item); + + //item = userInfo.RootFolder.FindItem( + // objectGroup.RootPart.FromUserInventoryItemID); + + if (null == item) { - // Deletes go to trash by default - // - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); + m_log.DebugFormat( + "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.", + objlist[0].Name, objlist[0].UUID); + return UUID.Zero; } - else + } + else + { + // Folder magic + // + if (action == DeRezAction.Delete) { + // Deleting someone else's item + // if (remoteClient == null || - objectGroup.OwnerID != remoteClient.AgentId) + objlist[0].OwnerID != remoteClient.AgentId) { - // Taking copy of another person's item. Take to - // Objects folder. - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); + + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { - // Catch all. Use lost & found + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); + } + } + else if (action == DeRezAction.Return) + { + + // Dump to lost + found unconditionally + // + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); + } + + if (folderID == UUID.Zero && folder == null) + { + if (action == DeRezAction.Delete) + { + // Deletes go to trash by default // + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); + } + else + { + if (remoteClient == null || + objlist[0].OwnerID != remoteClient.AgentId) + { + // Taking copy of another person's item. Take to + // Objects folder. + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.Object); + } + else + { + // Catch all. Use lost & found + // - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); + } } } - } - // Override and put into where it came from, if it came - // from anywhere in inventory - // - if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) - { - if (objectGroup.RootPart.FromFolderID != UUID.Zero) + // Override and put into where it came from, if it came + // from anywhere in inventory + // + if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) { - InventoryFolderBase f = new InventoryFolderBase(objectGroup.RootPart.FromFolderID, userID); - folder = m_Scene.InventoryService.GetFolder(f); + if (objlist[0].RootPart.FromFolderID != UUID.Zero) + { + InventoryFolderBase f = new InventoryFolderBase(objlist[0].RootPart.FromFolderID, userID); + folder = m_Scene.InventoryService.GetFolder(f); + } } - } - - if (folder == null) // None of the above - { - folder = new InventoryFolderBase(folderID); - if (folder == null) // Nowhere to put it + if (folder == null) // None of the above { - return UUID.Zero; - } - } + folder = new InventoryFolderBase(folderID); - item = new InventoryItemBase(); - item.CreatorId = objectGroup.RootPart.CreatorID.ToString(); - item.ID = UUID.Random(); - item.InvType = (int)InventoryType.Object; - item.Folder = folder.ID; - item.Owner = userID; - } + if (folder == null) // Nowhere to put it + { + return UUID.Zero; + } + } - AssetBase asset = CreateAsset( - objectGroup.GetPartName(objectGroup.RootPart.LocalId), - objectGroup.GetPartDescription(objectGroup.RootPart.LocalId), - (sbyte)AssetType.Object, - Utils.StringToBytes(sceneObjectXml), - objectGroup.OwnerID.ToString()); - m_Scene.AssetService.Store(asset); - assetID = asset.FullID; + item = new InventoryItemBase(); + // Can't know creator is the same, so null it in inventory + if (objlist.Count > 1) + item.CreatorId = UUID.Zero.ToString(); + else + item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); + item.ID = UUID.Random(); + item.InvType = (int)InventoryType.Object; + item.Folder = folder.ID; + item.Owner = userID; + if (objlist.Count > 1) + item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; + } - if (DeRezAction.SaveToExistingUserInventoryItem == action) - { - item.AssetID = asset.FullID; - m_Scene.InventoryService.UpdateItem(item); - } - else - { - item.AssetID = asset.FullID; + AssetBase asset = CreateAsset( + objlist[0].GetPartName(objlist[0].RootPart.LocalId), + objlist[0].GetPartDescription(objlist[0].RootPart.LocalId), + (sbyte)AssetType.Object, + Utils.StringToBytes(itemXml), + objlist[0].OwnerID.ToString()); + m_Scene.AssetService.Store(asset); + assetID = asset.FullID; - if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) + if (DeRezAction.SaveToExistingUserInventoryItem == action) { - uint perms = objectGroup.GetEffectivePermissions(); - uint nextPerms = (perms & 7) << 13; - if ((nextPerms & (uint)PermissionMask.Copy) == 0) - perms &= ~(uint)PermissionMask.Copy; - if ((nextPerms & (uint)PermissionMask.Transfer) == 0) - perms &= ~(uint)PermissionMask.Transfer; - if ((nextPerms & (uint)PermissionMask.Modify) == 0) - perms &= ~(uint)PermissionMask.Modify; - - // Make sure all bits but the ones we want are clear - // on take. - // This will be applied to the current perms, so - // it will do what we want. - objectGroup.RootPart.NextOwnerMask &= - ((uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify); - objectGroup.RootPart.NextOwnerMask |= - (uint)PermissionMask.Move; - - item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask; - item.CurrentPermissions = item.BasePermissions; - item.NextPermissions = objectGroup.RootPart.NextOwnerMask; - item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask; - item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask; - - // Magic number badness. Maybe this deserves an enum. - // bit 4 (16) is the "Slam" bit, it means treat as passed - // and apply next owner perms on rez - item.CurrentPermissions |= 16; // Slam! + item.AssetID = asset.FullID; + m_Scene.InventoryService.UpdateItem(item); } else { - item.BasePermissions = objectGroup.GetEffectivePermissions(); - item.CurrentPermissions = objectGroup.GetEffectivePermissions(); - item.NextPermissions = objectGroup.RootPart.NextOwnerMask; - item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask; - item.GroupPermissions = objectGroup.RootPart.GroupMask; + item.AssetID = asset.FullID; + + uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move) | 7; + foreach (SceneObjectGroup grp in objlist) + effectivePerms &= grp.GetEffectivePermissions(); + effectivePerms |= (uint)PermissionMask.Move; + + if (remoteClient != null && (remoteClient.AgentId != objlist[0].RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) + { + uint perms = effectivePerms; + uint nextPerms = (perms & 7) << 13; + if ((nextPerms & (uint)PermissionMask.Copy) == 0) + perms &= ~(uint)PermissionMask.Copy; + if ((nextPerms & (uint)PermissionMask.Transfer) == 0) + perms &= ~(uint)PermissionMask.Transfer; + if ((nextPerms & (uint)PermissionMask.Modify) == 0) + perms &= ~(uint)PermissionMask.Modify; + + item.BasePermissions = perms & objlist[0].RootPart.NextOwnerMask; + item.CurrentPermissions = item.BasePermissions; + item.NextPermissions = perms & objlist[0].RootPart.NextOwnerMask; + item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & objlist[0].RootPart.NextOwnerMask; + item.GroupPermissions = objlist[0].RootPart.GroupMask & objlist[0].RootPart.NextOwnerMask; + + // Magic number badness. Maybe this deserves an enum. + // bit 4 (16) is the "Slam" bit, it means treat as passed + // and apply next owner perms on rez + item.CurrentPermissions |= 16; // Slam! + } + else + { + item.BasePermissions = effectivePerms; + item.CurrentPermissions = effectivePerms; + item.NextPermissions = objlist[0].RootPart.NextOwnerMask & effectivePerms; + item.EveryOnePermissions = objlist[0].RootPart.EveryoneMask & effectivePerms; + item.GroupPermissions = objlist[0].RootPart.GroupMask & effectivePerms; - item.CurrentPermissions &= - ((uint)PermissionMask.Copy | - (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify | - (uint)PermissionMask.Move | - 7); // Preserve folded permissions - } + item.CurrentPermissions &= + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify | + (uint)PermissionMask.Move | + 7); // Preserve folded permissions + } - // TODO: add the new fields (Flags, Sale info, etc) - item.CreationDate = Util.UnixTimeSinceEpoch(); - item.Description = asset.Description; - item.Name = asset.Name; - item.AssetType = asset.Type; + // TODO: add the new fields (Flags, Sale info, etc) + item.CreationDate = Util.UnixTimeSinceEpoch(); + item.Description = asset.Description; + item.Name = asset.Name; + item.AssetType = asset.Type; - m_Scene.AddInventoryItem(item); + m_Scene.AddInventoryItem(item); - if (remoteClient != null && item.Owner == remoteClient.AgentId) - { - remoteClient.SendInventoryItemCreateUpdate(item, 0); - } - else - { - ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); - if (notifyUser != null) + if (remoteClient != null && item.Owner == remoteClient.AgentId) { - notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); + remoteClient.SendInventoryItemCreateUpdate(item, 0); + } + else + { + ScenePresence notifyUser = m_Scene.GetScenePresence(item.Owner); + if (notifyUser != null) + { + notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0); + } } } } - return assetID; } diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index 64567db..8feb022 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -137,7 +137,7 @@ namespace OpenSim.Region.Framework.Scenes x = m_inventoryDeletes.Dequeue(); m_log.DebugFormat( - "[ASYNC DELETER]: Sending object to user's inventory, {0} item(s) remaining.", left); + "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", left, x.action, x.objectGroups.Count); try { @@ -177,4 +177,4 @@ namespace OpenSim.Region.Framework.Scenes return false; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index bcc439c..76e160d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -5063,8 +5063,17 @@ namespace OpenSim.Region.Framework.Scenes { float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; + Vector3 vec = g.AbsolutePosition; + g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); + ominX += vec.X; + omaxX += vec.X; + ominY += vec.Y; + omaxY += vec.Y; + ominZ += vec.Z; + omaxZ += vec.Z; + if (minX > ominX) minX = ominX; if (minY > ominY) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index a6d89cf..9a7d560 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1569,8 +1569,6 @@ namespace OpenSim.Region.Framework.Scenes ILandObject parcel = m_scene.LandChannel.GetLandObject( m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); - List returns = new List(); - if (parcel != null && parcel.LandData != null && parcel.LandData.OtherCleanTime != 0) { @@ -1584,15 +1582,14 @@ namespace OpenSim.Region.Framework.Scenes DetachFromBackup(); m_log.InfoFormat("[SCENE]: Returning object {0} due to parcel auto return", RootPart.UUID.ToString()); m_scene.AddReturn(OwnerID, Name, AbsolutePosition, "parcel auto return"); - returns.Add(RootPart.LocalId); + m_scene.DeRezObjects(null, new List() { RootPart.LocalId }, UUID.Zero, + DeRezAction.Return, UUID.Zero); return; } } } - m_scene.DeRezObjects(null, returns, UUID.Zero, - DeRezAction.Return, UUID.Zero); } if (HasGroupChanged) -- cgit v1.1 From ba0afa53d30566381d5757fb5a7b1ce55fe4521a Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 7 Oct 2010 05:12:39 +0200 Subject: Implement rezzing coalesced objects --- .../InventoryAccess/InventoryAccessModule.cs | 318 ++++++++++++--------- 1 file changed, 182 insertions(+), 136 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 753aada..d429979 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -444,7 +444,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess item.Folder = folder.ID; item.Owner = userID; if (objlist.Count > 1) + { item.Flags = (uint)InventoryItemFlags.ObjectHasMultipleItems; + } + else + { + item.SaleType = objlist[0].RootPart.ObjectSaleType; + item.SalePrice = objlist[0].RootPart.SalePrice; + } } AssetBase asset = CreateAsset( @@ -508,7 +515,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess 7); // Preserve folded permissions } - // TODO: add the new fields (Flags, Sale info, etc) item.CreationDate = Util.UnixTimeSinceEpoch(); item.Description = asset.Description; item.Name = asset.Name; @@ -587,6 +593,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess AssetBase rezAsset = m_Scene.AssetService.Get(item.AssetID.ToString()); + SceneObjectGroup group = null; + if (rezAsset != null) { UUID itemId = UUID.Zero; @@ -595,16 +603,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // item that it came from. This allows us to enable 'save object to inventory' if (!m_Scene.Permissions.BypassPermissions()) { - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy) + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy && (item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { itemId = item.ID; } } else { - // Brave new fullperm world - // - itemId = item.ID; + if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) + { + // Brave new fullperm world + itemId = item.ID; + } } if (item.ID == UUID.Zero) @@ -613,27 +623,63 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } string xmlData = Utils.BytesToString(rezAsset.Data); - SceneObjectGroup group - = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); - Vector3 storedPosition = group.AbsolutePosition; - if (group.UUID == UUID.Zero) + List objlist = + new List(); + List veclist = new List(); + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xmlData); + XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); + if (e == null || attachment) // Single { - m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 3"); - } - group.RootPart.FromFolderID = item.Folder; + SceneObjectGroup g = + SceneObjectSerializer.FromOriginalXmlFormat( + itemId, xmlData); + objlist.Add(g); + veclist.Add(new Vector3(0, 0, 0)); - // If it's rezzed in world, select it. Much easier to - // find small items. - // - if (!attachment) + float offsetHeight = 0; + pos = m_Scene.GetNewRezLocation( + RayStart, RayEnd, RayTargetID, Quaternion.Identity, + BypassRayCast, bRayEndIsIntersection, true, g.GetAxisAlignedBoundingBox(out offsetHeight), false); + pos.Z += offsetHeight; + } + else { - group.RootPart.CreateSelected = true; - foreach (SceneObjectPart child in group.Parts) - child.CreateSelected = true; + XmlElement coll = (XmlElement)e; + float bx = Convert.ToSingle(coll.GetAttribute("x")); + float by = Convert.ToSingle(coll.GetAttribute("y")); + float bz = Convert.ToSingle(coll.GetAttribute("z")); + Vector3 bbox = new Vector3(bx, by, bz); + + pos = m_Scene.GetNewRezLocation(RayStart, RayEnd, + RayTargetID, Quaternion.Identity, + BypassRayCast, bRayEndIsIntersection, true, + bbox, false); + + pos -= bbox / 2; + + XmlNodeList groups = e.SelectNodes("SceneObjectGroup"); + foreach (XmlNode n in groups) + { + SceneObjectGroup g = + SceneObjectSerializer.FromOriginalXmlFormat( + itemId, n.OuterXml); + objlist.Add(g); + XmlElement el = (XmlElement)n; + float x = Convert.ToSingle(el.GetAttribute("offsetx")); + float y = Convert.ToSingle(el.GetAttribute("offsety")); + float z = Convert.ToSingle(el.GetAttribute("offsetz")); + veclist.Add(new Vector3(x, y, z)); + } } + int primcount = 0; + foreach (SceneObjectGroup g in objlist) + primcount += g.PrimCount; + if (!m_Scene.Permissions.CanRezObject( - group.PrimCount, remoteClient.AgentId, pos) + primcount, remoteClient.AgentId, pos) && !attachment) { // The client operates in no fail mode. It will @@ -645,135 +691,139 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess remoteClient.SendBulkUpdateInventory(item); return null; } - if (group.UUID == UUID.Zero) - { - m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 4"); - } - group.ResetIDs(); - if (group.UUID == UUID.Zero) - { - m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 5"); - } - if (attachment) + + for (int i = 0 ; i < objlist.Count ; i++ ) { - group.RootPart.Flags |= PrimFlags.Phantom; - group.RootPart.IsAttachment = true; - } + group = objlist[i]; - // If we're rezzing an attachment then don't ask AddNewSceneObject() to update the client since - // we'll be doing that later on. Scheduling more than one full update during the attachment - // process causes some clients to fail to display the attachment properly. - m_Scene.AddNewSceneObject(group, true, false); + Vector3 storedPosition = group.AbsolutePosition; + if (group.UUID == UUID.Zero) + { + m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 3"); + } + group.RootPart.FromFolderID = item.Folder; - // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z); - // if attachment we set it's asset id so object updates can reflect that - // if not, we set it's position in world. - if (!attachment) - { - group.ScheduleGroupForFullUpdate(); - - float offsetHeight = 0; - pos = m_Scene.GetNewRezLocation( - RayStart, RayEnd, RayTargetID, Quaternion.Identity, - BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false); - pos.Z += offsetHeight; - group.AbsolutePosition = pos; - // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight); + // If it's rezzed in world, select it. Much easier to + // find small items. + // + if (!attachment) + { + group.RootPart.CreateSelected = true; + foreach (SceneObjectPart child in group.Parts) + child.CreateSelected = true; + } - } - else - { - group.SetFromItemID(itemID); - } - if (group.UUID == UUID.Zero) - { - m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 6"); - } - SceneObjectPart rootPart = null; - try - { - rootPart = group.GetChildPart(group.UUID); - } - catch (NullReferenceException) - { - string isAttachment = ""; + group.ResetIDs(); if (attachment) - isAttachment = " Object was an attachment"; + { + group.RootPart.Flags |= PrimFlags.Phantom; + group.RootPart.IsAttachment = true; + } - m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); - } - if (group.UUID == UUID.Zero) - { - m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 7"); - } - // Since renaming the item in the inventory does not affect the name stored - // in the serialization, transfer the correct name from the inventory to the - // object itself before we rez. - rootPart.Name = item.Name; - rootPart.Description = item.Description; - - group.SetGroup(remoteClient.ActiveGroupId, remoteClient); - if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) - { - //Need to kill the for sale here - rootPart.ObjectSaleType = 0; - rootPart.SalePrice = 10; + // If we're rezzing an attachment then don't ask + // AddNewSceneObject() to update the client since + // we'll be doing that later on. Scheduling more than + // one full update during the attachment + // process causes some clients to fail to display the + // attachment properly. + m_Scene.AddNewSceneObject(group, true, false); + + // if attachment we set it's asset id so object updates + // can reflect that, if not, we set it's position in world. + if (!attachment) + { + group.ScheduleGroupForFullUpdate(); + + group.AbsolutePosition = pos + veclist[i]; + } + else + { + group.SetFromItemID(itemID); + } + + SceneObjectPart rootPart = null; + + try + { + rootPart = group.GetChildPart(group.UUID); + } + catch (NullReferenceException) + { + string isAttachment = ""; + + if (attachment) + isAttachment = " Object was an attachment"; + + m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment); + } - if (m_Scene.Permissions.PropagatePermissions()) + // Since renaming the item in the inventory does not + // affect the name stored in the serialization, transfer + // the correct name from the inventory to the + // object itself before we rez. + rootPart.Name = item.Name; + rootPart.Description = item.Description; + rootPart.ObjectSaleType = item.SaleType; + rootPart.SalePrice = item.SalePrice; + + group.SetGroup(remoteClient.ActiveGroupId, remoteClient); + if ((rootPart.OwnerID != item.Owner) || + (item.CurrentPermissions & 16) != 0) { - foreach (SceneObjectPart part in group.Parts) + //Need to kill the for sale here + rootPart.ObjectSaleType = 0; + rootPart.SalePrice = 10; + + if (m_Scene.Permissions.PropagatePermissions()) { - part.EveryoneMask = item.EveryOnePermissions; - part.NextOwnerMask = item.NextPermissions; - part.GroupMask = 0; // DO NOT propagate here + foreach (SceneObjectPart part in group.Parts) + { + if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) + { + part.EveryoneMask = item.EveryOnePermissions; + part.NextOwnerMask = item.NextPermissions; + } + part.GroupMask = 0; // DO NOT propagate here + } + + group.ApplyNextOwnerPermissions(); } - - group.ApplyNextOwnerPermissions(); } - } - if (group.UUID == UUID.Zero) - { - m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 8"); - } - foreach (SceneObjectPart part in group.Parts) - { - if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) + foreach (SceneObjectPart part in group.Parts) { - part.LastOwnerID = part.OwnerID; - part.OwnerID = item.Owner; - part.Inventory.ChangeInventoryOwner(item.Owner); - part.GroupMask = 0; // DO NOT propagate here + if ((part.OwnerID != item.Owner) || + (item.CurrentPermissions & 16) != 0) + { + part.LastOwnerID = part.OwnerID; + part.OwnerID = item.Owner; + part.Inventory.ChangeInventoryOwner(item.Owner); + part.GroupMask = 0; // DO NOT propagate here + } + part.EveryoneMask = item.EveryOnePermissions; + part.NextOwnerMask = item.NextPermissions; } - part.EveryoneMask = item.EveryOnePermissions; - part.NextOwnerMask = item.NextPermissions; - } - if (group.UUID == UUID.Zero) - { - m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 9"); - } - rootPart.TrimPermissions(); - if (group.UUID == UUID.Zero) - { - m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 10"); - } - if (!attachment) - { - if (group.RootPart.Shape.PCode == (byte)PCode.Prim) + + rootPart.TrimPermissions(); + + if (!attachment) { - // Save attachment data - group.RootPart.AttachPoint = group.RootPart.Shape.State; - group.RootPart.AttachOffset = storedPosition; + if (group.RootPart.Shape.PCode == (byte)PCode.Prim) + { + // Save attachment data + group.RootPart.AttachPoint = group.RootPart.Shape.State; + group.RootPart.AttachOffset = storedPosition; - group.ClearPartAttachmentData(); - } - - // Fire on_rez - group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); - rootPart.ParentGroup.ResumeScripts(); + group.ClearPartAttachmentData(); + } + + // Fire on_rez + group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); + rootPart.ParentGroup.ResumeScripts(); - rootPart.ScheduleFullUpdate(); + rootPart.ScheduleFullUpdate(); + } } if (!m_Scene.Permissions.BypassPermissions()) @@ -791,12 +841,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } } - if (group.UUID == UUID.Zero) - { - m_log.Debug("[InventoryAccessModule]: Inventory object has UUID.Zero! Position 11"); - } - return group; } + return group; } return null; -- cgit v1.1 From 52dd547863c0cdd22f53f0efcaef11ae096855a0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 8 Oct 2010 11:31:52 +0200 Subject: Make SendKillObject send multiple localIDs in one packet. This avoids the halting visual behavior of large group deletes and eliminates the packet flood --- OpenSim/Client/MXP/ClientStack/MXPClientView.cs | 8 ++++- .../Client/VWoHTTP/ClientStack/VWHClientView.cs | 2 +- OpenSim/Framework/IClientAPI.cs | 2 +- .../Region/ClientStack/LindenUDP/LLClientView.cs | 41 ++++++++++++++-------- .../Avatar/Attachments/AttachmentsModule.cs | 2 +- .../EntityTransfer/EntityTransferModule.cs | 2 +- .../Region/Examples/SimpleModule/ComplexObject.cs | 5 +-- .../Region/Examples/SimpleModule/MyNpcCharacter.cs | 2 +- .../Scenes/AsyncSceneObjectGroupDeleter.cs | 7 ++++ OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 8 +++-- OpenSim/Region/Framework/Scenes/Scene.cs | 26 ++++++++------ .../Framework/Scenes/SceneCommunicationService.cs | 4 --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 6 +--- .../Server/IRCClientView.cs | 2 +- .../ContentManagementSystem/CMModel.cs | 3 +- .../ContentManagementSystem/MetaEntity.cs | 4 +-- .../Region/OptionalModules/World/NPC/NPCAvatar.cs | 2 +- .../World/TreePopulator/TreePopulatorModule.cs | 4 +-- OpenSim/Tests/Common/Mock/TestClient.cs | 2 +- 19 files changed, 79 insertions(+), 53 deletions(-) diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index 87b99e0..df9d21b 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -897,7 +897,13 @@ namespace OpenSim.Client.MXP.ClientStack // Need to translate to MXP somehow } - public void SendKillObject(ulong regionHandle, uint localID) + public void SendKillObject(ulong regionHandle, List localIDs) + { + foreach (uint localID in localIDs) + SendKillObject(regionHandle, localID); + } + + private void SendKillObject(ulong regionHandle, uint localID) { DisappearanceEventMessage de = new DisappearanceEventMessage(); de.ObjectIndex = localID; diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 51c5c17..26be5d9 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -495,7 +495,7 @@ namespace OpenSim.Client.VWoHTTP.ClientStack throw new System.NotImplementedException(); } - public void SendKillObject(ulong regionHandle, uint localID) + public void SendKillObject(ulong regionHandle, List localID) { throw new System.NotImplementedException(); } diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 9025dda..51482a1 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -979,7 +979,7 @@ namespace OpenSim.Framework /// /// /// - void SendKillObject(ulong regionHandle, uint localID); + void SendKillObject(ulong regionHandle, List localID); void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 2b1bd97..fff4300 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -1516,35 +1516,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(pc, ThrottleOutPacketType.Unknown); } - public void SendKillObject(ulong regionHandle, uint localID) + public void SendKillObject(ulong regionHandle, List localIDs) { // m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); // TODO: don't create new blocks if recycling an old packet - kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; - kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); - kill.ObjectData[0].ID = localID; + kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count]; + for (int i = 0 ; i < localIDs.Count ; i++ ) + { + kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock(); + kill.ObjectData[i].ID = localIDs[i]; + } kill.Header.Reliable = true; kill.Header.Zerocoded = true; - if (m_scene.GetScenePresence(localID) == null) + if (localIDs.Count == 1) { - lock (m_entityUpdates.SyncRoot) + if (m_scene.GetScenePresence(localIDs[0]) != null) { - m_killRecord.Add(localID); - - // The throttle queue used here must match that being used for updates. Otherwise, there is a - // chance that a kill packet put on a separate queue will be sent to the client before an existing - // update packet on another queue. Receiving updates after kills results in unowned and undeletable - // scene objects in a viewer until that viewer is relogged in. - OutPacket(kill, ThrottleOutPacketType.Task); + OutPacket(kill, ThrottleOutPacketType.State); + return; } + m_killRecord.Add(localIDs[0]); } else { - OutPacket(kill, ThrottleOutPacketType.State); + lock (m_entityUpdates.SyncRoot) + { + foreach (uint localID in localIDs) + m_killRecord.Add(localID); + } } + + // The throttle queue used here must match that being used for + // updates. Otherwise, there is a chance that a kill packet put + // on a separate queue will be sent to the client before an + // existing update packet on another queue. Receiving updates + // after kills results in unowned and undeletable + // scene objects in a viewer until that viewer is relogged in. + OutPacket(kill, ThrottleOutPacketType.Task); } /// @@ -10969,7 +10980,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { // It's a ghost! tell the client to delete it from view. simClient.SendKillObject(Scene.RegionInfo.RegionHandle, - localId); + new List() { localId }); } else { diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 87c9100..6ff0ffc 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -616,7 +616,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // if (so.IsSelected) { - m_scene.SendKillObject(so.RootPart.LocalId); + m_scene.SendKillObject(new List { so.RootPart.LocalId }); } so.IsSelected = false; // fudge.... diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index d506208..2921b0d 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -529,7 +529,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected void KillEntity(Scene scene, uint localID) { - scene.SendKillObject(localID); + scene.SendKillObject(new List() { localID }); } protected virtual GridRegion GetFinalDestination(GridRegion region) diff --git a/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs b/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs index e951bef..7a0ce51 100644 --- a/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs +++ b/OpenSim/Region/Examples/SimpleModule/ComplexObject.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; @@ -110,7 +111,7 @@ namespace OpenSim.Region.Examples.SimpleModule { m_parts.Remove(part.UUID); - remoteClient.SendKillObject(m_regionHandle, part.LocalId); + remoteClient.SendKillObject(m_regionHandle, new List() { part.LocalId} ); remoteClient.AddMoney(1); remoteClient.SendChatMessage("Poof!", 1, AbsolutePosition, "Party Party", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); } @@ -121,7 +122,7 @@ namespace OpenSim.Region.Examples.SimpleModule { m_parts.Remove(m_rootPart.UUID); m_scene.DeleteSceneObject(this, false); - remoteClient.SendKillObject(m_regionHandle, m_rootPart.LocalId); + remoteClient.SendKillObject(m_regionHandle, new List() { m_rootPart.LocalId }); remoteClient.AddMoney(50); remoteClient.SendChatMessage("KABLAM!!!", 1, AbsolutePosition, "Groupie Groupie", UUID.Zero, (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); } diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 944ad94..db427b4 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -429,7 +429,7 @@ namespace OpenSim.Region.Examples.SimpleModule } - public virtual void SendKillObject(ulong regionHandle, uint localID) + public virtual void SendKillObject(ulong regionHandle, List localID) { } diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index 8feb022..a8d24fd 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs @@ -104,8 +104,15 @@ namespace OpenSim.Region.Framework.Scenes // better than losing the object for now. if (permissionToDelete) { + List killIDs = new List(); + foreach (SceneObjectGroup g in objectGroups) + { + killIDs.Add(g.LocalId); g.DeleteGroupFromScene(false); + } + + m_scene.SendKillObject(killIDs); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 8b5316a..6d7f984 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1709,7 +1709,7 @@ namespace OpenSim.Region.Framework.Scenes if (part == null) { //Client still thinks the object exists, kill it - SendKillObject(localID); + deleteIDs.Add(localID); continue; } @@ -1717,7 +1717,7 @@ namespace OpenSim.Region.Framework.Scenes if (part.ParentGroup == null || part.ParentGroup.IsDeleted) { //Client still thinks the object exists, kill it - SendKillObject(localID); + deleteIDs.Add(localID); continue; } @@ -1727,8 +1727,8 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup grp = part.ParentGroup; - deleteIDs.Add(localID); deleteGroups.Add(grp); + deleteIDs.Add(grp.LocalId); if (remoteClient == null) { @@ -1811,6 +1811,8 @@ namespace OpenSim.Region.Framework.Scenes } } + SendKillObject(deleteIDs); + if (permissionToTake) { m_asyncSceneObjectDeleter.DeleteToInventory( diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 76e160d..48ae4ca 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2188,6 +2188,8 @@ namespace OpenSim.Region.Framework.Scenes } group.DeleteGroupFromScene(silent); + if (!silent) + SendKillObject(new List() { group.LocalId }); // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); } @@ -3273,7 +3275,7 @@ namespace OpenSim.Region.Framework.Scenes delegate(IClientAPI client) { //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway - try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } + try { client.SendKillObject(avatar.RegionHandle, new List() { avatar.LocalId}); } catch (NullReferenceException) { } }); @@ -3336,18 +3338,24 @@ namespace OpenSim.Region.Framework.Scenes #region Entities - public void SendKillObject(uint localID) + public void SendKillObject(List localIDs) { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) // It is a prim + List deleteIDs = new List(); + + foreach (uint localID in localIDs) { - if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid + SceneObjectPart part = GetSceneObjectPart(localID); + if (part != null) // It is a prim { - if (part.ParentGroup.RootPart != part) // Child part - return; + if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid + { + if (part.ParentGroup.RootPart != part) // Child part + continue; + } } + deleteIDs.Add(localID); } - ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); + ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); }); } #endregion @@ -3365,7 +3373,6 @@ namespace OpenSim.Region.Framework.Scenes //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; - m_sceneGridService.KiPrimitive += SendKillObject; m_sceneGridService.OnGetLandData += GetLandData; } @@ -3374,7 +3381,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void UnRegisterRegionWithComms() { - m_sceneGridService.KiPrimitive -= SendKillObject; m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index 1293d5d..632646d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -44,8 +44,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.Framework.Scenes { - public delegate void KiPrimitiveDelegate(uint localID); - public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List regionlst); /// @@ -113,8 +111,6 @@ namespace OpenSim.Region.Framework.Scenes // private LogOffUser handlerLogOffUser = null; // private GetLandData handlerGetLandData = null; // OnGetLandData - public KiPrimitiveDelegate KiPrimitive; - public SceneCommunicationService() { } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 9a7d560..c870797 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1151,7 +1151,7 @@ namespace OpenSim.Region.Framework.Scenes // if (IsSelected) { - m_scene.SendKillObject(m_rootPart.LocalId); + m_scene.SendKillObject(new List { m_rootPart.LocalId }); } IsSelected = false; // fudge.... @@ -1415,11 +1415,7 @@ namespace OpenSim.Region.Framework.Scenes avatar.StandUp(); if (!silent) - { part.UpdateFlag = 0; - if (part == m_rootPart) - avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); - } }); } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 4ab67aa..72e5ebd 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -947,7 +947,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void SendKillObject(ulong regionHandle, uint localID) + public void SendKillObject(ulong regionHandle, List localID) { } diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs index 3a6996e..84c7f29 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/CMModel.cs @@ -259,9 +259,10 @@ namespace OpenSim.Region.OptionalModules.ContentManagement // I thought that the DeleteGroup() function would handle all of this, but it doesn't. I'm not sure WHAT it handles. ((SceneObjectGroup)scene.Entities[uuid]).DetachFromBackup(); scene.PhysicsScene.RemovePrim(((SceneObjectGroup)scene.Entities[uuid]).RootPart.PhysActor); - scene.SendKillObject(scene.Entities[uuid].LocalId); + scene.SendKillObject(new List() { scene.Entities[uuid].LocalId }); scene.SceneGraph.DeleteSceneObject(uuid, false); ((SceneObjectGroup)scene.Entities[uuid]).DeleteGroupFromScene(false); + scene.SendKillObject(new List() { ((SceneObjectGroup)scene.Entities[uuid]).LocalId }); } catch(Exception e) { diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs index c7b1ed7..cd60f4b 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs @@ -175,7 +175,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement //This is important because we are not IN any database. //m_Entity.FakeDeleteGroup(); foreach (SceneObjectPart part in m_Entity.Parts) - client.SendKillObject(m_Entity.RegionHandle, part.LocalId); + client.SendKillObject(m_Entity.RegionHandle, new List() { part.LocalId }); } /// @@ -187,7 +187,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement { m_Entity.Scene.ForEachClient( delegate(IClientAPI controller) - { controller.SendKillObject(m_Entity.RegionHandle, part.LocalId); } + { controller.SendKillObject(m_Entity.RegionHandle, new List() { part.LocalId }); } ); } } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 1653ecb..3cbe391 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -519,7 +519,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC } - public virtual void SendKillObject(ulong regionHandle, uint localID) + public virtual void SendKillObject(ulong regionHandle, List localID) { } diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs index 421da36..2563361 100644 --- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs +++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs @@ -386,7 +386,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator m_scene.ForEachClient(delegate(IClientAPI controller) { controller.SendKillObject(m_scene.RegionInfo.RegionHandle, - selectedTree.LocalId); + new List() { selectedTree.LocalId }); }); } else @@ -727,7 +727,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator m_scene.ForEachClient(delegate(IClientAPI controller) { controller.SendKillObject(m_scene.RegionInfo.RegionHandle, - selectedTree.LocalId); + new List() { selectedTree.LocalId }); }); break; diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 1c860a7..6324146 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -487,7 +487,7 @@ namespace OpenSim.Tests.Common.Mock } - public virtual void SendKillObject(ulong regionHandle, uint localID) + public virtual void SendKillObject(ulong regionHandle, List localID) { } -- cgit v1.1 From ff49a21eca5b084bf0df71f69bce98db0b2f0094 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 9 Oct 2010 01:02:57 +0200 Subject: Fix a security relevant issue with take / take copy --- OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 110 ++++++++++++--------- 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6d7f984..9b5459d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1695,6 +1695,7 @@ namespace OpenSim.Region.Framework.Scenes // build a list of eligible objects List deleteIDs = new List(); List deleteGroups = new List(); + List takeGroups = new List(); // Start with true for both, then remove the flags if objects // that we can't derez are part of the selection @@ -1727,9 +1728,6 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup grp = part.ParentGroup; - deleteGroups.Add(grp); - deleteIDs.Add(grp.LocalId); - if (remoteClient == null) { // Autoreturn has a null client. Nothing else does. So @@ -1756,73 +1754,89 @@ namespace OpenSim.Region.Framework.Scenes if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) permissionToDelete = false; } - } - // Handle god perms - if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) - { - permissionToTake = true; - permissionToTakeCopy = true; - permissionToDelete = true; - } + // Handle god perms + if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) + { + permissionToTake = true; + permissionToTakeCopy = true; + permissionToDelete = true; + } - // If we're re-saving, we don't even want to delete - if (action == DeRezAction.SaveToExistingUserInventoryItem) - permissionToDelete = false; + // If we're re-saving, we don't even want to delete + if (action == DeRezAction.SaveToExistingUserInventoryItem) + permissionToDelete = false; - // if we want to take a copy, we also don't want to delete - // Note: after this point, the permissionToTakeCopy flag - // becomes irrelevant. It already includes the permissionToTake - // permission and after excluding no copy items here, we can - // just use that. - if (action == DeRezAction.TakeCopy) - { - // If we don't have permission, stop right here - if (!permissionToTakeCopy) - return; + // if we want to take a copy, we also don't want to delete + // Note: after this point, the permissionToTakeCopy flag + // becomes irrelevant. It already includes the permissionToTake + // permission and after excluding no copy items here, we can + // just use that. + if (action == DeRezAction.TakeCopy) + { + // If we don't have permission, stop right here + if (!permissionToTakeCopy) + return; - permissionToTake = true; - // Don't delete - permissionToDelete = false; - } + permissionToTake = true; + // Don't delete + permissionToDelete = false; + } - if (action == DeRezAction.Return) - { - if (remoteClient != null) + if (action == DeRezAction.Return) { - if (Permissions.CanReturnObjects( - null, - remoteClient.AgentId, - deleteGroups)) + if (remoteClient != null) + { + if (Permissions.CanReturnObjects( + null, + remoteClient.AgentId, + deleteGroups)) + { + permissionToTake = true; + permissionToDelete = true; + + AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return"); + } + } + else // Auto return passes through here with null agent { permissionToTake = true; permissionToDelete = true; + } - foreach (SceneObjectGroup g in deleteGroups) - { - AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); - } + if (permissionToTake && (!permissionToDelete)) + takeGroups.Add(grp); + + if (permissionToDelete) + { + if (permissionToTake) + deleteGroups.Add(grp); + deleteIDs.Add(grp.LocalId); } } - else // Auto return passes through here with null agent - { - permissionToTake = true; - permissionToDelete = true; - } } SendKillObject(deleteIDs); - if (permissionToTake) + if (deleteGroups.Count > 0) { + foreach (SceneObjectGroup g in deleteGroups) + deleteIDs.Remove(g.LocalId); + m_asyncSceneObjectDeleter.DeleteToInventory( action, destinationID, deleteGroups, remoteClient, - permissionToDelete); + true); + } + if (takeGroups.Count > 0) + { + m_asyncSceneObjectDeleter.DeleteToInventory( + action, destinationID, takeGroups, remoteClient, + false); } - else if (permissionToDelete) + if (deleteIDs.Count > 0) { foreach (SceneObjectGroup g in deleteGroups) - DeleteSceneObject(g, false); + DeleteSceneObject(g, true); } } -- cgit v1.1 From c2971a6398f21cb3eb6c9cad46348a035eb2a0f5 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 10 Oct 2010 20:15:02 +0200 Subject: Add group invites to the list of messages that get offlined --- .../Avatar/InstantMessage/OfflineMessageModule.cs | 1 + OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | 28 +++++++++++----------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index feeb9e6..d3db5b7 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -215,6 +215,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage if (im.dialog != (byte)InstantMessageDialog.MessageFromObject && im.dialog != (byte)InstantMessageDialog.MessageFromAgent && im.dialog != (byte)InstantMessageDialog.GroupNotice && + im.dialog != (byte)InstantMessageDialog.GroupInvitation && im.dialog != (byte)InstantMessageDialog.InventoryOffered) { return; diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 9b5459d..1d8b988 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1697,14 +1697,14 @@ namespace OpenSim.Region.Framework.Scenes List deleteGroups = new List(); List takeGroups = new List(); - // Start with true for both, then remove the flags if objects - // that we can't derez are part of the selection - bool permissionToTake = true; - bool permissionToTakeCopy = true; - bool permissionToDelete = true; - foreach (uint localID in localIDs) { + // Start with true for both, then remove the flags if objects + // that we can't derez are part of the selection + bool permissionToTake = true; + bool permissionToTakeCopy = true; + bool permissionToDelete = true; + // Invalid id SceneObjectPart part = GetSceneObjectPart(localID); if (part == null) @@ -1803,16 +1803,16 @@ namespace OpenSim.Region.Framework.Scenes permissionToTake = true; permissionToDelete = true; } + } - if (permissionToTake && (!permissionToDelete)) - takeGroups.Add(grp); + if (permissionToTake && (!permissionToDelete)) + takeGroups.Add(grp); - if (permissionToDelete) - { - if (permissionToTake) - deleteGroups.Add(grp); - deleteIDs.Add(grp.LocalId); - } + if (permissionToDelete) + { + if (permissionToTake) + deleteGroups.Add(grp); + deleteIDs.Add(grp.LocalId); } } -- cgit v1.1 From 2804c97a39ece1352bc8ce8cf3672307798417df Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 10 Oct 2010 22:06:47 +0100 Subject: Change the part for sound playback to be the root part / object UUID instead of the child prim because using the child prim plain doesn't work. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index efdb94c..726bda1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -2730,7 +2730,7 @@ namespace OpenSim.Region.Framework.Scenes public void PreloadSound(string sound) { // UUID ownerID = OwnerID; - UUID objectID = UUID; + UUID objectID = ParentGroup.RootPart.UUID; UUID soundID = UUID.Zero; if (!UUID.TryParse(sound, out soundID)) @@ -3112,7 +3112,7 @@ namespace OpenSim.Region.Framework.Scenes volume = 0; UUID ownerID = _ownerID; - UUID objectID = UUID; + UUID objectID = ParentGroup.RootPart.UUID; UUID parentID = GetRootPartUUID(); if (ParentGroup.IsAttachment && ParentGroup.RootPart.Shape.State > 30) @@ -3157,11 +3157,11 @@ namespace OpenSim.Region.Framework.Scenes else soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); ParentGroup.PlaySoundMasterPrim = this; - ownerID = this._ownerID; - objectID = this.UUID; - parentID = this.GetRootPartUUID(); - position = this.AbsolutePosition; // region local - regionHandle = this.ParentGroup.Scene.RegionInfo.RegionHandle; + ownerID = _ownerID; + objectID = ParentGroup.RootPart.UUID; + parentID = GetRootPartUUID(); + position = AbsolutePosition; // region local + regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; if (triggered) soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); else @@ -3169,7 +3169,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) { ownerID = prim._ownerID; - objectID = prim.UUID; + objectID = prim.ParentGroup.RootPart.UUID; parentID = prim.GetRootPartUUID(); position = prim.AbsolutePosition; // region local regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle; -- cgit v1.1 From 3eb68c319e1211bf0d4e251931f23d44ac88e63e Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 13 Oct 2010 08:24:18 +0200 Subject: change default next owner persm to mod/trans to match SL. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 726bda1..f0740f8 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -443,7 +443,7 @@ namespace OpenSim.Region.Framework.Scenes private uint _ownerMask = (uint)PermissionMask.All; private uint _groupMask = (uint)PermissionMask.None; private uint _everyoneMask = (uint)PermissionMask.None; - private uint _nextOwnerMask = (uint)PermissionMask.All; + private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer); private PrimFlags _flags = PrimFlags.None; private DateTime m_expires; private DateTime m_rezzed; @@ -1668,6 +1668,9 @@ namespace OpenSim.Region.Framework.Scenes // Move afterwards ResetIDs as it clears the localID dupe.LocalId = localID; + if(dupe.PhysActor != null) + dupe.PhysActor.LocalID = localID; + // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. dupe._lastOwnerID = OwnerID; -- cgit v1.1 From 537905d81b1d1d4c573eb56f41afdc39c1eec5ef Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 13 Oct 2010 19:45:55 +0100 Subject: Add a setter to OldItemID so it can be deserialized --- OpenSim/Framework/TaskInventoryItem.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs index 883f61a..53237fc 100644 --- a/OpenSim/Framework/TaskInventoryItem.cs +++ b/OpenSim/Framework/TaskInventoryItem.cs @@ -227,6 +227,9 @@ namespace OpenSim.Framework get { return _oldID; } + set { + _oldID = value; + } } public UUID LastOwnerID { -- cgit v1.1 From efc555ca225f05d1adfa8ed75f5802637bd76a9f Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 16 Oct 2010 10:50:07 +0200 Subject: Actually set the PrivateBinPath in XEngine so relocating the scripts directory works --- OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | 7 ++++--- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index b4da246..623cb7d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -56,7 +56,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { public class ScriptInstance : MarshalByRefObject, IScriptInstance { - // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IScriptEngine m_Engine; private IScriptWorkItem m_CurrentResult = null; @@ -271,9 +271,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); // lease.Register(this); } - catch (Exception) + catch (Exception e) { - // m_log.ErrorFormat("[Script] Error loading assembly {0}\n"+e.ToString(), assembly); + m_log.ErrorFormat("[Script] Error loading assembly {0}\n"+e.ToString(), assembly); + throw; } try diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index c0ec0e8..35cc65b 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -794,9 +794,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine try { AppDomainSetup appSetup = new AppDomainSetup(); - // appSetup.ApplicationBase = Path.Combine( - // "ScriptEngines", - // m_Scene.RegionInfo.RegionID.ToString()); + appSetup.PrivateBinPath = Path.Combine( + m_ScriptEnginesPath, + m_Scene.RegionInfo.RegionID.ToString()); Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; Evidence evidence = new Evidence(baseEvidence); -- cgit v1.1 From 78a6e5489beccbd4de7385219d0d214323a3d9a1 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 18 Oct 2010 20:50:16 +0200 Subject: Fix merge issues --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 7ec3697..0321515 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -191,7 +191,6 @@ namespace OpenSim.Region.Framework.Scenes public UUID FromFolderID; -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/SceneObjectPart.cs // The following two are to hold the attachment data // while an object is inworld [XmlIgnore] @@ -201,9 +200,6 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 AttachOffset = Vector3.Zero; [XmlIgnore] -======= - ->>>>>>> master:OpenSim/Region/Framework/Scenes/SceneObjectPart.cs public int STATUS_ROTATE_X; @@ -633,20 +629,12 @@ namespace OpenSim.Region.Framework.Scenes set { m_LoopSoundSlavePrims = value; } } -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/SceneObjectPart.cs -======= - ->>>>>>> master:OpenSim/Region/Framework/Scenes/SceneObjectPart.cs public Byte[] TextureAnimation { get { return m_TextureAnimation; } set { m_TextureAnimation = value; } } -<<<<<<< HEAD:OpenSim/Region/Framework/Scenes/SceneObjectPart.cs -======= - ->>>>>>> master:OpenSim/Region/Framework/Scenes/SceneObjectPart.cs public Byte[] ParticleSystem { get { return m_particleSystem; } -- cgit v1.1 From ce3594f7f2b5a4af2d92d6b2c812f7241c61e82b Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 18 Oct 2010 22:58:04 +0100 Subject: Change substring matching to prefix matching in region search. This affects both map and login, as they use the same method. --- OpenSim/Services/GridService/GridService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index ce6f64b..e7988d6 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -323,7 +323,7 @@ namespace OpenSim.Services.GridService { m_log.DebugFormat("[GRID SERVICE]: GetRegionsByName {0}", name); - List rdatas = m_Database.Get("%" + name + "%", scopeID); + List rdatas = m_Database.Get(name + "%", scopeID); int count = 0; List rinfos = new List(); -- cgit v1.1 From 8853c21763790389f4bcc3b21993221630fdfd2e Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 19 Oct 2010 01:22:31 +0100 Subject: COmmented the wrong line instead, now I commented them all to be on the safe side --- .../Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index 49ebe81..e33ad4a 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -1363,7 +1363,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } else { - m_log.DebugFormat("[SceneObjectSerializer]: caught unknown element {0}", nodeName); +// m_log.DebugFormat("[SceneObjectSerializer]: caught unknown element {0}", nodeName); reader.ReadOuterXml(); // ignore } @@ -1467,7 +1467,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization p(shape, reader); else { - m_log.DebugFormat("[SceneObjectSerializer]: caught unknown element in Shape {0}", reader.Name); +// m_log.DebugFormat("[SceneObjectSerializer]: caught unknown element in Shape {0}", reader.Name); reader.ReadOuterXml(); } } -- cgit v1.1 From fa7da00cc3113bf57d12bdec84ebdf748cae07f7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 21 Oct 2010 09:35:33 +0100 Subject: COnvert some funky K&R notation to proper (MS) style --- .../Shared/Api/Implementation/LSL_Api.cs | 61 +++++++++++++++------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index e94790f..296a50e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3824,7 +3824,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (targetPart != null) { - if (parent != 0) { + if (parent != 0) + { parentPrim = m_host.ParentGroup; childPrim = targetPart.ParentGroup; } @@ -5426,7 +5427,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } - else { + else + { object[] array = new object[src.Length]; Array.Copy(src.Data, 0, array, 0, src.Length); result = new LSL_List(array); @@ -6271,7 +6273,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api SetParticleSystem(m_host, rules); } - private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { + private void SetParticleSystem(SceneObjectPart part, LSL_List rules) + { if (rules.Length == 0) @@ -8965,17 +8968,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api * Convert separator and spacer lists to C# strings. * Also filter out null strings so we don't hang. */ - for (i = 0; i < seplen; i ++) { + for (i = 0; i < seplen; i ++) + { d = separray[i].ToString(); - if (d.Length > 0) { + if (d.Length > 0) + { delarray[dellen++] = d; } } seplen = dellen; - for (i = 0; i < spclen; i ++) { + for (i = 0; i < spclen; i ++) + { d = spcarray[i].ToString(); - if (d.Length > 0) { + if (d.Length > 0) + { delarray[dellen++] = d; } } @@ -8983,7 +8990,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /* * Scan through source string from beginning to end. */ - for (i = 0;;) { + for (i = 0;;) + { /* * Find earliest delimeter in src starting at i (if any). @@ -8991,13 +8999,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api int earliestDel = -1; int earliestSrc = srclen; string earliestStr = null; - for (j = 0; j < dellen; j ++) { + for (j = 0; j < dellen; j ++) + { d = delarray[j]; - if (d != null) { + if (d != null) + { int index = src.IndexOf(d, i); - if (index < 0) { + if (index < 0) + { delarray[j] = null; // delim nowhere in src, don't check it anymore - } else if (index < earliestSrc) { + } + else if (index < earliestSrc) + { earliestSrc = index; // where delimeter starts in source string earliestDel = j; // where delimeter is in delarray[] earliestStr = d; // the delimeter string from delarray[] @@ -9009,7 +9022,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /* * Output source string starting at i through start of earliest delimeter. */ - if (keepNulls || (earliestSrc > i)) { + if (keepNulls || (earliestSrc > i)) + { outarray[outlen++] = src.Substring(i, earliestSrc - i); } @@ -9021,7 +9035,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /* * If delimeter was a spacer, output the spacer. */ - if (earliestDel >= seplen) { + if (earliestDel >= seplen) + { outarray[outlen++] = earliestStr; } @@ -9035,7 +9050,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api * Make up an exact-sized output array suitable for an LSL_List object. */ object[] outlist = new object[outlen]; - for (i = 0; i < outlen; i ++) { + for (i = 0; i < outlen; i ++) + { outlist[i] = new LSL_String(outarray[i]); } return new LSL_List(outlist); @@ -10002,12 +10018,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api SortedDictionary parameters = new SortedDictionary(); object[] data = rules.Data; - for (int i = 0; i < data.Length; ++i) { + for (int i = 0; i < data.Length; ++i) + { int type = Convert.ToInt32(data[i++].ToString()); if (i >= data.Length) break; // odd number of entries => ignore the last // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) - switch (type) { + switch (type) + { case ScriptBaseClass.CAMERA_FOCUS: case ScriptBaseClass.CAMERA_FOCUS_OFFSET: case ScriptBaseClass.CAMERA_POSITION: @@ -10213,12 +10231,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Regex r = new Regex(authregex); int[] gnums = r.GetGroupNumbers(); Match m = r.Match(url); - if (m.Success) { - for (int i = 1; i < gnums.Length; i++) { + if (m.Success) + { + for (int i = 1; i < gnums.Length; i++) + { //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; //CaptureCollection cc = g.Captures; } - if (m.Groups.Count == 5) { + if (m.Groups.Count == 5) + { httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); url = m.Groups[1].ToString() + m.Groups[4].ToString(); } -- cgit v1.1 From 301a926015f0bdc1c99c814f18b7a0505bd59869 Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 22 Oct 2010 13:29:59 +0100 Subject: Change some exception to use ToString(). e.Message is not sufficient to fix errors. Please don't use e.Message, devs NEED to see the dumps! --- OpenSim/Region/Framework/Scenes/Scene.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 4b24ba2..5428e5d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2466,7 +2466,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.WarnFormat("[SCENE]: Problem casting object: {0}", e.Message); + m_log.WarnFormat("[SCENE]: Problem casting object: " + e.ToString()); return false; } @@ -3464,7 +3464,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.DebugFormat("[CONNECTION BEGIN]: Exception verifying presence {0}", e.Message); + m_log.ErrorFormat("[CONNECTION BEGIN]: Exception verifying presence " + e.ToString()); return false; } @@ -3475,7 +3475,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.DebugFormat("[CONNECTION BEGIN]: Exception authorizing user {0}", e.Message); + m_log.ErrorFormat("[CONNECTION BEGIN]: Exception authorizing user " + e.ToString()); return false; } -- cgit v1.1 From c3ddf461880ded2bff0f9ca6bd6b956fbe4c23d5 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 23 Oct 2010 00:18:56 +0200 Subject: Prevent database lookups on every avatar movement when land is set to group access. Fixes a massive performance degradation. --- .../Region/CoreModules/World/Land/LandObject.cs | 28 +++++++--------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index bd1dd66..d0517b7 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -290,28 +290,16 @@ namespace OpenSim.Region.CoreModules.World.Land public bool HasGroupAccess(UUID avatar) { - if ((LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) + if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) { - IGroupsModule groupsModule = - m_scene.RequestModuleInterface(); + ScenePresence sp; + if (!m_scene.TryGetScenePresence(avatar, out sp)) + return false; - List agentGroups = new List(); - if (groupsModule != null) - { - GroupMembershipData[] GroupMembership = - groupsModule.GetMembershipData(avatar); - - if (GroupMembership != null) - { - for (int i = 0; i < GroupMembership.Length; i++) - { - if (LandData.GroupID == GroupMembership[i].GroupID) - { - return true; - } - } - } - } + if (!sp.ControllingClient.IsGroupMember(LandData.GroupID)) + return false; + + return true; } return false; } -- cgit v1.1 From d0c707209abf50902d4fb748138d8a52070ea3ed Mon Sep 17 00:00:00 2001 From: Melanie Date: Sat, 23 Oct 2010 22:40:56 +0100 Subject: Prevent an exception if a string passed into llXorBase64StringsCorrect is not a base 64 string. Return the empty string in this case. --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3249ae2..36ca542 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10145,8 +10145,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (str2 == String.Empty) return str1; - byte[] data1 = Convert.FromBase64String(str1); - byte[] data2 = Convert.FromBase64String(str2); + byte[] data1; + byte[] data2; + try + { + data1 = Convert.FromBase64String(str1); + data2 = Convert.FromBase64String(str2); + } + catch (Exception) + { + return new LSL_String(String.Empty); + } byte[] d2 = new Byte[data1.Length]; int pos = 0; -- cgit v1.1 From 5f266fd57131193a9ff37b03f214aa0476e2e3aa Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 24 Oct 2010 17:18:21 +0200 Subject: Change the results from llGetPrimitiveParams to be the same as SL for the prim position. This will make attached resizer scripts work like SL. Existing resizers may be affected adversely. --- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 0321515..5521326 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1060,7 +1060,7 @@ namespace OpenSim.Region.Framework.Scenes { get { if (IsAttachment) - return GroupPosition; + return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset); // return m_offsetPosition + m_groupPosition; } return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored! diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3249ae2..94d3dee 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -8029,13 +8029,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, part.AbsolutePosition.Y, part.AbsolutePosition.Z); - // For some reason, the part.AbsolutePosition.* values do not change if the - // linkset is rotated; they always reflect the child prim's world position - // as though the linkset is unrotated. This is incompatible behavior with SL's - // implementation, so will break scripts imported from there (not to mention it - // makes it more difficult to determine a child prim's actual inworld position). - if (part.ParentID != 0) - v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition(); res.Add(v); break; -- cgit v1.1 From 61137eac22b222720a24fa248f22b58c439c0560 Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 24 Oct 2010 18:19:48 +0200 Subject: Add PRIM_NAME, PRIM_DESC and PRIM_ROT_LOCAL --- .../Shared/Api/Implementation/LSL_Api.cs | 27 ++++++++++++++++++++++ .../Shared/Api/Runtime/LSL_Constants.cs | 3 +++ 2 files changed, 30 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index db124f7..1b11f2c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -7691,6 +7691,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); break; + case (int)ScriptBaseClass.PRIM_NAME: + if (remain < 1) + return; + string primName = rules.GetLSLStringItem(idx++); + part.Name = primName; + break; + case (int)ScriptBaseClass.PRIM_DESC: + if (remain < 1) + return; + string primDesc = rules.GetLSLStringItem(idx++); + part.Description = primDesc; + break; + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + if (remain < 1) + return; + LSL_Rotation lr = rules.GetQuaternionItem(idx++); + SetRot(part, Rot2Quaternion(lr)); + break; } } } @@ -8373,6 +8391,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api textColor.B)); res.Add(new LSL_Float(textColor.A)); break; + case (int)ScriptBaseClass.PRIM_NAME: + res.Add(part.Name); + break; + case (int)ScriptBaseClass.PRIM_DESC: + res.Add(part.Description); + break; + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); + break; } } return res; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 6e8435d..0342283 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -317,6 +317,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PRIM_POINT_LIGHT = 23; // Huh? public const int PRIM_GLOW = 25; public const int PRIM_TEXT = 26; + public const int PRIM_NAME = 27; + public const int PRIM_DESC = 28; + public const int PRIM_ROT_LOCAL = 29; public const int PRIM_TEXGEN_DEFAULT = 0; public const int PRIM_TEXGEN_PLANAR = 1; -- cgit v1.1 From dd7f9ed7bf3a6776ccdb1efe06a820f51ef6af1e Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 25 Oct 2010 00:33:34 +0200 Subject: Implement llGetLinkNumberOfSides(), needed for 1-script sculptie foot shoe scripts. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 9 +++++++++ OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 1 + OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1b11f2c..2527757 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10777,6 +10777,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return GetLinkPrimitiveParams(obj, rules); } + + public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) + { + List parts = GetLinkParts(link); + if (parts.Count < 1) + return 0; + + return GetNumberOfSides(parts[0]); + } } public class NotecardCache diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 561e3b3..bae7d4b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -398,6 +398,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Vector llWind(LSL_Vector offset); LSL_String llXorBase64Strings(string str1, string str2); LSL_String llXorBase64StringsCorrect(string str1, string str2); + LSL_Integer llGetLinkNumberOfSides(LSL_Integer link); void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index f14967e..7c26824 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -1849,5 +1849,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_LSL_Functions.llClearPrimMedia(face); } + + public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) + { + return m_LSL_Functions.llGetLinkNumberOfSides(link); + } } } -- cgit v1.1 From cf78f3fae311be4aa4c0ab37d2a7c8b6679fb22d Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 25 Oct 2010 00:53:38 +0200 Subject: Comment repeated add and remove of avatars from the physical scene. It's no longer needed. --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 38 ++++++++++++++---------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 618f425..7bf0a99 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2865,22 +2865,28 @@ namespace OpenSim.Region.Framework.Scenes { lock (m_syncRoot) { - if (m_physicsActor != null) - { - if (!IsChildAgent) - { - // This may seem like it's redundant, remove the avatar from the physics scene - // just to add it back again, but it saves us from having to update - // 3 variables 10 times a second. - bool flyingTemp = m_physicsActor.Flying; - RemoveFromPhysicalScene(); - //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor); - - //PhysicsActor = null; - - AddToPhysicalScene(flyingTemp); - } - } +// MT: Commented this because it's no longer needed. +// It used to be that the avatar height was calculated from the visual +// params, so any call to this method could change the physical actor's +// height. Now the height is supplied in the agent circuit data and never +// changes here. So, we can leave physics alone. +// +// if (m_physicsActor != null) +// { +// if (!IsChildAgent) +// { +// // This may seem like it's redundant, remove the avatar from the physics scene +// // just to add it back again, but it saves us from having to update +// // 3 variables 10 times a second. +// bool flyingTemp = m_physicsActor.Flying; +// RemoveFromPhysicalScene(); +// //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor); +// +// //PhysicsActor = null; +// +// AddToPhysicalScene(flyingTemp); +// } +// } #region Bake Cache Check -- cgit v1.1 From a51a545cb9489f3b02ed7a9a7691c5b5dd557bd7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 28 Oct 2010 13:24:45 +0100 Subject: Fix attached sounds from HUDs erroneously being delivered to other avatars --- OpenSim/Region/CoreModules/World/Sound/SoundModule.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index a52fea4..e77062b 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -62,6 +62,12 @@ namespace OpenSim.Region.CoreModules.World.Sound public virtual void PlayAttachedSound( UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) { + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + if (part == null) + return; + + SceneObjectGroup grp = part.ParentGroup; + m_scene.ForEachScenePresence(delegate(ScenePresence sp) { if (sp.IsChildAgent) @@ -71,6 +77,19 @@ namespace OpenSim.Region.CoreModules.World.Sound if (dis > 100.0) // Max audio distance return; + if (grp.IsAttachment) + { + + if (grp.GetAttachmentPoint() > 30) // HUD + { + if (sp.ControllingClient.AgentId != grp.OwnerID) + return; + } + + if (sp.ControllingClient.AgentId == grp.OwnerID) + dis = 0; + } + // Scale by distance if (radius == 0) gain = (float)((double)gain * ((100.0 - dis) / 100.0)); -- cgit v1.1 From e6a8d2872c3ff4992cd7e9615f69e0c6773e461f Mon Sep 17 00:00:00 2001 From: Melanie Date: Fri, 29 Oct 2010 18:59:53 +0200 Subject: Preliminary work on appearance layers. No user functionality yet. --- OpenSim/Framework/AvatarAppearance.cs | 451 +++++++++------------ .../InventoryAccess/InventoryAccessModule.cs | 12 +- .../Shared/Api/Implementation/LSL_Api.cs | 11 +- bin/assets/TexturesAssetSet/TexturesAssetSet.xml | 6 + .../BodyPartsLibrary/BodyPartsLibraryItems.xml | 28 ++ 5 files changed, 243 insertions(+), 265 deletions(-) diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index 5da8ba1..829ad79 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -32,6 +32,125 @@ using OpenMetaverse; namespace OpenSim.Framework { + // A special dictionary for avatar appearance + public struct LayerItem + { + public UUID ItemID; + public UUID AssetID; + + public LayerItem(UUID itemID, UUID assetID) + { + ItemID = itemID; + AssetID = assetID; + } + } + + public class Layer + { + protected int m_layerType; + protected Dictionary m_items = new Dictionary(); + protected List m_ids = new List(); + + public Layer(int type) + { + m_layerType = type; + } + + public int LayerType + { + get { return m_layerType; } + } + + public int Count + { + get { return m_ids.Count; } + } + + public void Add(UUID itemID, UUID assetID) + { + if (m_items.ContainsKey(itemID)) + return; + if (m_ids.Count >= 5) + return; + + m_ids.Add(itemID); + m_items[itemID] = assetID; + } + + public void Wear(UUID itemID, UUID assetID) + { + Clear(); + Add(itemID, assetID); + } + + public void Clear() + { + m_ids.Clear(); + m_items.Clear(); + } + + public void RemoveItem(UUID itemID) + { + if (m_items.ContainsKey(itemID)) + { + m_ids.Remove(itemID); + m_items.Remove(itemID); + } + } + + public void RemoveAsset(UUID assetID) + { + UUID itemID = UUID.Zero; + + foreach (KeyValuePair kvp in m_items) + { + if (kvp.Value == assetID) + { + itemID = kvp.Key; + break; + } + } + + if (itemID != UUID.Zero) + { + m_ids.Remove(itemID); + m_items.Remove(itemID); + } + } + + public LayerItem this [int idx] + { + get + { + if (idx >= m_ids.Count || idx < 0) + return new LayerItem(UUID.Zero, UUID.Zero); + + return new LayerItem(m_ids[idx], m_items[m_ids[idx]]); + } + } + } + + public enum AppearanceLayer + { + BODY = 0, + SKIN = 1, + HAIR = 2, + EYES = 3, + SHIRT = 4, + PANTS = 5, + SHOES = 6, + SOCKS = 7, + JACKET = 8, + GLOVES = 9, + UNDERSHIRT = 10, + UNDERPANTS = 11, + SKIRT = 12, + ALPHA = 13, + TATTOO = 14, + + MAX_WEARABLES = 15 + } + /// /// Contains the Avatar's Appearance and methods to manipulate the appearance. /// @@ -39,25 +158,6 @@ namespace OpenSim.Framework { //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - // these are guessed at by the list here - - // http://wiki.secondlife.com/wiki/Avatar_Appearance. We'll - // correct them over time for when were are wrong. - public readonly static int BODY = 0; - public readonly static int SKIN = 1; - public readonly static int HAIR = 2; - public readonly static int EYES = 3; - public readonly static int SHIRT = 4; - public readonly static int PANTS = 5; - public readonly static int SHOES = 6; - public readonly static int SOCKS = 7; - public readonly static int JACKET = 8; - public readonly static int GLOVES = 9; - public readonly static int UNDERSHIRT = 10; - public readonly static int UNDERPANTS = 11; - public readonly static int SKIRT = 12; - - private readonly static int MAX_WEARABLES = 13; - private static UUID BODY_ASSET = new UUID("66c41e39-38f9-f75a-024e-585989bfab73"); private static UUID BODY_ITEM = new UUID("66c41e39-38f9-f75a-024e-585989bfaba9"); private static UUID SKIN_ASSET = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb"); @@ -68,6 +168,10 @@ namespace OpenSim.Framework private static UUID PANTS_ITEM = new UUID("77c41e39-38f9-f75a-0000-5859892f1111"); private static UUID HAIR_ASSET = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66"); private static UUID HAIR_ITEM = new UUID("d342e6c1-b9d2-11dc-95ff-0800200c9a66"); + private static UUID ALPHA_ASSET = new UUID("1578a2b1-5179-4b53-b618-fe00ca5a5594"); + private static UUID TATTOO_ASSET = new UUID("00000000-0000-2222-3333-100000001007"); + private static UUID ALPHA_ITEM = new UUID("bfb9923c-4838-4d2d-bf07-608c5b1165c8"); + private static UUID TATTOO_ITEM = new UUID("c47e22bd-3021-4ba4-82aa-2b5cb34d35e1"); public readonly static int VISUALPARAM_COUNT = 218; @@ -103,152 +207,156 @@ namespace OpenSim.Framework } public virtual UUID BodyItem { - get { return m_wearables[BODY].ItemID; } - set { m_wearables[BODY].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.BODY].ItemID; } + set { m_wearables[(int)AppearanceLayer.BODY].ItemID = value; } } public virtual UUID BodyAsset { - get { return m_wearables[BODY].AssetID; } - set { m_wearables[BODY].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.BODY].AssetID; } + set { m_wearables[(int)AppearanceLayer.BODY].AssetID = value; } } public virtual UUID SkinItem { - get { return m_wearables[SKIN].ItemID; } - set { m_wearables[SKIN].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.SKIN].ItemID; } + set { m_wearables[(int)AppearanceLayer.SKIN].ItemID = value; } } public virtual UUID SkinAsset { - get { return m_wearables[SKIN].AssetID; } - set { m_wearables[SKIN].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.SKIN].AssetID; } + set { m_wearables[(int)AppearanceLayer.SKIN].AssetID = value; } } public virtual UUID HairItem { - get { return m_wearables[HAIR].ItemID; } - set { m_wearables[HAIR].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.HAIR].ItemID; } + set { m_wearables[(int)AppearanceLayer.HAIR].ItemID = value; } } public virtual UUID HairAsset { - get { return m_wearables[HAIR].AssetID; } - set { m_wearables[HAIR].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.HAIR].AssetID; } + set { m_wearables[(int)AppearanceLayer.HAIR].AssetID = value; } } public virtual UUID EyesItem { - get { return m_wearables[EYES].ItemID; } - set { m_wearables[EYES].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.EYES].ItemID; } + set { m_wearables[(int)AppearanceLayer.EYES].ItemID = value; } } public virtual UUID EyesAsset { - get { return m_wearables[EYES].AssetID; } - set { m_wearables[EYES].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.EYES].AssetID; } + set { m_wearables[(int)AppearanceLayer.EYES].AssetID = value; } } public virtual UUID ShirtItem { - get { return m_wearables[SHIRT].ItemID; } - set { m_wearables[SHIRT].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.SHIRT].ItemID; } + set { m_wearables[(int)AppearanceLayer.SHIRT].ItemID = value; } } public virtual UUID ShirtAsset { - get { return m_wearables[SHIRT].AssetID; } - set { m_wearables[SHIRT].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.SHIRT].AssetID; } + set { m_wearables[(int)AppearanceLayer.SHIRT].AssetID = value; } } public virtual UUID PantsItem { - get { return m_wearables[PANTS].ItemID; } - set { m_wearables[PANTS].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.PANTS].ItemID; } + set { m_wearables[(int)AppearanceLayer.PANTS].ItemID = value; } } public virtual UUID PantsAsset { - get { return m_wearables[PANTS].AssetID; } - set { m_wearables[PANTS].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.PANTS].AssetID; } + set { m_wearables[(int)AppearanceLayer.PANTS].AssetID = value; } } public virtual UUID ShoesItem { - get { return m_wearables[SHOES].ItemID; } - set { m_wearables[SHOES].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.SHOES].ItemID; } + set { m_wearables[(int)AppearanceLayer.SHOES].ItemID = value; } } public virtual UUID ShoesAsset { - get { return m_wearables[SHOES].AssetID; } - set { m_wearables[SHOES].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.SHOES].AssetID; } + set { m_wearables[(int)AppearanceLayer.SHOES].AssetID = value; } } public virtual UUID SocksItem { - get { return m_wearables[SOCKS].ItemID; } - set { m_wearables[SOCKS].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.SOCKS].ItemID; } + set { m_wearables[(int)AppearanceLayer.SOCKS].ItemID = value; } } public virtual UUID SocksAsset { - get { return m_wearables[SOCKS].AssetID; } - set { m_wearables[SOCKS].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.SOCKS].AssetID; } + set { m_wearables[(int)AppearanceLayer.SOCKS].AssetID = value; } } public virtual UUID JacketItem { - get { return m_wearables[JACKET].ItemID; } - set { m_wearables[JACKET].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.JACKET].ItemID; } + set { m_wearables[(int)AppearanceLayer.JACKET].ItemID = value; } } public virtual UUID JacketAsset { - get { return m_wearables[JACKET].AssetID; } - set { m_wearables[JACKET].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.JACKET].AssetID; } + set { m_wearables[(int)AppearanceLayer.JACKET].AssetID = value; } } public virtual UUID GlovesItem { - get { return m_wearables[GLOVES].ItemID; } - set { m_wearables[GLOVES].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.GLOVES].ItemID; } + set { m_wearables[(int)AppearanceLayer.GLOVES].ItemID = value; } } public virtual UUID GlovesAsset { - get { return m_wearables[GLOVES].AssetID; } - set { m_wearables[GLOVES].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.GLOVES].AssetID; } + set { m_wearables[(int)AppearanceLayer.GLOVES].AssetID = value; } } public virtual UUID UnderShirtItem { - get { return m_wearables[UNDERSHIRT].ItemID; } - set { m_wearables[UNDERSHIRT].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.UNDERSHIRT].ItemID; } + set { m_wearables[(int)AppearanceLayer.UNDERSHIRT].ItemID = value; } } public virtual UUID UnderShirtAsset { - get { return m_wearables[UNDERSHIRT].AssetID; } - set { m_wearables[UNDERSHIRT].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.UNDERSHIRT].AssetID; } + set { m_wearables[(int)AppearanceLayer.UNDERSHIRT].AssetID = value; } } public virtual UUID UnderPantsItem { - get { return m_wearables[UNDERPANTS].ItemID; } - set { m_wearables[UNDERPANTS].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.UNDERPANTS].ItemID; } + set { m_wearables[(int)AppearanceLayer.UNDERPANTS].ItemID = value; } } public virtual UUID UnderPantsAsset { - get { return m_wearables[UNDERPANTS].AssetID; } - set { m_wearables[UNDERPANTS].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.UNDERPANTS].AssetID; } + set { m_wearables[(int)AppearanceLayer.UNDERPANTS].AssetID = value; } } public virtual UUID SkirtItem { - get { return m_wearables[SKIRT].ItemID; } - set { m_wearables[SKIRT].ItemID = value; } + get { return m_wearables[(int)AppearanceLayer.SKIRT].ItemID; } + set { m_wearables[(int)AppearanceLayer.SKIRT].ItemID = value; } } public virtual UUID SkirtAsset { - get { return m_wearables[SKIRT].AssetID; } - set { m_wearables[SKIRT].AssetID = value; } + get { return m_wearables[(int)AppearanceLayer.SKIRT].AssetID; } + set { m_wearables[(int)AppearanceLayer.SKIRT].AssetID = value; } } public virtual void SetDefaultWearables() { - m_wearables[BODY].AssetID = BODY_ASSET; - m_wearables[BODY].ItemID = BODY_ITEM; - m_wearables[SKIN].AssetID = SKIN_ASSET; - m_wearables[SKIN].ItemID = SKIN_ITEM; - m_wearables[HAIR].AssetID = HAIR_ASSET; - m_wearables[HAIR].ItemID = HAIR_ITEM; - m_wearables[SHIRT].AssetID = SHIRT_ASSET; - m_wearables[SHIRT].ItemID = SHIRT_ITEM; - m_wearables[PANTS].AssetID = PANTS_ASSET; - m_wearables[PANTS].ItemID = PANTS_ITEM; + m_wearables[(int)AppearanceLayer.BODY].AssetID = BODY_ASSET; + m_wearables[(int)AppearanceLayer.BODY].ItemID = BODY_ITEM; + m_wearables[(int)AppearanceLayer.SKIN].AssetID = SKIN_ASSET; + m_wearables[(int)AppearanceLayer.SKIN].ItemID = SKIN_ITEM; + m_wearables[(int)AppearanceLayer.HAIR].AssetID = HAIR_ASSET; + m_wearables[(int)AppearanceLayer.HAIR].ItemID = HAIR_ITEM; + m_wearables[(int)AppearanceLayer.SHIRT].AssetID = SHIRT_ASSET; + m_wearables[(int)AppearanceLayer.SHIRT].ItemID = SHIRT_ITEM; + m_wearables[(int)AppearanceLayer.PANTS].AssetID = PANTS_ASSET; + m_wearables[(int)AppearanceLayer.PANTS].ItemID = PANTS_ITEM; + m_wearables[(int)AppearanceLayer.ALPHA].AssetID = ALPHA_ASSET; + m_wearables[(int)AppearanceLayer.ALPHA].ItemID = ALPHA_ITEM; + m_wearables[(int)AppearanceLayer.TATTOO].AssetID = TATTOO_ASSET; + m_wearables[(int)AppearanceLayer.TATTOO].ItemID = TATTOO_ITEM; } public virtual void ClearWearables() { - for (int i = 0; i < 13; i++) + for (int i = 0; i < m_wearables.Length ; i++) { m_wearables[i].AssetID = UUID.Zero; m_wearables[i].ItemID = UUID.Zero; @@ -286,70 +394,12 @@ namespace OpenSim.Framework get { return m_hipOffset; } } - //Builds the VisualParam Enum using LIBOMV's Visual Param NameValues - /* - public void BuildVisualParamEnum() - { - Dictionary IndexedParams = new Dictionary(); - int vpIndex = 0; - IndexedParams = new Dictionary(); - - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - - sb.Append("public enum VPElement: int\n"); - sb.Append("{\n"); - foreach (KeyValuePair kvp in OpenMetaverse.VisualParams.Params) - { - VisualParam vp = kvp.Value; - - // Only Group-0 parameters are sent in AgentSetAppearance packets - if (kvp.Value.Group == 0) - { - - if (!IndexedParams.ContainsKey(vp.Name)) - { - - if (vp.Label.Length > 0 || vp.LabelMin.Length > 0 || vp.LabelMax.Length > 0) - { - - sb.Append("/// \n"); - if (vp.LabelMin.Length > 0 && vp.LabelMax.Length > 0) - sb.Append(string.Format("/// {0} - {1} 0--+255 {2}\n", vp.Label, vp.LabelMin, - vp.LabelMax)); - - else - sb.Append(string.Format("/// {0}\n", vp.Label)); - - sb.Append("/// \n"); - } - sb.Append(string.Format(" {0}_{1} = {2}", vp.Wearable.ToUpper(), vp.Name.ToUpper().Replace(" ", "_"),vpIndex)); - - IndexedParams.Add(vp.Name, vpIndex++); - } - else - { - sb.Append(string.Format(" {0}_{1}_{2} = {2}", vp.Wearable.ToUpper(), vp.Name.ToUpper().Replace(" ", "_"), vpIndex)); - vpIndex++; - //int i = 0; - } - } - if (vpIndex < 217) - sb.Append(",\n"); - else - sb.Append("\n"); - - } - sb.Append("}\n"); - - } - */ - public AvatarAppearance() : this(UUID.Zero) {} public AvatarAppearance(UUID owner) { - m_wearables = new AvatarWearable[MAX_WEARABLES]; - for (int i = 0; i < MAX_WEARABLES; i++) + m_wearables = new AvatarWearable[(int)AppearanceLayer.MAX_WEARABLES]; + for (int i = 0; i < (int)AppearanceLayer.MAX_WEARABLES; i++) { // this makes them all null m_wearables[i] = new AvatarWearable(); @@ -442,121 +492,6 @@ namespace OpenSim.Framework return visualParams; } - public override String ToString() - { - String s = "[Wearables] =>"; - s += " Body Item: " + BodyItem.ToString() + ";"; - s += " Skin Item: " + SkinItem.ToString() + ";"; - s += " Shirt Item: " + ShirtItem.ToString() + ";"; - s += " Pants Item: " + PantsItem.ToString() + ";"; - return s; - } - - // this is used for OGS1 - public virtual Hashtable ToHashTable() - { - Hashtable h = new Hashtable(); - h["owner"] = Owner.ToString(); - h["serial"] = Serial.ToString(); - h["visual_params"] = VisualParams; - h["texture"] = Texture.GetBytes(); - h["avatar_height"] = AvatarHeight.ToString(); - h["body_item"] = BodyItem.ToString(); - h["body_asset"] = BodyAsset.ToString(); - h["skin_item"] = SkinItem.ToString(); - h["skin_asset"] = SkinAsset.ToString(); - h["hair_item"] = HairItem.ToString(); - h["hair_asset"] = HairAsset.ToString(); - h["eyes_item"] = EyesItem.ToString(); - h["eyes_asset"] = EyesAsset.ToString(); - h["shirt_item"] = ShirtItem.ToString(); - h["shirt_asset"] = ShirtAsset.ToString(); - h["pants_item"] = PantsItem.ToString(); - h["pants_asset"] = PantsAsset.ToString(); - h["shoes_item"] = ShoesItem.ToString(); - h["shoes_asset"] = ShoesAsset.ToString(); - h["socks_item"] = SocksItem.ToString(); - h["socks_asset"] = SocksAsset.ToString(); - h["jacket_item"] = JacketItem.ToString(); - h["jacket_asset"] = JacketAsset.ToString(); - h["gloves_item"] = GlovesItem.ToString(); - h["gloves_asset"] = GlovesAsset.ToString(); - h["undershirt_item"] = UnderShirtItem.ToString(); - h["undershirt_asset"] = UnderShirtAsset.ToString(); - h["underpants_item"] = UnderPantsItem.ToString(); - h["underpants_asset"] = UnderPantsAsset.ToString(); - h["skirt_item"] = SkirtItem.ToString(); - h["skirt_asset"] = SkirtAsset.ToString(); - - string attachments = GetAttachmentsString(); - if (attachments != String.Empty) - h["attachments"] = attachments; - - return h; - } - - public AvatarAppearance(Hashtable h) - { - Owner = new UUID((string)h["owner"]); - Serial = Convert.ToInt32((string)h["serial"]); - VisualParams = (byte[])h["visual_params"]; - - if (h.Contains("texture")) - { - byte[] te = h["texture"] as byte[]; - if (te != null && te.Length > 0) - Texture = new Primitive.TextureEntry(te, 0, te.Length); - } - else - { - // We shouldn't be receiving appearance hashtables without a TextureEntry, - // but in case we do this will prevent a failure when saving to the database - Texture = GetDefaultTexture(); - } - - - AvatarHeight = (float)Convert.ToDouble((string)h["avatar_height"]); - - m_wearables = new AvatarWearable[MAX_WEARABLES]; - for (int i = 0; i < MAX_WEARABLES; i++) - { - // this makes them all null - m_wearables[i] = new AvatarWearable(); - } - - BodyItem = new UUID((string)h["body_item"]); - BodyAsset = new UUID((string)h["body_asset"]); - SkinItem = new UUID((string)h["skin_item"]); - SkinAsset = new UUID((string)h["skin_asset"]); - HairItem = new UUID((string)h["hair_item"]); - HairAsset = new UUID((string)h["hair_asset"]); - EyesItem = new UUID((string)h["eyes_item"]); - EyesAsset = new UUID((string)h["eyes_asset"]); - ShirtItem = new UUID((string)h["shirt_item"]); - ShirtAsset = new UUID((string)h["shirt_asset"]); - PantsItem = new UUID((string)h["pants_item"]); - PantsAsset = new UUID((string)h["pants_asset"]); - ShoesItem = new UUID((string)h["shoes_item"]); - ShoesAsset = new UUID((string)h["shoes_asset"]); - SocksItem = new UUID((string)h["socks_item"]); - SocksAsset = new UUID((string)h["socks_asset"]); - JacketItem = new UUID((string)h["jacket_item"]); - JacketAsset = new UUID((string)h["jacket_asset"]); - GlovesItem = new UUID((string)h["gloves_item"]); - GlovesAsset = new UUID((string)h["gloves_asset"]); - UnderShirtItem = new UUID((string)h["undershirt_item"]); - UnderShirtAsset = new UUID((string)h["undershirt_asset"]); - UnderPantsItem = new UUID((string)h["underpants_item"]); - UnderPantsAsset = new UUID((string)h["underpants_asset"]); - SkirtItem = new UUID((string)h["skirt_item"]); - SkirtAsset = new UUID((string)h["skirt_asset"]); - - if (h.ContainsKey("attachments")) - { - SetAttachmentsString(h["attachments"].ToString()); - } - } - private Dictionary m_attachments = new Dictionary(); public void SetAttachments(AttachmentData[] data) @@ -1489,4 +1424,4 @@ namespace OpenSim.Framework SKIRT_SKIRT_BLUE = 217 } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index d429979..0700aa5 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -762,10 +762,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // affect the name stored in the serialization, transfer // the correct name from the inventory to the // object itself before we rez. - rootPart.Name = item.Name; - rootPart.Description = item.Description; - rootPart.ObjectSaleType = item.SaleType; - rootPart.SalePrice = item.SalePrice; + // On coalesced objects, this has no effect. + if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) + { + rootPart.Name = item.Name; + rootPart.Description = item.Description; + rootPart.ObjectSaleType = item.SaleType; + rootPart.SalePrice = item.SalePrice; + } group.SetGroup(remoteClient.ActiveGroupId, remoteClient); if ((rootPart.OwnerID != item.Owner) || diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 2527757..8f05359 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2187,9 +2187,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // try to let this work as in SL... - if (m_host.ParentID == 0) - { - // special case: If we are root, rotate complete SOG to new rotation + if (m_host.LinkNum < 2) + { + // Special case: If we are root, rotate complete SOG to new + // rotation. + // We are root if the link number is 0 (single prim) or 1 + // (root prim). ParentID may be nonzero in attachments and + // using it would cause attachments and HUDs to rotate + // to the wrong positions. SetRot(m_host, Rot2Quaternion(rot)); } else diff --git a/bin/assets/TexturesAssetSet/TexturesAssetSet.xml b/bin/assets/TexturesAssetSet/TexturesAssetSet.xml index c5cafa7..7c74a48 100644 --- a/bin/assets/TexturesAssetSet/TexturesAssetSet.xml +++ b/bin/assets/TexturesAssetSet/TexturesAssetSet.xml @@ -1,4 +1,10 @@ +
+ + + + +
diff --git a/bin/inventory/BodyPartsLibrary/BodyPartsLibraryItems.xml b/bin/inventory/BodyPartsLibrary/BodyPartsLibraryItems.xml index aa8d9d9..5cb71c0 100644 --- a/bin/inventory/BodyPartsLibrary/BodyPartsLibraryItems.xml +++ b/bin/inventory/BodyPartsLibrary/BodyPartsLibraryItems.xml @@ -16,6 +16,34 @@
--> + + + + + + */ + + @" + + + + + + + + + + + + + + + + + + + + + + ", m_freeSwitchContext, m_freeSwitchRealm); + } + + return response; } - public Hashtable HandleDialplanRequest(Hashtable requestBody) + public Hashtable HandleDirectoryRequest(Hashtable request) + { + Hashtable response = new Hashtable(); + string domain = (string) request["domain"]; + if (domain != m_freeSwitchRealm) { + response["content_type"] = "text/xml"; + response["keepalive"] = false; + response["int_response_code"] = 200; + response["str_response_string"] = ""; + } else { + m_log.DebugFormat("[FreeSwitchDirectory] HandleDirectoryRequest called with {0}",request.ToString()); + + // information in the request we might be interested in + + // Request 1 sip_auth for users account + + //Event-Calling-Function=sofia_reg_parse_auth + //Event-Calling-Line-Number=1494 + //action=sip_auth + //sip_user_agent=Vivox-SDK-2.1.3010.6151-Mac%20(Feb-11-2009/16%3A42%3A41) + //sip_auth_username=xhZuXKmRpECyr2AARJYyGgg%3D%3D (==) + //sip_auth_realm=9.20.151.43 + //sip_contact_user=xhZuXKmRpECyr2AARJYyGgg%3D%3D (==) + //sip_contact_host=192.168.0.3 // this shouldnt really be a local IP, investigate STUN servers + //sip_to_user=xhZuXKmRpECyr2AARJYyGgg%3D%3D + //sip_to_host=9.20.151.43 + //sip_auth_method=REGISTER + //user=xhZuXKmRpECyr2AARJYyGgg%3D%3D + //domain=9.20.151.43 + //ip=9.167.220.137 // this is the correct IP rather than sip_contact_host above when through a vpn or NAT setup + + foreach (DictionaryEntry item in request) + { + m_log.InfoFormat("[FreeSwitchDirectory] requestBody item {0} {1}", item.Key, item.Value); + } + + string eventCallingFunction = (string) request["Event-Calling-Function"]; + if (eventCallingFunction == null) + { + eventCallingFunction = "sofia_reg_parse_auth"; + } + + if (eventCallingFunction.Length == 0) + { + eventCallingFunction = "sofia_reg_parse_auth"; + } + + if (eventCallingFunction == "sofia_reg_parse_auth") + { + string sipAuthMethod = (string)request["sip_auth_method"]; + + if (sipAuthMethod == "REGISTER") + { + response = HandleRegister(m_freeSwitchContext, m_freeSwitchRealm, request); + } + else if (sipAuthMethod == "INVITE") + { + response = HandleInvite(m_freeSwitchContext, m_freeSwitchRealm, request); + } + else + { + m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown sip_auth_method {0}",sipAuthMethod); + response["int_response_code"] = 404; + response["content_type"] = "text/xml"; + response["str_response_string"] = ""; + } + } + else if (eventCallingFunction == "switch_xml_locate_user") + { + response = HandleLocateUser(m_freeSwitchRealm, request); + } + else if (eventCallingFunction == "user_data_function") // gets called when an avatar to avatar call is made + { + response = HandleLocateUser(m_freeSwitchRealm, request); + } + else if (eventCallingFunction == "user_outgoing_channel") + { + response = HandleRegister(m_freeSwitchContext, m_freeSwitchRealm, request); + } + else if (eventCallingFunction == "config_sofia") // happens once on freeswitch startup + { + response = HandleConfigSofia(m_freeSwitchContext, m_freeSwitchRealm, request); + } + else if (eventCallingFunction == "switch_load_network_lists") + { + //response = HandleLoadNetworkLists(request); + response["int_response_code"] = 404; + response["keepalive"] = false; + response["content_type"] = "text/xml"; + response["str_response_string"] = ""; + } + else + { + m_log.ErrorFormat("[FreeSwitchVoice] HandleDirectoryRequest unknown Event-Calling-Function {0}",eventCallingFunction); + response["int_response_code"] = 404; + response["keepalive"] = false; + response["content_type"] = "text/xml"; + response["str_response_string"] = ""; + } + } + return response; + } + + private Hashtable HandleRegister(string Context, string Realm, Hashtable request) + { + m_log.Info("[FreeSwitchDirectory] HandleRegister called"); + + // TODO the password we return needs to match that sent in the request, this is hard coded for now + string password = "1234"; + string domain = (string) request["domain"]; + string user = (string) request["user"]; + + Hashtable response = new Hashtable(); + response["content_type"] = "text/xml"; + response["keepalive"] = false; + response["int_response_code"] = 200; + + response["str_response_string"] = String.Format( + "\r\n" + + "\r\n" + + "
\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + ""+ + "\r\n" + + "\r\n" + + "\r\n" + + "
\r\n" + + "
\r\n", + domain , user, password, Context); + + return response; + } + + private Hashtable HandleInvite(string Context, string Realm, Hashtable request) + { + m_log.Info("[FreeSwitchDirectory] HandleInvite called"); + + // TODO the password we return needs to match that sent in the request, this is hard coded for now + string password = "1234"; + string domain = (string) request["domain"]; + string user = (string) request["user"]; + string sipRequestUser = (string) request["sip_request_user"]; + + Hashtable response = new Hashtable(); + response["content_type"] = "text/xml"; + response["keepalive"] = false; + response["int_response_code"] = 200; + response["str_response_string"] = String.Format( + "\r\n" + + "\r\n" + + "
\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + ""+ + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + ""+ + "\r\n" + + "\r\n" + + "\r\n" + + "
\r\n" + + "
\r\n", + domain , user, password,sipRequestUser, Context); + + return response; + } + + private Hashtable HandleLocateUser(String Realm, Hashtable request) + { + m_log.Info("[FreeSwitchDirectory] HandleLocateUser called"); + + // TODO the password we return needs to match that sent in the request, this is hard coded for now + string domain = (string) request["domain"]; + string user = (string) request["user"]; + + Hashtable response = new Hashtable(); + response["content_type"] = "text/xml"; + response["keepalive"] = false; + response["int_response_code"] = 200; + response["str_response_string"] = String.Format( + "\r\n" + + "\r\n" + + "
\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n"+ + "\r\n"+ + ""+ + "\r\n"+ + "\r\n" + + "\r\n" + + "
\r\n" + + "
\r\n", + domain , user); + + return response; + } + + private Hashtable HandleConfigSofia(string Context, string Realm, Hashtable request) { - return new Hashtable(); + m_log.Info("[FreeSwitchDirectory] HandleConfigSofia called"); + + // TODO the password we return needs to match that sent in the request, this is hard coded for now + string domain = (string) request["domain"]; + + Hashtable response = new Hashtable(); + response["content_type"] = "text/xml"; + response["keepalive"] = false; + response["int_response_code"] = 200; + response["str_response_string"] = String.Format( + "\r\n" + + "\r\n" + + "
\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n" + + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n"+ + ""+ + "\r\n" + + "\r\n"+ + "\r\n"+ + "\r\n"+ + "\r\n" + + "
\r\n" + + "
\r\n", + domain, Context); + + return response; } } } -- cgit v1.1 From 5f8a0f3d1f4cd9948ced87e312bcd0c4a616ef2a Mon Sep 17 00:00:00 2001 From: Melanie Date: Sun, 21 Nov 2010 23:41:56 +0000 Subject: Add the remote connector for freeswitch config retrieval --- .../Freeswitch/RemoteFreeswitchConnector.cs | 103 +++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs diff --git a/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs new file mode 100644 index 0000000..d63d99d --- /dev/null +++ b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs @@ -0,0 +1,103 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using log4net; +using System; +using System.IO; +using System.Collections; +using System.Reflection; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Services.Interfaces; +using OpenSim.Server.Base; +using OpenMetaverse; + +namespace OpenSim.Services.Connectors +{ + public class RemoteFreeswitchConnector : IFreeswitchService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_ServerURI = String.Empty; + + public RemoteFreeswitchConnector() + { + } + + public RemoteFreeswitchConnector(string serverURI) + { + m_ServerURI = Path.Combine(serverURI.TrimEnd('/'), "region-config"); + } + + public RemoteFreeswitchConnector(IConfigSource source) + { + Initialise(source); + } + + public virtual void Initialise(IConfigSource source) + { + IConfig freeswitchConfig = source.Configs["FreeSwitchVoice"]; + if (freeswitchConfig == null) + { + m_log.Error("[FREESWITCH CONNECTOR]: FreeSwitchVoice missing from OpenSim.ini"); + throw new Exception("Freeswitch connector init error"); + } + + string serviceURI = freeswitchConfig.GetString("FreeswitchServiceURL", + String.Empty); + + if (serviceURI == String.Empty) + { + m_log.Error("[FREESWITCH CONNECTOR]: No FreeswitchServiceURL named in section FreeSwitchVoice"); + throw new Exception("Freeswitch connector init error"); + } + m_ServerURI = serviceURI; + } + + public Hashtable HandleDirectoryRequest(Hashtable requestBody) + { + // not used here + return new Hashtable(); + } + + public Hashtable HandleDialplanRequest(Hashtable requestBody) + { + // not used here + return new Hashtable(); + } + + public string GetJsonConfig() + { + return SynchronousRestFormsRequester.MakeRequest("GET", + m_ServerURI, String.Empty); + } + } +} -- cgit v1.1 From 7e9a3019ac719b88defd69bded0f9b801194fe85 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 22 Nov 2010 00:55:11 +0100 Subject: Fox the buglets in Freeswitch. Grid mode works now and there is no reason why standalone should not. --- .../Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 1 + OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index a5e553c..294d4f0 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -134,6 +134,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice m_FreeswitchService = ServerUtils.LoadPlugin(serviceDll, args); string jsonConfig = m_FreeswitchService.GetJsonConfig(); + m_log.Debug("[FreeSwitchVoice]: Configuration string: " + jsonConfig); OSDMap map = (OSDMap)OSDParser.DeserializeJson(jsonConfig); m_freeSwitchAPIPrefix = map["APIPrefix"].AsString(); diff --git a/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs index d63d99d..c9bba0b 100644 --- a/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs +++ b/OpenSim/Services/Connectors/Freeswitch/RemoteFreeswitchConnector.cs @@ -54,7 +54,7 @@ namespace OpenSim.Services.Connectors public RemoteFreeswitchConnector(string serverURI) { - m_ServerURI = Path.Combine(serverURI.TrimEnd('/'), "region-config"); + m_ServerURI = serverURI.TrimEnd('/') + "/region-config"; } public RemoteFreeswitchConnector(IConfigSource source) @@ -79,7 +79,7 @@ namespace OpenSim.Services.Connectors m_log.Error("[FREESWITCH CONNECTOR]: No FreeswitchServiceURL named in section FreeSwitchVoice"); throw new Exception("Freeswitch connector init error"); } - m_ServerURI = serviceURI; + m_ServerURI = serviceURI.TrimEnd('/') + "/region-config"; } public Hashtable HandleDirectoryRequest(Hashtable requestBody) @@ -96,6 +96,7 @@ namespace OpenSim.Services.Connectors public string GetJsonConfig() { + m_log.DebugFormat("[FREESWITCH CONNECTOR]: Requesting config from {0}", m_ServerURI); return SynchronousRestFormsRequester.MakeRequest("GET", m_ServerURI, String.Empty); } -- cgit v1.1 From 54d1d6d917e565e1e5f7ba39f7b2cfbdf199a260 Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 22 Nov 2010 14:32:51 +0100 Subject: Fox case on a method --- .../Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index 9a17233..a583cca 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -603,7 +603,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice response["str_response_string"] = string.Empty; response["content-type"] = "text/xml"; - Hashtable requestBody = parseRequestBody((string)request["body"]); + Hashtable requestBody = ParseRequestBody((string)request["body"]); if (!requestBody.ContainsKey("auth_token")) return response; @@ -675,7 +675,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice string uri = (string)request["uri"]; string contenttype = (string)request["content-type"]; - Hashtable requestBody = parseRequestBody((string)request["body"]); + Hashtable requestBody = ParseRequestBody((string)request["body"]); //string pwd = (string) requestBody["pwd"]; string userid = (string) requestBody["userid"]; @@ -719,7 +719,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice return response; } - public Hashtable parseRequestBody(string body) + public Hashtable ParseRequestBody(string body) { Hashtable bodyParams = new Hashtable(); // split string -- cgit v1.1 From 506192e4663456d1d35976cc854e2a675660463a Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 22 Nov 2010 15:16:28 +0100 Subject: Make an invalud key string in llTextBox and llDialog non fatal to avoid breakinf sloppily made no-mod scripted items. --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index dee0d9a..1ba28dc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4469,7 +4469,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID av = new UUID(); if (!UUID.TryParse(agent,out av)) { - LSLError("First parameter to llDialog needs to be a key"); + //LSLError("First parameter to llDialog needs to be a key"); return; } @@ -6731,7 +6731,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID av = new UUID(); if (!UUID.TryParse(avatar,out av)) { - LSLError("First parameter to llDialog needs to be a key"); + //LSLError("First parameter to llDialog needs to be a key"); return; } if (buttons.Length < 1) -- cgit v1.1 From 571becefb652869fa844188cadf8aca1fea774ab Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 22 Nov 2010 23:31:29 +0100 Subject: Fix some crashes caused by the addition of the CreatorData column --- OpenSim/Framework/Capabilities/Caps.cs | 1 + OpenSim/Framework/TaskInventoryDictionary.cs | 1 + .../InventoryAccess/InventoryAccessModule.cs | 6 ++++++ .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 19 ++++++++++++++++++- .../Connectors/Inventory/XInventoryConnector.cs | 9 ++++++++- 5 files changed, 34 insertions(+), 2 deletions(-) diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs index 7b0e053..e7f2e13 100644 --- a/OpenSim/Framework/Capabilities/Caps.cs +++ b/OpenSim/Framework/Capabilities/Caps.cs @@ -967,6 +967,7 @@ namespace OpenSim.Framework.Capabilities InventoryItemBase item = new InventoryItemBase(); item.Owner = m_agentID; item.CreatorId = m_agentID.ToString(); + item.CreatorData = String.Empty; item.ID = inventoryItem; item.AssetID = asset.FullID; item.Description = assetDescription; diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index a8a53f2..940e567 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs @@ -151,6 +151,7 @@ namespace OpenSim.Framework while (!m_itemLock.TryEnterWriteLock(60000)) { m_log.Error("Thread lock detected while trying to aquire WRITE lock in TaskInventoryDictionary. Locked by thread " + LockedByThread.Name + ". I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed."); + System.Console.WriteLine("My call stack:\n" + Environment.StackTrace); if (m_itemLock.IsWriteLockHeld) { m_itemLock = new System.Threading.ReaderWriterLockSlim(); diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 2e3db48..22da665 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -436,9 +436,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess item = new InventoryItemBase(); // Can't know creator is the same, so null it in inventory if (objlist.Count > 1) + { item.CreatorId = UUID.Zero.ToString(); + item.CreatorData = String.Empty; + } else + { item.CreatorId = objlist[0].RootPart.CreatorID.ToString(); + item.CreatorData = objlist[0].RootPart.CreatorData; + } item.ID = UUID.Random(); item.InvType = (int)InventoryType.Object; item.Folder = folder.ID; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1ba28dc..7e9224d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10177,6 +10177,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (str2 == String.Empty) return str1; + int len = str2.Length; + if ((len % 4) != 0) // LL is EVIL!!!! + { + while (str2.EndsWith("=")) + str2 = str2.Substring(0, str2.Length - 1); + + len = str2.Length; + int mod = len % 4; + + if (mod == 1) + str2 = str2.Substring(0, str2.Length - 1); + else if (mod == 2) + str2 += "=="; + else if (mod == 3) + str2 += "="; + } + byte[] data1; byte[] data2; try @@ -10200,7 +10217,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { while (pos < data1.Length) { - int len = data1.Length - pos; + len = data1.Length - pos; if (len > data2.Length) len = data2.Length; diff --git a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs index 88fbda3..b3bfcc2 100644 --- a/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs +++ b/OpenSim/Services/Connectors/Inventory/XInventoryConnector.cs @@ -302,6 +302,8 @@ namespace OpenSim.Services.Connectors public bool AddItem(InventoryItemBase item) { + if (item.CreatorData == null) + item.CreatorData = String.Empty; Dictionary ret = MakeRequest("ADDITEM", new Dictionary { { "AssetID", item.AssetID.ToString() }, @@ -335,6 +337,8 @@ namespace OpenSim.Services.Connectors public bool UpdateItem(InventoryItemBase item) { + if (item.CreatorData == null) + item.CreatorData = String.Empty; Dictionary ret = MakeRequest("UPDATEITEM", new Dictionary { { "AssetID", item.AssetID.ToString() }, @@ -558,7 +562,10 @@ namespace OpenSim.Services.Connectors item.InvType = int.Parse(data["InvType"].ToString()); item.Folder = new UUID(data["Folder"].ToString()); item.CreatorId = data["CreatorId"].ToString(); - item.CreatorData = data["CreatorData"].ToString(); + if (data.ContainsKey("CreatorData")) + item.CreatorData = data["CreatorData"].ToString(); + else + item.CreatorData = String.Empty; item.Description = data["Description"].ToString(); item.NextPermissions = uint.Parse(data["NextPermissions"].ToString()); item.CurrentPermissions = uint.Parse(data["CurrentPermissions"].ToString()); -- cgit v1.1 From 4a54b3318b202d75bde2f1fcde3e80114df91d2e Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 23 Nov 2010 00:31:09 +0100 Subject: Fix more potential nullrefs --- OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index 456b6fc..ce72c78 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -601,8 +601,10 @@ namespace OpenSim.Server.Handlers.Asset ret["AssetType"] = item.AssetType.ToString(); ret["BasePermissions"] = item.BasePermissions.ToString(); ret["CreationDate"] = item.CreationDate.ToString(); - ret["CreatorId"] = item.CreatorId.ToString(); - ret["CreatorData"] = item.CreatorData.ToString(); + if (item.CreatorId != null) + ret["CreatorId"] = item.CreatorId.ToString(); + else + ret["CreatorId"] = String.Empty; ret["CurrentPermissions"] = item.CurrentPermissions.ToString(); ret["Description"] = item.Description.ToString(); ret["EveryOnePermissions"] = item.EveryOnePermissions.ToString(); -- cgit v1.1 From a47fb93b7419c08549b27dc0d5c27896ecf744c7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Tue, 23 Nov 2010 23:48:52 +0100 Subject: Prevent a dump in the llGetLinkKey method when using LINK_ROOT in a single prim --- OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 7e9224d..ec4d815 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4007,6 +4007,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { linknum -= (m_host.ParentGroup.PrimCount) + 1; + if (linknum < 0) + return UUID.Zero.ToString(); + List avatars = GetLinkAvatars(ScriptBaseClass.LINK_SET); if (avatars.Count > linknum) { -- cgit v1.1 From b3a71c6df1538c61247f7d4711aba4c840508db8 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 24 Nov 2010 18:56:25 +0100 Subject: Prevent an overlength button label from producing a debug dump and aborting the script. --- OpenSim/Framework/AgentCircuitData.cs | 35 ++-- OpenSim/Framework/ChildAgentDataUpdate.cs | 10 +- .../Avatar/AvatarFactory/AvatarFactoryModule.cs | 30 +-- .../EntityTransfer/EntityTransferModule.cs | 4 +- .../Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2 +- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 233 +++++++++++---------- .../Avatar/XmlRpcGroups/GroupsModule.cs | 9 +- .../Shared/Api/Implementation/LSL_Api.cs | 6 +- 9 files changed, 155 insertions(+), 176 deletions(-) diff --git a/OpenSim/Framework/AgentCircuitData.cs b/OpenSim/Framework/AgentCircuitData.cs index cc9fcea..1600bdc 100644 --- a/OpenSim/Framework/AgentCircuitData.cs +++ b/OpenSim/Framework/AgentCircuitData.cs @@ -302,31 +302,26 @@ namespace OpenSim.Framework if (args["start_pos"] != null) Vector3.TryParse(args["start_pos"].AsString(), out startpos); -// DEBUG ON - m_log.WarnFormat("[AGENTCIRCUITDATA] agentid={0}, child={1}, startpos={2}",AgentID,child,startpos.ToString()); -// DEBUG OFF + m_log.InfoFormat("[AGENTCIRCUITDATA] agentid={0}, child={1}, startpos={2}",AgentID,child,startpos.ToString()); try { - // Unpack various appearance elements - Appearance = new AvatarAppearance(AgentID); + // Unpack various appearance elements + Appearance = new AvatarAppearance(AgentID); - // Eventually this code should be deprecated, use full appearance - // packing in packed_appearance - if (args["appearance_serial"] != null) - Appearance.Serial = args["appearance_serial"].AsInteger(); + // Eventually this code should be deprecated, use full appearance + // packing in packed_appearance + if (args["appearance_serial"] != null) + Appearance.Serial = args["appearance_serial"].AsInteger(); - if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map)) - { - Appearance.Unpack((OSDMap)args["packed_appearance"]); -// DEBUG ON - m_log.WarnFormat("[AGENTCIRCUITDATA] unpacked appearance"); -// DEBUG OFF + if (args.ContainsKey("packed_appearance") && (args["packed_appearance"].Type == OSDType.Map)) + { + Appearance.Unpack((OSDMap)args["packed_appearance"]); + m_log.InfoFormat("[AGENTCIRCUITDATA] unpacked appearance"); + } + else + m_log.Warn("[AGENTCIRCUITDATA] failed to find a valid packed_appearance"); } -// DEBUG ON - else - m_log.Warn("[AGENTCIRCUITDATA] failed to find a valid packed_appearance"); -// DEBUG OFF - } catch (Exception e) + catch (Exception e) { m_log.ErrorFormat("[AGENTCIRCUITDATA] failed to unpack appearance; {0}",e.Message); } diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index a227338..ce0b2fb 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -331,9 +331,7 @@ namespace OpenSim.Framework public virtual OSDMap Pack() { -// DEBUG ON - m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Pack data"); -// DEBUG OFF + m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Pack data"); OSDMap args = new OSDMap(); args["message_type"] = OSD.FromString("AgentData"); @@ -454,9 +452,7 @@ namespace OpenSim.Framework /// public virtual void Unpack(OSDMap args) { -// DEBUG ON - m_log.WarnFormat("[CHILDAGENTDATAUPDATE] Unpack data"); -// DEBUG OFF + m_log.InfoFormat("[CHILDAGENTDATAUPDATE] Unpack data"); if (args.ContainsKey("region_id")) UUID.TryParse(args["region_id"].AsString(), out RegionID); @@ -613,10 +609,8 @@ namespace OpenSim.Framework if (args.ContainsKey("packed_appearance") && (args["packed_appearance"]).Type == OSDType.Map) Appearance = new AvatarAppearance(AgentID,(OSDMap)args["packed_appearance"]); -// DEBUG ON else m_log.WarnFormat("[CHILDAGENTDATAUPDATE] No packed appearance"); -// DEBUG OFF if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) { diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 0df4585..ab1c206 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -183,7 +183,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory }); } - // m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); + m_log.WarnFormat("[AVFACTORY]: Complete texture check for {0}",client.AgentId); } // Process the visual params, this may change height as well @@ -196,12 +196,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory sp.SetHeight(sp.Appearance.AvatarHeight); } } - - // Send the appearance back to the avatar, not clear that this is needed - sp.ControllingClient.SendAvatarDataImmediate(sp); - // AvatarAppearance avp = sp.Appearance; - // sp.ControllingClient.SendAppearance(avp.Owner,avp.VisualParams,avp.Texture.GetBytes()); - } @@ -274,21 +268,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Send the appearance to everyone in the scene sp.SendAppearanceToAllOtherAgents(); - // sp.ControllingClient.SendAvatarDataImmediate(sp); - - // Send the appearance back to the avatar - // AvatarAppearance avp = sp.Appearance; - // sp.ControllingClient.SendAppearance(avp.Owner, avp.VisualParams, avp.Texture.GetBytes()); - -/* -// this needs to be fixed, the flag should be on scene presence not the region module - // Start the animations if necessary - if (!m_startAnimationSet) - { - sp.Animator.UpdateMovementAnimations(); - m_startAnimationSet = true; - } -*/ } private void HandleAppearanceSave(UUID agentid) @@ -374,6 +353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // m_log.WarnFormat("[AVFACTORY]: AvatarIsWearing called for {0}", client.AgentId); + // operate on a copy of the appearance so we don't have to lock anything AvatarAppearance avatAppearance = new AvatarAppearance(sp.Appearance, false); foreach (AvatarWearingArgs.Wearable wear in e.NowWearing) @@ -388,9 +368,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory SetAppearanceAssets(sp.UUID, ref avatAppearance); // could get fancier with the locks here, but in the spirit of "last write wins" - // this should work correctly + // this should work correctly, also, we don't need to send the appearance here + // since the "iswearing" will trigger a new set of visual param and baked texture changes + // when those complete, the new appearance will be sent sp.Appearance = avatAppearance; - m_scene.AvatarService.SetAppearance(client.AgentId, sp.Appearance); + QueueAppearanceSave(client.AgentId); } private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 81d6f70..aa7a1cd 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -925,8 +925,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } agent.MakeChildAgent(); + // now we have a child agent in this region. Request all interesting data about other (root) agents - agent.SendInitialFullUpdateToAllClients(); + agent.SendOtherAgentsAvatarDataToMe(); + agent.SendOtherAgentsAppearanceToMe(); CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f3964c2..bcb715b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -398,7 +398,7 @@ namespace OpenSim.Region.Framework.Scenes Vector3 offset = p.GetWorldPosition() - av.ParentPosition; av.AbsolutePosition += offset; av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition - av.SendFullUpdateToAllClients(); + av.SendAvatarDataToAllAgents(); } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index bdd42fc..8cc2be1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -803,7 +803,7 @@ namespace OpenSim.Region.Framework.Scenes { Vector3 offset = (m_offsetPosition - oldpos); av.OffsetPosition += offset; - av.SendFullUpdateToAllClients(); + av.SendAvatarDataToAllAgents(); } } } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index c35df08..98a3b29 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -767,7 +767,9 @@ namespace OpenSim.Region.Framework.Scenes // Note: This won't send data *to* other clients in that region (children don't send) // MIC: This gets called again in CompleteMovement - SendInitialFullUpdateToAllClients(); + // SendInitialFullUpdateToAllClients(); + SendOtherAgentsAvatarDataToMe(); + SendOtherAgentsAppearanceToMe(); RegisterToEvents(); SetDirectionVectors(); @@ -1757,7 +1759,7 @@ namespace OpenSim.Region.Framework.Scenes { AbsolutePosition = part.AbsolutePosition; Velocity = Vector3.Zero; - SendFullUpdateToAllClients(); + SendAvatarDataToAllAgents(); HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ?? } @@ -1867,7 +1869,7 @@ namespace OpenSim.Region.Framework.Scenes m_parentID = 0; m_linkedPrim = UUID.Zero; m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f); - SendFullUpdateToAllClients(); + SendAvatarDataToAllAgents(); m_requestedSitTargetID = 0; if (m_physicsActor != null && m_appearance != null) { @@ -2462,8 +2464,8 @@ namespace OpenSim.Region.Framework.Scenes Velocity = Vector3.Zero; RemoveFromPhysicalScene(); Animator.TrySetMovementAnimation(sitAnimation); - SendFullUpdateToAllClients(); - SendTerseUpdateToAllClients(); + SendAvatarDataToAllAgents(); + //SendTerseUpdateToAllClients(); } public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal) @@ -2742,165 +2744,169 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar) + /// Do everything required once a client completes its movement into a region and becomes + /// a root agent. /// - /// - public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar) + private void SendInitialData() { - // 2 stage check is needed. - if (remoteAvatar == null) - return; + // Moved this into CompleteMovement to ensure that m_appearance is initialized before + // the inventory arrives + // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); - IClientAPI cl = remoteAvatar.ControllingClient; - if (cl == null) - return; + // This agent just became root. We are going to tell everyone about it. The process of + // getting other avatars information was initiated in the constructor... don't do it + // again here... + SendAvatarDataToAllAgents(); - if (m_appearance.Texture == null) - return; - -// MT: This is needed for sit. It's legal to send it to oneself, and the name -// of the method is a misnomer -// -// if (LocalId == remoteAvatar.LocalId) -// { -// m_log.WarnFormat("[SCENEPRESENCE]: An agent is attempting to send avatar data to itself; {0}", UUID); -// return; -// } + // We have an appearance but we may not have the baked textures. Check the asset cache + // to see if all the baked textures are already here. + if (m_scene.AvatarFactory != null) + { + if (m_scene.AvatarFactory.ValidateBakedTextureCache(m_controllingClient)) + { +// m_log.WarnFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); + SendAppearanceToAgent(this); - if (IsChildAgent) + // If the avatars baked textures are all in the cache, then we have a + // complete appearance... send it out, if not, then we'll send it when + // the avatar finishes updating its appearance + SendAppearanceToAllOtherAgents(); + } + } + else { - m_log.WarnFormat("[SCENEPRESENCE]: A child agent is attempting to send out avatar data; {0}", UUID); - return; + m_log.WarnFormat("[SCENEPRESENCE]: AvatarFactory not set for {0}", Name); } - - remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this); - m_scene.StatsReporter.AddAgentUpdates(1); } /// - /// Tell *ALL* agents about this agent + /// Send this agent's avatar data to all other root and child agents in the scene + /// This agent must be root. This avatar will receive its own update. /// - public void SendInitialFullUpdateToAllClients() + public void SendAvatarDataToAllAgents() { - m_perfMonMS = Util.EnvironmentTickCount(); - int avUpdates = 0; - m_scene.ForEachScenePresence(delegate(ScenePresence avatar) + // only send update from root agents to other clients; children are only "listening posts" + if (IsChildAgent) { - ++avUpdates; - - // Don't update ourselves - if (avatar.LocalId == LocalId) - return; - - // If this is a root agent, then get info about the avatar - if (!IsChildAgent) - { - SendFullUpdateToOtherClient(avatar); - } + m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent"); + return; + } + + m_perfMonMS = Util.EnvironmentTickCount(); - // If the other avatar is a root - if (!avatar.IsChildAgent) - { - avatar.SendFullUpdateToOtherClient(this); - avatar.SendAppearanceToOtherAgent(this); - avatar.Animator.SendAnimPackToClient(ControllingClient); - } - }); + int count = 0; + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + SendAvatarDataToAgent(scenePresence); + count++; + }); - m_scene.StatsReporter.AddAgentUpdates(avUpdates); + m_scene.StatsReporter.AddAgentUpdates(count); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - - //Animator.SendAnimPack(); } - public void SendFullUpdateToAllClients() + /// + /// Send avatar data for all other root agents to this agent, this agent + /// can be either a child or root + /// + public void SendOtherAgentsAvatarDataToMe() { m_perfMonMS = Util.EnvironmentTickCount(); - // only send update from root agents to other clients; children are only "listening posts" - if (IsChildAgent) - { - m_log.Warn("[SCENEPRESENCE] attempt to send update from a childagent"); - return; - } - int count = 0; - m_scene.ForEachScenePresence(delegate(ScenePresence sp) - { - if (sp.IsChildAgent) - return; - SendFullUpdateToOtherClient(sp); - ++count; - }); + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + // only send information about root agents + if (scenePresence.IsChildAgent) + return; + + // only send information about other root agents + if (scenePresence.UUID == UUID) + return; + + scenePresence.SendAvatarDataToAgent(this); + count++; + }); + m_scene.StatsReporter.AddAgentUpdates(count); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); - - Animator.SendAnimPack(); } /// - /// Do everything required once a client completes its movement into a region + /// Send avatar data to an agent. /// - public void SendInitialData() + /// + private void SendAvatarDataToAgent(ScenePresence avatar) { - // Moved this into CompleteMovement to ensure that m_appearance is initialized before - // the inventory arrives - // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance); +// m_log.WarnFormat("[SP] Send avatar data from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); - m_controllingClient.SendAvatarDataImmediate(this); - if (m_scene.AvatarFactory != null) - { - if (m_scene.AvatarFactory.ValidateBakedTextureCache(m_controllingClient)) - { -// m_log.WarnFormat("[SCENEPRESENCE]: baked textures are in the cache for {0}", Name); - m_controllingClient.SendAppearance( - m_appearance.Owner,m_appearance.VisualParams,m_appearance.Texture.GetBytes()); - } - } - else + avatar.ControllingClient.SendAvatarDataImmediate(this); + Animator.SendAnimPackToClient(avatar.ControllingClient); + } + + /// + /// Send this agent's appearance to all other root and child agents in the scene + /// This agent must be root. + /// + public void SendAppearanceToAllOtherAgents() + { + // only send update from root agents to other clients; children are only "listening posts" + if (IsChildAgent) { - m_log.WarnFormat("[SCENEPRESENCE]: AvatarFactory not set for {0}", Name); + m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent"); + return; } + + m_perfMonMS = Util.EnvironmentTickCount(); + + int count = 0; + m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) + { + if (scenePresence.UUID == UUID) + return; - SendInitialFullUpdateToAllClients(); + SendAppearanceToAgent(scenePresence); + count++; + }); + + m_scene.StatsReporter.AddAgentUpdates(count); + m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); } /// - /// + /// Send appearance from all other root agents to this agent. this agent + /// can be either root or child /// - public void SendAppearanceToAllOtherAgents() + public void SendOtherAgentsAppearanceToMe() { -// DEBUG ON -// m_log.WarnFormat("[SCENEPRESENCE]: Send appearance from {0} to all other agents", m_uuid); -// DEBUG OFF m_perfMonMS = Util.EnvironmentTickCount(); + int count = 0; m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) { - if (scenePresence.UUID != UUID) - { - SendAppearanceToOtherAgent(scenePresence); - } + // only send information about root agents + if (scenePresence.IsChildAgent) + return; + + // only send information about other root agents + if (scenePresence.UUID == UUID) + return; + + scenePresence.SendAppearanceToAgent(this); + count++; }); + m_scene.StatsReporter.AddAgentUpdates(count); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); } /// - /// Send appearance data to an agent that isn't this one. + /// Send appearance data to an agent. /// /// - public void SendAppearanceToOtherAgent(ScenePresence avatar) + private void SendAppearanceToAgent(ScenePresence avatar) { - if (LocalId == avatar.LocalId) - { - m_log.WarnFormat("[SCENE PRESENCE]: An agent is attempting to send appearance data to itself; {0}", UUID); - return; - } - -// DEBUG ON // m_log.WarnFormat("[SP] Send appearance from {0} to {1}",m_uuid,avatar.ControllingClient.AgentId); -// DEBUG OFF avatar.ControllingClient.SendAppearance( m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes()); @@ -3413,9 +3419,6 @@ namespace OpenSim.Region.Framework.Scenes public void CopyFrom(AgentData cAgent) { -// DEBUG ON - m_log.ErrorFormat("[SCENEPRESENCE] CALLING COPYFROM"); -// DEBUG OFF m_originRegionID = cAgent.RegionID; m_callbackURI = cAgent.CallbackURI; diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 0c8113e..ccf5289 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -1173,10 +1173,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups presence = scene.GetScenePresence(AgentID); if (presence != null) { - presence.Grouptitle = Title; + if (presence.Grouptitle != Title) + { + presence.Grouptitle = Title; - // FixMe: Ter suggests a "Schedule" method that I can't find. - presence.SendFullUpdateToAllClients(); + if (! presence.IsChildAgent) + presence.SendAvatarDataToAllAgents(); + } } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index ec4d815..1dd4ca4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6756,7 +6756,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } if (buttons.Data[i].ToString().Length > 24) { - LSLError("button label cannot be longer than 24 characters"); + llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters"); return; } buts[i] = buttons.Data[i].ToString(); @@ -7319,7 +7319,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector v; v = rules.GetVector3Item(idx++); av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); - av.SendFullUpdateToAllClients(); + av.SendAvatarDataToAllAgents(); break; @@ -7329,7 +7329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Rotation r; r = rules.GetQuaternionItem(idx++); av.OffsetRotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); - av.SendFullUpdateToAllClients(); + av.SendAvatarDataToAllAgents(); break; } } -- cgit v1.1 From 152256792084639f67ec085fe4d19abb95b68e1d Mon Sep 17 00:00:00 2001 From: Melanie Date: Thu, 25 Nov 2010 02:37:50 +0100 Subject: Finish the RestartModule and fix some bugs. Add new console commands: region restart bluebox